Developing an IBM Spectrum Symphony application with Eclipse

This tutorial walks you through the steps for developing application code using the IBM® Spectrum Symphony plug-in for the Eclipse IDE. It then guides you through the process of building, packaging, and deploying the associated service. This tutorial was prepared for users that are already familiar with the Eclipse IDE.

Before you begin

  1. If you are using Eclipse on a Linux® system, source the environment script file, for example:
    • (bsh) . $EGO_TOP/profile.platform
    • (csh) source $EGO_TOP/cshrc.platform
  2. Launch Eclipse.
Important:

If you are using Eclipse on a Linux system, launch Eclipse from the command line so that the environment variables for the Developer Edition are accessible.

Note: If you are running the Eclipse plug-in on a host that has a IBM Spectrum SymphonyDeveloper Edition pre-7.3.2 version and IBM Spectrum Symphony Developer Edition 7.3.2 installed, you must ensure that the system environment is set up for IBM Spectrum Symphony Developer Edition 7.3.2. Refer to Installing IBM Spectrum Symphony Developer Edition.

About this task

Install the IBM Spectrum Symphony plug-in for Eclipse
For instructions on installing the IBM Spectrum Symphony plug-in into Eclipse, refer to Using Eclipse as your development environment.
What the IBM Spectrum Symphony plug-in can do
The IBM Spectrum Symphony plug-in for Eclipse is an all-in-one tool package that eases the task of IBM Spectrum Symphony application development and package deployment.

The plug-in generates a framework of code that provides a foundation for IBM Spectrum Symphony application development. This framework of basic code is typically common to all IBM Spectrum Symphony applications. All you need to do is add your own logic to it. One of the key components of the plug-in is the IBM Spectrum Symphony project wizard, which guides you through the development process and prompts you for application-specific information.

The plug-in also facilitates service package deployment and application registration. This is achieved by combining multiple tasks into single operations through the IBM Spectrum Symphony Developer Edition cluster management console, which is integrated with the plug-in.

Where to find the documentation
You can access additional documentation such as the API reference, Reference, and Error messages.
Creating a new IBM Spectrum Symphony Java application
This section describes the steps for creating a new IBM Spectrum Symphony Java application (with generated code) using the IBM Spectrum Symphony project wizard in Eclipse:

Procedure

  1. Create a new project.
    1. Select File > New > Project

      The New Project dialog appears.

    2. Expand the IBM Spectrum Symphony wizard. Select Symphony Java Application (with Generated Code).
    3. Click Next.

      The Symphony Application Identification dialog appears.

  2. Name the application and package.

    The application name is what binds the client to the service and it must be unique in the cluster.

    1. Enter MySymphonyApp as the IBM Spectrum Symphony application name.
    2. Verify that the Create a package for the generated Java classes box is checked.
    3. Enter com.platform.symphony.foo as the package name. Click Next.
      Note: Classes that are not placed in a named package belong to the default package associated with the current project directory.
  3. Name the client and service classes.
    1. Enter AsyncClient as the client class name.
    2. Select Async as the client type. An asynchronous client requires a callback class, which will be added to the project when the project is created.
    3. Enter MyService as the service class name. Click Next.
  4. Define the message.

    Your client application needs to handle data that it sends as input, and output data that it receives from the service. You need to define message classes that implement methods to set and access the data, such as the message string and task ID.

    1. In the New Message dialog, click Add.
    2. Enter MyInput as the message class name to handle input messages.
    3. Double-click Edit.

      The Message elements definition dialog appears.

    4. Click Add. Enter Id as the name of the data element. Verify that the data type is int (integer).
    5. Click Add. Enter Message as the name of the second data element. Set the data type to String.
    6. Click OK.
    7. In the New Message dialog, click Add.
    8. Enter MyOutput as the message class name to handle output messages.
    9. Double-click Edit.

      The Message elements definition dialog appears.

    10. Click Add. Enter Id as the name of the data element. Verify that the data type is int (integer).
    11. Click Add. Enter Message as the name of the second data element. Set the data type to String.
    12. Click OK.
    13. Click Next.

      The Create a Java project dialog appears.

  5. Create the Java project.
    1. The project name can be any descriptive name you choose. For this tutorial, enter MySymphonyProj as the project name. Your project will be created in the workspace associated with Eclipse.
    2. Select Use default location.
    3. Select Use default JRE. Ensure that you are using any of the following JDK versions: IBM JDK 1.7 or 1.8, or Oracle JDK 1.7 or Oracle JDK 1.8.
    4. Select Use project folder as root for sources and class files.
    5. Click Finish.

      Eclipse creates a new Java project in your workspace with sub-folders for the newly-created classes. These classes contain generated code that can be used as a basis for IBM Spectrum Symphony application development.

      The IBM Spectrum Symphony plug-in for Eclipse also adds project-dependent files such as the JRE system library and IBM Spectrum Symphony API to the project.

      CAUTION:
      If the .SOAMCFG file appears under the project directory, do not modify the file. It is an important configuration file and must not be changed in any way.
      Note: If you only see the Eclipse welcome screen and not your project with the generated Java code, minimize the welcome screen.

      To view your project in Package Explorer, select Window > Show View > Package Explorer.

  6. Review and understand the generated code.
    Review the client, message, and service code that is generated by the IBM Spectrum Symphony plug-in for Eclipse and discuss what you need to do to complete the application coding.
    Import message class in client class
    Since you need to create an instance of the message class in your client class, you must import the message class. Add the following import statement to the generated code for the client class:
    import com.platform.symphony.foo.message.*;
    Message input and output classes
    The MyInput class represents the data input to the service, and the MyOutput class represents the data output from the service. These classes implement methods to set and access the data, such as the message string and task ID.

    The code that is generated uses IBM Spectrum Symphony's API to serialize the MyInput and MyOutput objects. IBM Spectrum Symphony serialization is achieved by deriving from the SOAM Message object and implementing the appropriate serialization handlers, i.e., onSerialize() and onDeserialize().

    The following code was generated for the MyInput class:
    ...
    public class MyInput extends com.platform.symphony.soam.Message
    {
        //=============================================
        //.Constructor.    
        //=============================================  
        public MyInput()
        { 
            super();   
        }    
        //=============================================
        //.Accessors. 
        //============================================= 
        // "Id" () 
        public int getId()
        {      
            return this.Id;
        }    
        public void setId(int value)
        {
            this.Id = value;
        }       
        // "Message" ()
        public String getMessage()
        {
            return this.Message;
        }    
        public void setMessage(String value)
        {      
            this.Message = value; 
        }
        //============================================= 
        //.Serialization - Deserialization.
        //=============================================  
        public void onSerialize(OutputStream ostream) throws SoamException
        {
            ostream.writeLong(this.V4350FA63DBAA4f65A190EDDE29709AC6);
            ostream.writeInt(this.Id); 
            ostream.writeString(this.Message);
        } 
        public void onDeserialize(InputStream istream) throws SoamException 
        {        
            this.V4350FA63DBAA4f65A190EDDE29709AC6 = istream.readLong();
            if (this.V4350FA63DBAA4f65A190EDDE29709AC6 != 1)
            {           
                String errorMessage="A version mismatch error has occured.";
                errorMessage += "The message being deserialized is verion " +
                this.V4350FA63DBAA4f65A190EDDE29709AC6; 
                errorMessage += " but we were expecting verion <1>."; 
                errorMessage += "Verify that all message definitions are up to date.";  
                throw new FatalException(errorMessage); 
            }        
            this.Id = istream.readInt();
            this.Message = istream.readString();    
        }
    ...
    
    Callback class
    When the client type is set to asynchronous in the project wizard, it generates a callback class that extends the SessionCallback class.
    Import message class in callback class
    Since you need to create an instance of the message class in your callback class, you must import the message class. Add the following import statement to the generated code for the callback class:
    import com.platform.symphony.foo.message.*;
    Retrieve the output
    This class contains the onResponse() method to retrieve the output for each input message that is sent. To make the generated code complete, you need to add code to the onResponse() method, as indicated by the TODO comments.
    Note:
    • 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.
    public void onResponse(TaskOutputHandle output) throws SoamException
    {
        try
        {
            // Check for success of task
            if (output.isSuccessful())
            {
                // Get the message returned from the service
                /////////////////////////////////////////////////////
                // TODO: Retrieve the result from the TaskOutputHandle
                // NOTE : If your output message was generated by the 
                // Symphony Eclipse Pluggin
                // You must use the TaskOutputHandle.populateTaskOutput() method to
                // retrieve the output. The Symphony Eclipse
                // Pluggin generates messages inherited
                // from the "com.platform.symphony.soam.Message" class. 
                // eg.
                // MyOutputMessage myOutput = new MyOutputMessage();
                // output.populateTaskOutput(myOutput);
                ////////////////////////////////////////////////////
    
                // Display content of reply
                ////////////////////////////////////////////////////
                // TODO: Display some reply
                // eg . 
                // System.out.println("\nTask Succeeded [" + 
                // output.getId() + "]");
                // System.out.println("Your Internal ID was : " +
                // myOutput.getId());
                // System.out.println("Estimated runtime was recorded
                // as : ");
                // System.out.println(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());
            }
        }
        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();
    }
    
    The following code example shows the completed code for the onResponse() method. If there is output to retrieve, populateTaskOutput() gets the output. Once results return, print them to standard output and return.
    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 = new MyOutput();
                output.populateTaskOutput(myOutput);
                // display content of reply  
                  System.out.println("\nTask Succeeded [" +  output.getId() + "]");             
                System.out.println("Your Internal ID was : " + myOutput.getId());           
                System.out.println(myOutput.getMessage()); 
            }            
            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();
    }
    
    Service class
    • Import message class: Since you need to create an instance of the message class in your service class, you must import the message class. Add the following import statement to the generated code for the service class:
      import com.platform.symphony.foo.message.*;
    • Process the input
      IBM Spectrum Symphony calls onInvoke() on the service container once per task. This is where the calculation is performed.
      Important: Services are virtualized. As a result, a service should not read from stdin or write to stdout. Services can, however, read from and write to files that are accessible to all compute hosts.

      To gain access to the data set from the client, you call the populateTaskInput() method on the taskContext. TheIBM Spectrum Symphony middleware is responsible for placing the input into the taskContext object.

      The task context contains all information and functionality that is available to the service during an onInvoke() call in relation to the task that is being processed.

      The following code was generated by the IBM Spectrum Symphony plug-in. What is missing, as identified by the TODO comment, is your service logic for the onInvoke() method.
      ...
      public void onInvoke (TaskContext taskContext) throws SoamException
      {
          ////////////////////////////////////////////////////////////////
          // TODO: Place your service logic here. This method will be 
          //       called for each task that has to be processed.
          //
          // NOTE : If your message was generated by the Symphony Eclipse Pluggin
          // You must use the TaskContext.populateTaskInput() method to retrieve 
          // the input. The Symphony Eclipse Pluggin generates messages inherited
          // from the "com.platform.symphony.soam.Message" class. 
          // eg.
          //
          // // get input
          // MyInputMessage myInput = new MyInputMessage();
          // taskContext.populateTaskInput(myInput);
          //
          // // do some processing of input
          //  ...
          //
          // // set output (which is returned to client)
          // taskContext.setTaskOutput(myOutput);
          ////////////////////////////////////////////////////////////////
      }
      ...
      
    The following code example shows the onInvoke() method with the service logic. The input message is simply echoed back to the client by creating a string in the output message and passing it to the setTaskOutput() method.
    ...
    public void onInvoke (TaskContext taskContext) throws SoamException   
    {
        // We simply echo the data back to the client
        MyOutput myOutput = new MyOutput();
        // get the input that was sent from the client 
        MyInput myInput = new MyInput();
        taskContext.populateTaskInput(myInput);
        // echo the ID   
        myOutput.setId(myInput.getId());
        // setup a reply to the client
        StringBuffer sb = new StringBuffer(); 
        sb.append("Client sent : ");  
        sb.append(myInput.getMessage());
        sb.append("\nSymphony replied : Hello Client !!");
        myOutput.setMessage(sb.toString()); 
        // set our output message 
        taskContext.setTaskOutput(myOutput);  
    }
    ...
    
  7. Create a deployment package.

    You must package the files required by your service to create a service package.

    1. In the Eclipse Package Explorer, right-click on project MySymphonyProj. Select Symphony Operations > Create Deployment Package
    2. Enter MyService.zip as the package name in the Specify the package name box.
    3. Click Browse beside Select the package path to select the path where the service package will be stored.
    4. Click Browse beside Specify Main Service Class Name. Enter MyService in the box. Click OK.
    5. The JVM options can be used to configure JVM performance tuning such as memory allocation for the service instance. In this tutorial, we are using default JVM settings so it is not necessary to specify any JVM options.
    6. Select *.message.jar and *.service.jar files in the Package name or file name list.
    7. The option for Do stdout redirection from generated service script can remain unchecked. Selecting this option will cause standard output from the JVM to be redirected to a file located in the IBM Spectrum Symphony Developer Edition work directory. The file pattern is <main class name>_<computername>_<process ID of script>_<timestamp>.log.
    8. Click Create and Validate Service Package.

      After creating and validating the service package, the following message is displayed:

      Compressed package_path/MyService.zip successfully!

      The service package is valid and it is ready to be deployed to DE.

    9. Click Finish. The next step is to create an application profile and register your application.
  8. Create an application profile.
    The application profile defines the application behavior within IBM Spectrum Symphony and provides information that IBM Spectrum Symphony needs to run services and manage workload. It also binds the application to a specific service.
    Note: To create an application profile via the IBM Spectrum Symphony Developer Edition cluster management console, yourIBM Spectrum Symphony Developer Edition cluster must be started.
    1. In the Package Explorer, right-click on project MySymphonyProj. Select Symphony Operations > Add/Remove Application.
    2. Select Add a new application. Click Continue.
    3. Select Create new profile and add application wizard. The wizard automatically populates the application name field with MySymphonyApp.
      Important: If your development environment has more than one version of JDK installed (for example, JDK versions 1.7 and 1.8), you should configure the PATH environment variable to point to JDK 1.8. Failure to configure the PATH correctly may prevent your service from running. To configure the PATH environment variable, click Specify environment variables for this service. Enter PATH as the Name and the path to the JDK 1.8 bin directory as the value.
    4. Click Continue.
    5. Click Browse and navigate to the location of the service package. Select the service package file MyService.zip. Click Continue.
    6. Select System Defaults for the session type. Click Continue.
    7. Click Confirm to accept the application profile definitions.

      The project wizard creates your application and registers it within IBM Spectrum Symphony.

  9. Run the application.
    1. In the Package Explorer, right-click com.platform.symphony.foo.client class. Select Run As > Java Application. The application runs and prints results in the console window.
  10. Monitor workload.

    When you need to re-register an application, modify an application profile, or monitor workload on Linux with the Eclipse plug-in, you must specify the Mozilla-based browser as a Eclipse embedded browser to meet internal browser compatibility requirements for Eclipse. In addition, you can reregister an application, modify an application, or monitor workload from the IBM Spectrum Symphony Developer Edition cluster management console with Firefox or Microsoft Edge directly.

    1. Download the XULRunner package. For available releases, refer to your XULRunner documentation. IBM Spectrum Symphony is certified with release 1.9.2.28pre.
    2. Register XULRunner for all users:
      ./xulrunner --register-global
    3. Set the following values in the eclipse.ini file:
      • Set -Dorg.eclipse.swt.browser.DefaultType to mozilla.
      • Set -Dorg.eclipse.swt.browser.XULRunnerPath at the end of the configuration file to the location of XULRunner. For example:

        -Dorg.eclipse.swt.browser.XULRunnerPath=/xulruner

    4. Run the Eclipse binary.
    5. To monitor the session status, right-click the project in the Package Explorer and select Symphony Operations > Monitor Workload.
  11. Re-deploy the service package.
    You must update and re-deploy the service package if you have made modifications to the message or service code in your application.
    1. In the Eclipse Package Explorer, right-click on your project. Select Symphony Operations > Create Deployment Package.
    2. Verify the service information in the Symphony Service Packaging Utility dialog.
    3. Click Deploy the Package.
      Note: The Deploy the Package button is only enabled when the application is registered. Clicking this button adds the service package to the IBM Spectrum Symphony Developer Edition repository.
      After deploying the service package, the following message is displayed:
      Service package was deployed successfully to DE
    4. Click Finish.
  12. Importing samples into Eclipse.
    Every sample includes a .classpath file sufficient for building the project within Eclipse. Consequently, there is no need to import the project by importing the existing Ant build file.
    Notes:
    1. Importing and execution of Java samples in Eclipse from IBM Spectrum Symphony Developer Edition TAR packages is not supported.
    2. Importing samples into Eclipse from previous versions of IBM Spectrum Symphony Developer Edition (3.2 and earlier) is not recommended. Older samples require reorganization of their directory structure and editing of the application profile.
    3. You cannot preload information about message code that was generated outside the Eclipse plug-in since the code generation wizard is not aware of message code that has been created or modified externally. For example, if you define new message classes for an imported project using the code generation wizard, the existing message classes from the imported project will not appear in the Message Definition dialog.
    In this section, we will import the SampleApp sample that is included with IBM Spectrum Symphony Developer Edition and deploy its service. The Java samples are located at the following locations:
    • Windows: %SOAM_HOME%\version2\samples\Java
    • Linux: $SOAM_HOME/version2/samples/Java
    1. From the Eclipse menu, select File > Import.

      The Import dialog appears.

    2. Double-click General. Double-click Existing Projects into Workspace.
    3. Choose Select root directory. Click Browse. Browse to the SampleApp directory in IBM Spectrum Symphony Developer Edition. Click OK.
    4. Click Finish.
  13. Import samples into Eclipse.
    1. Create and validate the service package:
      1. In the Eclipse Package Explorer, right-click on the sample project SampleApp. Select Symphony Operations > Create Deployment Package
      2. Enter SampleAppService.zip as the package name in the Specify the package name box.
      3. Click Browse to select the path where the service package will be stored.
      4. Click Browse to specify the main service class name. Enter MyService in the box. Click OK.
      5. Select *.common.jar and *.service.jar files in the Package name or file name list.
      6. Click Create and Validate Service Package.

        After creating and validating the service package, the following message is displayed:

        Compressed package_path/SampleAppService.zip successfully!

        The service package is valid and it is ready to be deployed to DE.

      7. Click Finish. The next step is to create an application profile and register your application.
    2. Add the application to IBM Spectrum Symphony Developer Edition:
      1. In the Package Explorer, right-click on project SampleApp. Select Symphony Operations > Add/Remove Application.
      2. Click Validate to test the port connection to the IBM Spectrum Symphony Developer Edition cluster management console. (The plug-in pings the URL of the cluster management console to verify the connection.)
        Note: If the port is already in use, specify a different port number in file vem_resource.conf and enter it in the Please specify the port number text box.
      3. Once the cluster management console server replies, click OK.
      4. In the Package Explorer, right-click on project SampleApp. Select Symphony Operations > Add/Remove Application.

        The IBM Spectrum Symphony Developer Edition cluster management console displays.

      5. Select Add an application. Click Continue.
      6. Select Use existing profile and add application wizard. Click Browse and navigate to the location of the SampleAppJava.xml application profile. Click Continue.
      7. Click Browse and navigate to the location of the service package. Select the service package file SampleAppService.zip. Click Continue.
      8. Click Confirm to accept the application profile definitions.

        The project wizard creates your application and registers it within IBM Spectrum Symphony.

      9. Click Close.
      10. You can now run your client and submit workload to your IBM Spectrum Symphony application. In the Package Explorer, right-click com.platform.symphony.samples.SampleApp.client class. Select Run As > Java Application. In the Select Java Application dialog, select SyncClient - com.platform.sysmphony.samples.SampleApp.client. Click OK.