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


Gridify With Spring

This example demonstrates a simple use of GridGain grid with @Gridify Javadoc annotation and custom grid task by utilizing Spring proxy-based AOP implementation.

String "Hello World" is set into GridifySpringHelloWorld.java instance as its state. Since method GridifySpringHelloWorld#sayIt() is annotated with @Gridify Javadoc annotation it is automatically grid-enabled. The GridifySpringHelloWorldTask.java task specified in @Gridify Javadoc annotation will split the state of GridifySpringHelloWorld.java instance into words and send each word as job argument for execution on separate nodes. Jobs on remote nodes will create GridifySpringHelloWorldImpl.java instances and will preinitialize them with state passed in as job's argument. As an outcome, two participating nodes will print out a single word from "Hello World" string. One node will print out "Hello" and the other will print out "World". If there is only one node participating, then it will print out both words.

Grid task GridifySpringHelloWorldTask.java handles actual splitting into sub-jobs, remote execution, and result reduction (see GridTask).

This example is slightly modified version of [HelloWorld - Gridify With State] to make it work with Spring Framework AOP implementation.

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

There are four classes implemented for this example:

Spring AOP.

Spring AOP framework is based on dynamic proxy implementation and doesn't require any specific runtime parameters for online weaving. All weaving is on-demand and should be performed by calling method GridifySpringEnhancer#enhance(Object) for the object that has method with @Gridify Javadoc annotation.

That this method of weaving is rather inconvenient and AspectJ or JbossAOP is recommended over it. Spring AOP can be used in situation when code augmentation is undesired and cannot be used. It also allows for very fine grained control of what gets weaved.

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.

GridifySpringHelloWorldExample.java

1. Import GridGain classes.

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

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.

Add Gridify Annotation.

Method grid-enabled with @Gridify Javadoc annotation. Simply prints out the argument passed in. Note that we add annotation to the interface.

/**
 * Method grid-enabled with {@link Gridify} annotation.
 */
@Gridify(taskClass = GridifySpringHelloWorldTask.class, timeout = 3000)
public void sayIt();

Enhance with Spring.

GridifySpringHelloWorld hello = new GridifySpringHelloWorldImpl("Hello World");

hello = GridifySpringEnhancer.enhance(hello);

Full Source Code

GridifySpringHelloWorldExample.java
package org.gridgain.examples.helloworld.gridify.spring;

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

public final class GridifySpringHelloWorldExample {
    /**
     * Ensure singleton.
     */
    private GridifySpringHelloWorldExample() {
        // No-op.
    }

    /**
     * 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 {
            // Simple example stateful instance to demonstrate
            // how object state can be handled with grid-enabled methods.
            GridifySpringHelloWorld hello = new GridifySpringHelloWorldImpl("Hello World");

            // Required step with proxy-based Spring AOP.
            // The 'enhance' method will make sure that all methods
            // with Gridify annotation will be grid-enabled.
            hello = GridifySpringEnhancer.enhance(hello);

            // This method is grid-enabled and
            // will be executed on remote grid nodes.
            int phraseLen = hello.sayIt();

            System.out.println(">>>");
            System.out.println(">>> Finished executing Gridify \"Hello World\" Spring AOP stateful example.");
            System.out.println(">>> Total number of characters in the phrase is '" + phraseLen + "'.");
            System.out.println(">>> You should see print out of 'Hello' on one node and '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);
        }
    }
}

GridifySpringHelloWorld.java

GridifySpringHelloWorld.java
public interface GridifySpringHelloWorld {
    /**
     * Gets example state.
     *
     * @return Example state.
     */
    public String getState();

    /**
     * Method grid-enabled with {@link Gridify} annotation.
     */
    @Gridify(taskClass = GridifySpringHelloWorldTask.class, timeout = 3000)
    public void sayIt();
}

GridifySpringHelloWorldImpl.java

GridifySpringHelloWorldImpl.java
public class GridifySpringHelloWorldImpl implements GridifySpringHelloWorld {
    /** Example state. */
    private String state = null;

    /**
     * Creates a fully initialized instance with given String state.
     *
     * @param state State to use for this example.
     */
    public GridifySpringHelloWorldImpl(String state) {
        this.state = state;
    }

    /**
     * {@inheritDoc}
     */
    public String getState() {
        return state;
    }

    /**
     * Method grid-enabled with {@link Gridify} annotation. Simply prints
     * out the state of this instance. Note that {@link Gridify} annotation
     * is attached to {@link GridifySpringHelloWorld#sayIt()} method on the
     * interface.
     *
     * @return Number of letters in a phrase.
     */
    public int sayIt() {
        // Simply print out the argument.
        System.out.println(">>>");
        System.out.println(">>> Printing '" + state + "' on this node from grid-enabled method.");
        System.out.println(">>>");

        return state.length();
    }
}

GridifySpringHelloWorldTask.java

1. Import GridGain classes.

import java.io.*;
import java.util.*;
import org.gridgain.grid.*;
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 by jobs) to calculate length of initial string. This task passes the passed in string as an argument into remote job for execution.

Full Source Code

GridifySpringHelloWorldTask.java
package org.gridgain.examples.helloworld.gridify.spring;

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

/**
 * This grid task is responsible for splitting the string state of
 * {@link GridifySpringHelloWorldImpl} into separate words and then passing
 * each word into its own grid job as an argument for execution on
 * remote nodes. When job receives such argument on remote node,
 * it will set it as state into new {@link GridifySpringHelloWorldImpl} instance
 * to prepare the instance for execution and then execute grid-enabled
 * {@link GridifySpringHelloWorld#sayIt()} method on it.
 *
 * @author morpheus
 * @version 1.5
 */
public class GridifySpringHelloWorldTask extends GridifyTaskSplitAdapter<Integer> {
    /**
     * {@inheritDoc}
     */
    @Override
    protected Collection<? extends GridJob> split(int gridSize, GridifyArgument arg) throws GridException {
        // Get target instance on which grid-enabled method was invoked.
        GridifySpringHelloWorld hello = (GridifySpringHelloWorld)arg.getTarget();

        // Split internal string state of GridifySpringHelloWorld into separate words.
        String[] words = hello.getState().split(" ");

        List<GridJobAdapter<String>> jobs = new ArrayList<GridJobAdapter<String>>(words.length);

        for (String word : words) {
            // Every job gets its own word as an argument.
            jobs.add(new GridJobAdapter<String>(word) {
                /*
                 * Simply executes 'GridifySpringHelloWorldImpl#sayIt(String)' method
                 * with passed in state.
                 */
                public Serializable execute() throws GridException {
                    // Initialize GridifySpringHelloWorldImpl instance with state
                    // passed in as an argument.
                    GridifySpringHelloWorld hello = new GridifySpringHelloWorldImpl(getArgument());

                    // Execute method that was grid-enabled on the
                    // parent task node.
                    return hello.sayIt();
                }
            });
        }

        return jobs;
    }

    /**
     * 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 characters for the 'phrase' passed into
     *      {@link GridifySpringHelloWorldImpl} constructor.
     * @throws GridException If reduce failed.
     */
    public Integer reduce(List<GridJobResult> results) throws GridException {
        int totalCharCnt = 0;

        for (GridJobResult res : results) {
            // Every job returned a number of letters
            // for the phrase it was responsible for.
            Integer charCnt = res.getData();

            totalCharCnt += charCnt;
        }

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

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