SampleApp: Your first synchronous IBM Spectrum Symphony Java client

This tutorial guides you through the process of building, packaging, deploying, and running the sample client and service. It then walks you through the sample client application code. You will learn the minimum amount of code that you need to create a synchronous client.

About this task

In this tutorial, you will complete these tasks:
  1. Build the sample client and service
  2. Package the sample service
  3. Add the application
  4. Run the sample client and service
  5. Walk through the code

Procedure

  1. Build the sample client and service:
    1. Build the sample client and service on Windows:

      You can build client application and service samples at the same time.

      1. 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
        
      2. 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
      3. Compile in Eclipse.

        To compile in Eclipse, see Using Eclipse as your development environment.

    2. Build the sample client and service on Linux®:
      1. Change to the conf directory under the directory in which you installed IBM Spectrum Symphony Developer Edition.
      2. Set the environment:
        • (csh) source cshrc.soam
        • (bash) . profile.soam
      3. Compile with the Makefile or with the Ant build file:
        • Compile with the makefile:
          Change to the $SOAM_HOME/version/samples/Java/SampleApp directory and run the make command:
          make
        • 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 build command:
          ant
  2. 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%\version\samples\Java\SampleApp directory.

  3. Add the application.

    When you add an application through the IBM Spectrum Symphony Developer Edition cluster management console, you must use the Add Application wizard. This wizard defines 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.

    1. In the cluster management console, click Workload > Symphony > Application Profiles.

      The Applications page displays.

    2. Select Global Actions > Add/Remove Applications.

      The Add/Remove Application page displays.

    3. Select Add a new application, then click Continue.

      The Adding an Application page displays.

    4. Select Use existing profile and add application wizard. Click Browse and navigate to your application profile.
    5. 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.

    6. Browse to the created service package and select it, then, click Continue.
      • Windows: %SOAM_HOME%\version\samples\Java\SampleApp\SampleServiceJavaPackage.jar
      • Linux: $SOAM_HOME/version/samples/Java/SampleApp/SampleServiceJavaPackage.zip

      The Confirmation window displays.

    7. Review your selections, then click Confirm.

      The window displays indicating progress. Your application is ready to use.

    8. Click Close.

      The window closes and you are now back in the cluster management console. Your new application is displayed as enabled.

  4. 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.

    1. Run the sample client and service on Windows:

      Run the client application from the command line:%SOAM_HOME%\version\samples\Java\SampleApp\RunSyncClient.bat

      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.

    2. Run the sample client and service on Linux:

      Run the client application:$SOAM_HOME/version/samples/Java/SampleApp/RunSyncClient.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.

  5. Walk through the code.

    Review the sample client application code to learn how you can create a synchronous client application.

    1. 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\SyncClient.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/syncClient.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/
    2. 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 client blocks to receive messages synchronously.

      The service takes the input data sent by the client and returns it with the additional data Hello Client !!.

    3. Understand synchronous client structure

      Before developing your client code, implement input and output objects that implement java.io.Serializable. Then, create your IBM Spectrum Symphony client.

      Client synchronization in Java
    4. Implement input and output objects:
      1. Implement the MyInput class

        The myInput class acts as input to the service. In MyInput.java, we implement methods to set and access the data, such as the message string and task ID.

        The input object must implement java.io.Serializable. Making the object serializable means that Java knows how to deconstruct the object so that it can be passed through the network to the service. This also means that Java knows how to reconstruct the object when it is received by the service.
        ...
        public class MyInput implements Serializable
        {
            //=========================================================================
            //  Constructors
            //=========================================================================
        
            public MyInput()
            {
                super();
                m_id = 0;
            }
        
            public MyInput(int id, String string)
            {
                super();
                m_id = id;
                m_string = string;
            }
        
            //=========================================================================
            //  Accessors and Mutators
            //=========================================================================
            
            public int getId()
            {
                return m_id;
            }
        
            public void setId(int id)
            {
                m_id = id;
            }
        
            public String getString()
            {
                return m_string;
            }
        
            public void setString(String string)
            {
                m_string = string;
            }
        
        ...
        
        
      2. Implement the MyOutput class

        The myoutput object is the result of the computation of input to the service, and is returned to the client by the service.

        In MyOutput.java, we implement methods to set and access the output data, such as the message string, task ID, and run time that is returned from the service. Similar to the input object, the output object must implement java.io.Serializable.
        ...
        public class MyOutput implements Serializable{
            //=========================================================================
            //  Constructor
            //=========================================================================
        
            public MyOutput()
            {
                super();
                m_id = 0;
            }
        
        
            //=========================================================================
            //  Accessors and Mutators
            //=========================================================================
        
            public int getId()
            {
                return m_id;
            }
        
            public void setId(int id)
            {
                m_id = id;
            }
        
            public String getRunTime()
            {
                return m_runTime;
            }
        
            public void setRunTime(String runTime)
            {
                m_runTime = runTime;
            }
        
            public String getString()
            {
                return m_string;
            }
            
            public void setString(String string)
            {
                m_string = string;
            }
        ...
        
    5. Initialize the client.
      In SyncClient.java, when you initialize, you initialize the IBM Spectrum Symphony client infrastructure. You initialize once per client.
      Important:
      Initialization is required. Otherwise, API calls fail.
      ...
      SoamFactory.initialize();
      ...
      
    6. Connect to an application.
      A connection establishes a context for your client and workload. When you connect to an application:
      • Application attributes defined in the application profile are used to provide context such as which service to use, session type, and any additional scheduling or application parameters.
      • A connection object is returned.

      The application name in the connection must match that defined in the application profile.

      The default security callback encapsulates the callback for the user name and password. In IBM Spectrum Symphony Developer Edition, there is no security checking and logon credentials are ignored; you can specify any user name and password. However, when using your client on the grid with IBM Spectrum Symphony, you need a valid user name and password:
      ...
      // Set up application specific information to be supplied to Symphony
                  String appName="SampleAppJava";
      
                  // Set up application authentication information using the default security provider
                  DefaultSecurityCallback securityCB = new DefaultSecurityCallback("User1", "User1pw");
      
                  Connection connection = null;
                  try
                  {
                      // Connect to the specified application
                      connection = SoamFactory.connect(appName, securityCB);
      
                      // Retrieve and print our connection ID
                      System.out.println("connection ID=" + connection.getId());
      ...
      
      finally
                  {
                      // Mandatory connection close
                      if (connection != null)
                      {
                          connection.close();
                          System.out.println("Connection closed");
                      }
                }
      ...
      
      
      Important: The creation and usage of the connection object must be scoped in a try-finally block. The finally block, with the connection.close() method, ensures that the connection is always closed whether exceptional behavior occurs or not. Failure to close the connection causes the connection to continue to occupy system resources.
    7. Create a session to group tasks.
      A session is a way of logically grouping tasks that are sent to a service for execution. The tasks are sent and received synchronously:
      ...
       // Set up session attributes
                      SessionCreationAttributes attributes = new SessionCreationAttributes();
                      attributes.setSessionName("mySession");
                      attributes.setSessionType("ShortRunningTasks");
                      attributes.setSessionFlags(Session.SYNC);
      
                      // Create a synchronous session
                      Session session = null;
                      try
                      {
                          session = connection.createSession(attributes);
      ...
                      finally
                      {
                          // Mandatory session close
                          if (session != null)
                          {
                              session.close();
                              System.out.println("Session closed");
                          }
                      }
      ...
      
      

      When creating a synchronous session, you need to specify the session attributes by using the SessionCreationAttributes object. In this sample, we create a SessionCreationAttributes object called attributes and set three parameters in the object.

      The first parameter is the session name. This is optional. The session name can be any descriptive name you want to assign to your session. It is for informational purposes, such as in the command line interface.

      The second parameter is the session type. The session type is optional. You can leave this parameter blank and system default values are used for your session.

      The third parameter is the session flag, which we specify as Session.SYNC. This indicates to IBM Spectrum Symphony that this is a synchronous session.

      We pass the attributes object to the createSession() method, which returns the created session.

      Important: Similar to the connection object, the creation and usage of the session (sending and receiving data) must be scoped in a try-finally block. The finally block, with the session.close() method, ensures that the session is always closed, whether exceptional behavior occurs or not. Failure to close the session causes the session to continue to occupy system resources.
    8. Send input data to be processed.
      In this step, we create 10 input messages to be processed by the service. When a message is sent, a task input handle is returned. This task input handle contains the ID for the task that was created for this input message:
      ...
      // Now we will send some messages to our service
                          int tasksToSend = 10;
                          for (int taskCount = 0; taskCount < tasksToSend; taskCount++)
                          {
                              // Create a message
                              MyInput myInput = new MyInput(taskCount, Hello Grid !!);
      
                              // Set task submission attributes
                              TaskSubmissionAttributes taskAttr = new TaskSubmissionAttributes();
                              taskAttr.setTaskInput(myInput);
      
                              // Send it
                              TaskInputHandle input = session.sendTaskInput(taskAttr);
      
                              // Retrieve and print task ID
                              System.out.println("task submitted with ID : " + input.getId());
                        }
      
      ...
      
    9. Retrieve output.

      The call fetchTaskOutput() blocks until the output for all tasks is retrieved. If there is output to retrieve, getTaskOutput() gets the output

      Important:
      Results are not sent back in order. If order of results is important, the client application must sort the results:
      ...
      // Now get our results - will block here until all tasks retrieved
                          EnumItems enumOutput = session.fetchTaskOutput(tasksToSend);
      
                          // Inspect results
                          TaskOutputHandle output = enumOutput.getNext();
                          while (output != null)
                          {
                              // 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.toString());
                              }
                              output = enumOutput.getNext();
                        }
       ...
      
      
    10. Catch exceptions

      Any exceptions thrown take the form of SoamException. Catch all IBM Spectrum Symphony exceptions that occurred in the client application, service, and system.

      The sample code in Retrieve output catches exceptions of type SoamException.

    1. Uninitialize.

      Always uninitialize the client at the end of all API calls. If you do not call uninitialize, the client stays in an undefined state and resources used by the client are held indefinitely.

      Important:
      Once you uninitialize, all objects become invalid. For example, you can no longer create a session or send an input message.
      ...
      SoamFactory.uninitialize();
      ...