Dashboard > GridGain User Guide > Table Of Contents > Examples Gallery > HelloWorld - Gridify With Failover
HelloWorld - Gridify With Failover
Added by architect, last edited by morpheus on Mar 07, 2008  (view change)
Labels: 
(None)


Gridify With Failover

This example contains HelloWorld example that is using Gridify Javadoc annotation to grid-enable Java logic and also provides custom split and aggregate logic by deploying a custom task. This example also shows basic example usage of grid job failover.

String 'Hello World' is passed as an argument to GridifyHelloWorldFailoverExample.sayIt(String) method. Since this method is annotated with @Gridify Javadoc annotation it is automatically grid-enabled. The GridifyHelloWorldFailoverTask task responsible for split and reduce logic will do the following:

  1. Set session attribute 'fail=true'.
  2. Pass the passed in string as an argument into remote job for execution.
  3. The job will check the value of 'fail' attribute. If it is true, then it will set it to false and throw exception to simulate a failure. If it is false, then it will execute the grid-enabled method.

Note that when job throws an exception it will be treated as a failure by GridifyHelloWorldFailoverTask.result(GridJobResult, List) method which will return GridJobResultPolicy.FAILOVER Javadoc policy. This will cause the job to automatically failover to another node for execution. The new job will simply print out the argument passed in.

The possible outcome will look as following:

Node 1 (failure occured on this node)

Exception:
----------
>>> Type: org.gridgain.grid.GridException
>>> Message: Example job exception.
>>> Documentation: http://www.gridgain.com/product.html
>>> Stack trace:
>>> at org.gridgain.examples.helloworld.gridify.failover.GridifyHelloWorldFailoverTask$1.execute(GridifyHelloWorldFailoverTask.java:57)
>>> at org.gridgain.grid.kernal.GridJobWorker.body(GridJobWorker.java:285)
>>> at org.gridgain.grid.util.runnable.GridRunnable$1.run(GridRunnable.java:125)
>>> at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
>>> at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)
>>> at java.util.concurrent.FutureTask.run(FutureTask.java:123)
>>> at org.gridgain.grid.util.runnable.GridRunnable.run(GridRunnable.java:175)
>>> at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
>>> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
>>> at java.lang.Thread.run(Thread.java:595)

Node 2 (job was failed over to this node)

[15:15:57,549][INFO ][GridFailoverManager] Resolving failover [jobRes=org.gridgain.grid.kernal.GridJobResultImpl ... ]
>>>
>>> Printing 'Hello World' on this node from grid-enabled method.
>>>

Package:
org.gridgain.examples.helloworld.gridify.failover

There are two classes implemented for this example:

AspectJ AOP Configuration

We will use AspectJ AOP for this example. To use other AOP implementations (such as JBoss AOP, or Spring AOP), refer to AOP Configuration documentation.

The following configuration needs to be applied to enable AspectJ byte code weaving.

  • JVM configuration should include: -javaagent:[GRIDGAIN_HOME]/libs/aspectjweaver-1.5.3.jar
  • Classpath should contain the [GRIDGAIN_HOME]/config/aop/aspectj folder.

Running Grid Node

This example will need one remote node to be running. Note that you don't need another machine for it - you can start remote node on the same machine you are running example on.

To start a remote node open the terminal window on Linux/Mac OS X or Command Prompt on Windows, change directory to ${GRIDGAIN_HOME}/bin and run the gridgain.{sh|bat} script. It takes 2-3 seconds for grid node to start and if everything worked fine you should see starting log ending with successful start acknowledgment.

GridifyHelloWorldFailoverExample.java

1. Import GridGain classes.

import org.gridgain.grid.*;
import org.gridgain.grid.gridify.*;

2. Add Grid Start and Stop.

GridFactory.start();
        
try {
    ...
}
finally {
    GridFactory.stop(true);
}

finally clause allows for graceful grid shutdown in case of the exceptions.

3. Add Gridify Annotation.

Method grid-enabled with @Gridify Javadoc annotation. Simply prints out the argument passed in.

@Gridify(taskClass = GridifyHelloWorldFailoverTask.class, timeout = 60000)
public static int sayIt(String phrase) {
    // Simply print out the argument.
    System.out.println(">>>");
    System.out.println(">>> Printing '" + phrase + "' on this node from grid-enabled method.");
    System.out.println(">>>");

    return phrase.length();
}

Full Source Code

GridifyHelloWorldFailoverExample.java
package org.gridgain.examples.helloworld.gridify.failover;

import org.gridgain.grid.*;
import org.gridgain.grid.gridify.*;
import org.gridgain.grid.gridify.aop.spring.*;

public final class GridifyHelloWorldFailoverExample {
    /**
     * Enforces singleton.
     */
    private GridifyHelloWorldFailoverExample() {
        // No-op.
    }
    
    /**
     * Method grid-enabled with {@link Gridify} annotation. Simply prints
     * out the argument passed in.
     *
     * @param arg String to print.
     */
    @Gridify(taskClass = GridifyHelloWorldFailoverTask.class, timeout = 60000)
    public static int sayIt(String phrase) {
        // Simply print out the argument.
        System.out.println(">>>");
        System.out.println(">>> Printing '" + phrase + "' on this node from grid-enabled method.");
        System.out.println(">>>");

        return phrase.length();
    }

    /**
     * Execute <tt>HelloWorld</tt> example grid-enabled with <tt>Gridify</tt> annotation.
     *
     * @param args Command line arguments, none required but if provided
     *      first one should point to the Spring XML configuration file. See
     *      <tt>"examples/config/"</tt> for configuration file examples.
     * @throws GridException If example execution failed.
     */
    public static void main(String[] args) throws GridException {
        if (args.length == 0) {
            GridFactory.start();
        }
        else {
            GridFactory.start(args[0]);
        }

        try {
            // This method will be executed on a remote grid node.
            int phraseLen = sayIt("Hello World");

            System.out.println(">>>");
            System.out.println(">>> Finished executing Gridify \"Hello World\" example with failover.");
            System.out.println(">>> Total number of characters in the phrase is '" + phraseLen + "'.");
            System.out.println(">>> You should see exception stack trace from failed job on one node.");
            System.out.println(">>> Failed job will be failed over to another node.");
            System.out.println(">>> You should see print out of 'Hello World' on another node.");
            System.out.println(">>> Check all nodes for output (this node is also part of the grid).");
            System.out.println(">>>");
        }
        finally {
            GridFactory.stop(true);
        }
    }
}

GridifyHelloWorldFailoverTask.java

1. Import GridGain classes.

import org.gridgain.grid.*;
import org.gridgain.grid.resources.*;
import org.gridgain.grid.gridify.*;

2. Split Logic.

This is a grid task implementation that is responsible for split and aggregate (a.k.a map/reduce) logic. Note that this implementation uses GridifyTaskSplitAdapter Javadoc that simplifies API for grid tasks in homogeneous grids (which is often the case). Main two methods that are implemented here are split and reduce. Method reduce aggregates results (sums up numbers returned from jobs) to calculate length of initial string.

This grid task demonstrates some basic usage of task session and failover. It does the following:

  1. Set session attribute 'fail=true'.
  2. Pass the passed in string as an argument into remote job for execution.
  3. The job will check the value of 'fail' attribute. If it is true, then it will set it to false and throw exception to simulate a failure. If it is false, then it will execute the grid-enabled method.

3. Result Logic.

Method GridTask.result(GridJobResult, List) is invoked every time a result from remote job execution is received (see GridTask Javadoc ). We override default implementation from GridTaskAdapter Javadoc to make sure that GridJobResultPolicy.FAILOVER Javadoc policy is returned in case of any exception and job will be automatically failed over (by default job would automatically fail over only in case of node failure or job execution rejection).

Full Source Code

GridifyHelloWorldFailoverTask.java
package org.gridgain.examples.helloworld.gridify.failover;

import org.gridgain.grid.*;
import org.gridgain.grid.resources.*;
import org.gridgain.grid.gridify.*;
import java.util.*;
import java.io.*;

/**
 * This grid task demonstrates some basic usage of task session and failover. It does the following:
 * <ol>
 * <li>Set session attribute '<tt>fail=true</tt>'.</li>
 * <li>Pass the passed in string as an argument into remote job for execution.</li>
 * <li>
 *   The job will check the value of '<tt>fail</tt>' attribute. If it
 *   is <tt>true</tt>, then it will set it to <tt>false</tt> and throw
 *   exception to simulate a failure. If it is <tt>false</tt>, then
 *   it will execute the grid-enabled method.
 * </li>
 * </ol>
 * Note that when job throws an exception it will be treated as a failure
 * by {@link #result(GridJobResult, List)} method which will return 
 * {@link GridJobResultPolicy#FAILOVER} policy. This will cause the job to 
 * automatically failover to another node for execution. The new job will 
 * simply print out the argument passed in.
 */
public class GridifyHelloWorldFailoverTask extends GridifyTaskSplitAdapter<Integer> {
    /** Grid task session is injected here. */
    @GridTaskSessionResource
    private GridTaskSession ses = null;

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<? extends GridJob> split(int gridSize, GridifyArgument arg) throws GridException {
        // Set initial value for 'fail' attribute to 'true'.
        ses.setAttribute("fail", true);

        // We know that 1st parameter of our 'sayIt' method is a string.
        String words = ((String)arg.getMethodParameters()[0]);

        // Return just one job here.
        return Collections.singletonList(new GridJobAdapter<String>(words) {
            /*
             * The job will check the '<tt>fail</tt>' session attribute and if
             * it's <tt>true</tt> it will throw exception to simulate a failure.
             * Otherwise, it will execute the grid-enabled method.
             */
            public Serializable execute() throws GridException {
                boolean fail = false;

                try {
                    // Wait and get 'fail' attribute from session when it becomes available.
                    // In our example - we'll get it immediately since we set it up front
                    // in the 'split' method above.
                    fail = (Boolean)ses.waitForAttribute("fail");
                }
                catch (InterruptedException e) {
                    throw new GridException("Got interrupted while waiting for attribute to be set.", e);
                }

                // First time 'fail' attribute will be 'true' since
                // that's what we initialized it to during 'split'.
                if (fail == true) {
                    // Reset this attribute to 'false'.
                    // Next time we get this attribute we'll get 'false' value.
                    ses.setAttribute("fail", false);

                    // Throw exception to simulate error condition.
                    // The task 'result' method will see this exception 
                    // and failover the job.
                    throw new GridException("Example job exception.");
                }

                // Execute gridified method.
                // Note that since we are calling this method from within the grid job
                // AOP-based grid enabling will not cross-cut it and method will just
                // execute normally.
                return GridifyHelloWorldFailoverExample.sayIt(getArgument());
            }
        });
    }

    /**
     * To facilitate example's logic, returns {@link GridJobResultPolicy#FAILOVER}
     * policy in case of any exception.
     *
     * @param result {@inheritDoc}
     * @param received {@inheritDoc}
     * @throws GridException {@inheritDoc}
     * @return {@inheritDoc}
     */
    @Override
    public GridJobResultPolicy result(GridJobResult result, List<GridJobResult> received) throws GridException {
        return result.getException() != null ? GridJobResultPolicy.FAILOVER : GridJobResultPolicy.WAIT;
    }

    /**
     * Sums up all characters from all jobs and returns a
     * total number of characters in the initial phrase.
     *
     * @param results Job results.
     * @return Number of letters for the phrase passed into
     *      {@link GridifyHelloWorldFailoverExample#sayIt(String)} method.
     * @throws GridException If reduce failed.
     */
    public Integer reduce(List<GridJobResult> results) throws GridException {
        // We only had one job in the split. Therefore,
        // we only have one result.
        Integer charCnt = results.get(0).getData();

        // Total number of characters in the phrase
        // passed into task execution.
        return charCnt;
    }
}

Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.10 Build:#528 Nov 29, 2006) - Bug/feature request - Contact Administrators