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.
You review the sample client application code to learn how you can create a synchronous client application.
%SOAM_HOME%\5.1\samples\DotNet\CS\SampleApp\sampleApplication.NET.<version>.sln
%SOAM_HOME%\5.1\samples\DotNet\CS\SampleApp\sampleApplication.NET64.<version>.sln
%SOAM_HOME%\5.1\samples\DotNet\CS\SampleApp\SyncClient\SyncClient.cs
%SOAM_HOME%\5.1\samples\DotNet\CS\SampleApp\Common\MyMessage.cs
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\SampleApp\SampleAppDotNetCS.xml
The client application sample sends 10 input messages with the data “Hello Grid !!”, and retrieves the results. The client application is a synchronous client that sends input and blocks the output until all the results are returned.
The service takes input data sent by client applications, returns the input data you have sent and replies "Hello Client !!".
In SyncClient.cs, when you initialize, you initialize the Symphony client infrastructure. You initialize once per client.
Your client application needs to handle data that it sends as input, and output data that it receives from the service.
In MyMessage.cs, we implement methods to set and access the data, such as the message string, task ID, and sync flag.
The MyMessage class must be marked with the serializable attribute. The .NET Framework provides the ability to serialize object data for the purpose of passing it by value across application domains. Making the class serializable means that the object can be deconstructed so that it can be passed through the network to the service. Similarly, the object can be reconstructed when it is received by the service.
To send data to be calculated in the form of input messages, you connect to an application.
You specify an application name, a user name, and password. The application name must match that defined in the application profile.
For Symphony Developer Edition, there is no security checking and login credentials are ignored—you can specify any user name and password. Security checking is done however, when your client application submits workload to the actual grid.
The default security callback encapsulates the callback for the user name and password.
It should be emphasized that the creation and usage of the connection object 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 middleware resources.
A session is a way of logically grouping tasks that are sent to a service for execution. The tasks are sent and received synchronously.
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 description. This is optional. The session description can be any descriptive name you want to assign to your session. It is for information 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. When creating a synchronous session, set the flag to SessionFlags.AliasSync. This flag indicates to Symphony that this is a synchronous session.
As is the case with the connection object, the creation and usage of the session object, i.e., 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 middleware resources.
In this step, we create 10 input messages to be processed by the service. We call the MyMessage constructor and pass three input parameters: ID (taskCount), the Boolean value (true) to indicate synchronous communication, and a message string ("Hello Grid !!"). 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.
Pass the number of tasks to the FetchTaskOutput() method to retrieve the output messages that were produced by the service instance. This method blocks until the output for all tasks is retrieved. The return value is an enumeration that contains the completed task results.
Iterate through the task results and extract the messages using the GetTaskOutput() method. Display the task ID, internal ID (taskCount), and the output message.
Any exceptions thrown take the form of SoamException. Catch all Symphony exceptions to know about exceptions that occurred in the client application, service, and middleware.
The sample code above catches exceptions of type SoamException.
Always uninitialize the client API at the end of all API calls. If you do not call uninitialize, the client API remains in an undefined state and resources used by the client are held indefinitely.
For a service to be managed by Symphony, it needs to be in a container object. This is the service container.
In SampleService.cs, SampleServiceContainer inherits from the base class ServiceContainer.
Symphony calls OnInvoke() on the service container once per task. Once you inherit from the ServiceContainer class, implement handlers so that the service can function properly. This is where the calculation is performed.
To gain access to the data set from the client, you call the GetTaskInput() method on the task context. The 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.
In this sample, we use the StringBuilder object to build the output message, which includes the input message that is echoed back to the client. Since we are using the same service for sync and async clients, the if statement is used to indicate that the message was sent from a sync client. When the string in the output message is completely assembled, pass it to the SetTaskOutput() method, which sets the task output message that is sent to the client.