SampleApp: Developing an asynchronous IBM Spectrum Symphony Java client
In this tutorial, you will learn how to convert a synchronous client into an asynchronous one.
About this task
- Build the sample client and service
- Package the sample service
- Add the application
- Run the sample client and service
- Walk through the code
Procedure
- Build the sample client and service:
You can build client application and service samples at the same time.
- Build the sample client and service on Windows:
- Compile with the .bat file by changing to the
%SOAM_HOME%\version\samples\Java\SampleApp directory
under IBM® Spectrum Symphony
Developer Edition and running the .bat file:
build.bat
- Compile with the Ant build file.Note: IBM Spectrum Symphony supports Ant 1.6.0 or higher for building Java™ samples in the IBM Spectrum Symphony Developer Edition package.Change to the %SOAM_HOME%\version\samples\Java\SampleApp directory and run the command:
ant
- Compile in Eclipse.
To compile in Eclipse, see Using Eclipse as your development environment.
- Compile with the .bat file by changing to the
%SOAM_HOME%\version\samples\Java\SampleApp directory
under IBM® Spectrum Symphony
Developer Edition and running the .bat file:
-
Build the sample client and service on Linux®:
- Change to the conf directory under the directory in which you installed IBM Spectrum Symphony Developer Edition.
- Set the environment:
- (csh) source cshrc.soam
- (bash) . profile.soam
- Compile with the makefile or with the Ant build file:
- To compile with the Makefile, change to the
$SOAM_HOME/version/samples/Java/SampleApp directory and run
the make command:
make
- To compile with the Ant build file, change to the
$SOAM_HOME/version/samples/Java/SampleApp directory and run
the build command:
ant
Note: IBM Spectrum Symphony supports Ant 1.6.0 or higher for building Java samples in the IBM Spectrum Symphony Developer Edition package.
- To compile with the Makefile, change to the
$SOAM_HOME/version/samples/Java/SampleApp directory and run
the make command:
- Build the sample client and service on Windows:
- Package the sample service.
You must package the files required by your service to create a service package. When you built the sample, the service package was automatically created for you.
Your service package SampleServiceJavaPackage.jar is in the %SOAM_HOME%\7.3.2\samples\Java\SampleApp directory.
- Add the application.
When you add an application through the cluster management console, you must use the Add Application wizard. This wizard creates a consumer location to associate with your application, deploys your service package, and registers your application. After completing the steps with the wizard, your application should be ready to use.
-
In the cluster management console, click Symphony Workload > Configure Applications.
The Applications page displays.
- Select Global Actions > Add/Remove Applications.
The Add/Remove Application page displays.
- Select Add an application, then
click Continue.
The Adding an Application page displays.
-
Select your application profile XML file, then click Continue
For SampleApp, you can find your profile in the following location:
- Windows: %SOAM_HOME%\version\samples\Java\SampleApp\SampleAppJava.xml
- Linux: $SOAM_HOME/version/samples/Java/SampleApp/SampleAppJava.xml
The Service Package location window displays.
- Browse to the created service package and select it,
then, select Continue.
- Windows: %SOAM_HOME%\version\samples\Java\SampleApp\SampleServiceJavaPackage.jar
- Linux: $SOAM_HOME/version/samples/Java/SampleApp/SampleServiceJavaPackage.zip
The Confirmation window displays.
- Review your selections, then click Confirm.
The window displays indicating progress. Your application is ready to use.
- Click Close.
The window closes and you are now back in the cluster management console. Your new application is displayed as enabled.
-
In the cluster management console, click Symphony Workload > Configure Applications.
- Run the sample client and service:
To run the service, you run the client application. The service a client application uses is specified in the application profile.
- Run the sample client and service on Windows, run the client application from
the command line:
%SOAM_HOME%\version\samples\Java\SampleaApp\RunAsyncClient.bat
- Run the sample client and service on Linux by running the client application:
$SOAM_HOME/version/samples/Java/SampleApp/RunAsyncClient.sh
You should see output as work is submitted to the system.
The client starts and the system starts the corresponding service. The client displays messages indicating that it is running.
- Run the sample client and service on Windows, run the client application from
the command line:
- Walk through the code.
Review the sample client application code to learn how you can understand the differences between a synchronous client and an asynchronous client.
- Locate the code samples:
Table 1. Code samples Operating system Files Location of code sample Windows Client %SOAM_HOME%\version\samples\Java\SampleApp\src\com\platform\symphony\samples\SampleApp\client\AsyncClient.java Input and output objects %SOAM_HOME%\version\samples\Java\SampleApp\src\com\platform\symphony\samples\SampleApp\common\MyInput.java %SOAM_HOME%\version\samples\Java\SampleApp\src\com\platform\symphony\samples\SampleApp\common\MyOutput.java
Service code %SOAM_HOME%\version\samples\Java\SampleApp\src\com\platform\symphony\samples\SampleApp\service\MyService.java Application profile The service required to compute the input data along with additional application parameters are defined in the application profile: %SOAM_HOME%\version\samples\Java\SampleApp\SampleAppJava.xml
Output directory %SOAM_HOME%\version\samples\Java\SampleApp\ Linux Client $SOAM_HOME/version/samples/Java/SampleApp/src/com/platform/symphony/samples/SampleApp/client/AsyncClient.java Input and output objects $SOAM_HOME/version/samples/Java/SampleApp/src/com/platform/symphony/samples/SampleApp/common/MyInput.java $SOAM_HOME/version/samples/Java/SampleApp/src/com/platform/symphony/samples/SampleApp/common/MyOutput.java
Service code $SOAM_HOME/version/samples/Java/SampleApp/src/com/platform/symphony/samples/SampleApp/service/MyService.java Application profile The service required to compute the input data along with additional application parameters are defined in the application profile: $SOAM_HOME/version/samples/Java/SampleApp/SampleAppJava.xml
Output directory $SOAM_HOME/version/samples/Java/SampleApp/ - Understand what the sample does
The client application sample sends 10 input messages through IBM Spectrum Symphony to the service with the data
Hello Grid !!
.The service takes the input data sent by the client and returns it with the additional data
Hello Client !!
.Results are returned asynchronously with a callback interface provided by the client to the API. Methods in this interface are called from threads within the API when certain events occur. In the sample, the events are:- When there is an error at the session level.
- When results return from IBM Spectrum Symphony.
- Understand considerations for asynchronous clients.
The purpose of an asynchronous client is to get the output as soon as it is available. The client thread does not need to be blocked once the input data is sent and can perform other actions.
- Synchronization
- Because results can come back at any time, it is probable that your callback code needs synchronization between the callback thread and the controlling thread. The controlling thread needs to know when work is complete.
- Order of results
- Results are not sent back in order. If order of results is important, the client application must sort the results.
- Understand code differences between synchronous and
asynchronous clients. An asynchronous client is very similar to a synchronous client. The only differences are as follows:
- You need to specify a callback when creating a session
- You specify a different flag to indicate asynchronous when you create a session
- Handling of replies
The following figure highlights in bold the differences between synchronous and asynchronous clients. Everything else is the same as the synchronous client. - Implement input and output objects and initialize the
client.
As in the synchronous client tutorial, implement your own input and output objects and initialize the client.
For more details, look at the synchronous client tutorial, specifically:- Implement input and output objects
- Initialize the client
- Declare and implement your callback object.
Perform this step after implementing your own input and output objects.
In MySessionCallback.java, we create our own callback class that extends the SessionCallback class, and we implemented onResponse() to retrieve the output for each input message that we send.Notes:- We handle when an exception occurs on the callback method for the session. If you do not handle the exception, you do not have any exceptions if an error occurs on the callback.
- onResponse() is called every time a task completes and output is returned to the client. The task output handle allows the client code to manipulate the output.
- isSuccessful() checks whether there is output to retrieve.
- If there is output to retrieve, getTaskOutput() gets the output. Once results return, we print them to standard output and return.
public class MySessionCallback extends SessionCallback { //========================================================================= // Constructor //========================================================================= public MySessionCallback(int tasksToReceive) { m_tasksReceived = 0; m_exception = false; m_tasksToReceive = tasksToReceive; }
//========================================================================= // SessionCallback Interface Methods //========================================================================= /** * Invoked when an exception occurs within the scope of the given session. * Must be implemented by the application developer. */ public void onException(SoamException exception) throws SoamException { System.out.println("An exception occured on the callback :"); System.out.println(exception.getMessage()); setException(true); }
/** * Invoked when a task response is ready. * Must be implemented by the application developer. */ public void onResponse(TaskOutputHandle output) throws SoamException { try { // check for success of task if (output.isSuccessful()) { // get the message returned from the service MyOutput myOutput = (MyOutput)output.getTaskOutput(); // display content of reply System.out.println("\nTask Succeeded [" + output.getId() + "]"); System.out.println("Your Internal ID was : " + myOutput.getId()); System.out.println("Estimated runtime was recorded as : " + myOutput.getRunTime()); System.out.println(myOutput.getString()); } else { // get the exception associated with this task SoamException ex = output.getException(); System.out.println("Task Failed :"); System.out.println(ex.getMessage()); } } catch (Exception exception) { System.out.println("Exception occured in onResponse() : "); System.out.println(exception.getMessage()); } // Update counter used to synchronize the controlling thread // with this callback object incrementTaskCount(); }
- Create a session to group tasks.
In AsyncClient.java, perform this step after you have connected to the application.
When creating an asynchronous session:- Specify the flag PARTIAL_ASYNC. This indicates that results are collected asynchronously.
- Provide a callback object.
... // Create session callback int tasksToSend = 10; MySessionCallback myCallback = new MySessionCallback(tasksToSend); Session session = null; // Set up session attributes SessionCreationAttributes attributes = new SessionCreationAttributes(); attributes.setSessionName("mySession"); attributes.setSessionType("ShortRunningTasks"); attributes.setSessionFlags(Session.PARTIAL_ASYNC); attributes.setSessionCallback(myCallback); // Create an asynchronous session try { session = connection.createSession(attributes); // Retrieve and print session ID System.out.println("Session ID:" + session.getId()); ...
- Synchronize the controlling and callback threads.
Perform this step after sending the input data to be processed.
Since our client is asynchronous, we need to synchronize the controlling thread and the callback thread. In this example, the controlling thread blocks until all replies have come back.
The callback signals when all results are received:... synchronized(myCallback) { while (!myCallback.isDone()) { myCallback.wait(); } } ...
- Locate the code samples: