SharingData: Developing a C# client and service to share data among tasks

Goal

This tutorial walks you through how to develop a client application and service to share data among all tasks in a session. The data is shared by all invocations of tasks within the same session.

You lean how to use different data objects for input, output, and common data.

At a glance

Before you begin, ensure you have installed and started Platform Symphony Developer Edition.
  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

Build the sample client and service

  1. Navigate to %SOAM_HOME%\5.1\samples\DotNet\CS\SampleApp.
  2. Open the Visual C#.NET solution file that is supported by your version of Visual Studio.
  3. Build the .NET solution by pressing ctrl+shift+B.

    Compiled executables and libraries are in the %SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\output directory.

    Note:

    %SOAM_HOME% is an environment variable that represents the Symphony DE installation directory; for example, C:\SymphonyDE\DE51.

Package the sample service

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

Note:

Make sure the dlls are included in your service package.

  1. Go to the directory that contains the files for the service package:
    cd %SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\output
  2. Locate the SharingDataServiceDotNetCS.exe and Common.dll files. Add these files to an archive using a compression program such as gzip. Save the archive as SharingDataServiceDotNetCS.zip in the current directory.

Add the application

When you add an application through the DE PMC, 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. Click Symphony Workload > Configure Applications.

    The Applications page displays.

  2. Select Global Actions > Add/Remove Applications.

    The Add/Remove Application page displays.

  3. Select Add an application, then click Continue.

    The Adding an Application page displays.

  4. Select Use existing profile and add application wizard, and browse to your application profile.
  5. Select your application profile xml file, then click Continue

    For SharingData, you can find your profile in the following location:

    • .NET:

      • %SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\SharingDataDotNetCS.xml

    The Service Package location window displays.

  6. Browse to the service package you created in .gz, .zip, or tar.gz format and select it, then, select Continue.

    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 Platform Management Console. Your new application is displayed as enabled.

Run the sample client and service

To run the service, run the client application. The service that a client application uses is specified in the application profile.

Before running the sample client, ensure that the Client project is set as the StartUp project in Visual C#.NET.

Press F5 to run the application.

The client starts and the system starts the corresponding service. The client displays messages in the console window indicating that it is running.

Walk through the code

Review the sample code to learn how you can create a client and service that uses common data.

Locate the code samples

Solution file (Visual Studio)

%SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\sharing_data_<version>.sln

or

sharing_data64_<version>.sln

where <version> is the version of Visual Studio.

Client

%SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\Client\SyncClient.cs

Input, output, and data objects

%SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\Common\

Service
%SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\Service\SampleService.cs
Application profile

The service required to compute the input data along with additional application parameters are defined in the application profile:

%SOAM_HOME%\5.1\samples\DotNet\CS\SharingData\SharingDataDotNetCS.xml

What the samples do

The client creates a session with common data. It sends 10 input messages, and retrieves the output. The client then outputs "Hello Grid !!".

The service takes input data sent by client applications, returns the input data you have sent and replies "Hello Client !!" followed by the common data appended to the message. The service uses OnSessionEnter() to define attributes global to the session.

When to use common data

Common data is data that can be made available to service instances for the duration of a session.

Use common data when you need to set up the initial state of a service, and you only want to do it once, not on every task. Common data is useful for passing data from a client to a service. The service loads the data when the session is created.

You can use common data, for example, to set the environment in the service that is common to all tasks in a session. This way you only need to set the environment once, when the session is created.

Symphony attempts to use the same service instance for all tasks in a session. A service instance is made available to other sessions only when session workload completes, a session is closed or aborted, or when another session of higher priority is assigned the service instance.

Prepare common data in your client

Declare and implement the Message objects

In the synchronous client tutorial, input and output message objects were the same object. In this tutorial, different objects represent input and output. In addition, we are creating an additional object to represent common data.

Remember to mark your message and data handler classes with the Serializable attribute. This allows the objects to be serialized for transfer across the network.

Use the common data object when creating a session

As in the synchronous client tutorial, initialize the client and connect to the application. Then, create your session to group tasks.

When creating a session, use the common data object to pass data from the client application to the service.

In SyncClient.cs, we create a session and pass the common data object via the SessionCreationAttributes object.

...
                    // Set up our common data to be shared by all task 
                    // invocations within this session
                    MyCommonData commonData = new MyCommonData();
                    commonData.StringMessage="Common Data To Be Shared";
                    Session session = null;
                    try
                    {
                        // Set up session attributes
                        SessionCreationAttributes attributes = new
                        SessionCreationAttributes();
                        attributes.SessionName="mySession";
                        attributes.SessionType="ShortRunningTasks";
                        attributes.SessionFlags = SessionFlags.AliasSync;
                        attributes.SetCommonData(commonData);
                        // Create a synchronous Session
                        session = connection.CreateSession(attributes);
...

Continue with your client as usual

Now you can proceed the same way as in the synchronous client tutorial:

  • Send input data to be processed

  • Retrieve output

  • Close the session

  • Close the connection

  • Catch exceptions

  • Uninitialize

Access common data in your service

Define a service container and get data from the session

As in the basic service tutorial, first define a service container. Then retrieve the common data sent by the client by implementing OnSessionEnter(). This method is called once by the middleware for the duration of the session to bind the service instance to the session.

In SampleService.cs, we use OnSessionEnter() to get common data and store it for later use within the scope of the session.

...
public override void OnSessionEnter(SessionContext sessionContext)
{
       // get the current session ID (if needed)
       m_currentSID = sessionContext.SessionId;
        
       // populate our common data object
       m_commonData = sessionContext.GetCommonData() as MyCommonData;
       if(m_commonData == null)
       {
           throw new SoamException("Have got wrong type of CommonData object."); 
       }
} 
...

Process the input

In this example, each time the OnInvoke() method is called by the middleware, we append the common data to the output string. We then set our output message as usual to send common data back with each of the replies.

...
public override void OnInvoke(TaskContext taskContext)
{
            // estimate and set our runtime
            MyOutput outMsg = new MyOutput();
            outMsg.RunTime = DateTime.Now.ToString();
            // Get the input that was sent from the client 
            MyInput inMsg = taskContext.GetTaskInput() as MyInput;
            
            if(inMsg == null)
            {
                throw new SoamException("The service attempted to access the wrong type
                of InputMessage object."); 
            }
            // We simply echo the data back to the client 
            outMsg.Id = inMsg.Id;
            StringBuilder reply = new StringBuilder();
            reply.Append("Client sent : ");
            reply.Append(inMsg.StringMessage);
            reply.Append("\nSymphony replied : Hello Client !! with common data (\"");
            reply.Append(m_commonData.StringMessage);
            reply.Append("\") for session(");
            reply.Append(String.Format("{0}", m_currentSID));
            reply.Append(")");
            outMsg.StringMessage = reply.ToString();
            // Set our output message 
            taskContext.SetTaskOutput(outMsg);
}
...

Perform any data cleanup

After processing the input, use the OnSessionLeave() call to free the data for the session. The OnSessionLeave() method is called once by the middleware for every session that is created.

...
public override void OnSessionLeave()
{
       // free our data
       m_currentSID = null;
       m_commonData = null;
}
...

Run the container and catch exceptions

As with the basic service, run the container in the service main and catch exceptions.

...
static int Main(string[] args)
{
       // Return value of our service program
       int returnValue = 0;
       try
       {
            // Create a new service container and run it
            SampleServiceContainer myContainer = new SampleServiceContainer();
            myContainer.Run();
       }
       catch( Exception ex )
       {
            // report exception
            Console.WriteLine( "Exception caught ... " + ex.ToString() );
            returnValue = -1;
       }
       return returnValue;
}
...