Symphony COM API supports synchronous message input and output.
Symphony COM API is intended for clients written with VB6.0, VB Script, or VBA, and services written with C++, Java, or .NET.
This tutorial walks you through the sample client application code, then guides you through the process of building, packaging, and deploying the associated service.
This tutorial is based on the VBA client code in the SoamExcelSample.xls spreadsheet. The sample code demonstrates how to connect to an application using the COM API.
To help grasp the concepts, the spreadsheet actually contains two code samples. The first sample shows how a simple calculation is performed locally within the spreadsheet itself. The second sample extends the first sample to a grid-ready version by implementing the computational logic as a C++ service that can run on compute hosts in a Symphony cluster.
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 will review the sample client application code to learn how you can create a synchronous client application that makes calls to the Symphony COM API.
The first sample implements computational logic that is processed locally in the spreadsheet. It calculates the standard deviation of 32 sets of values and populates the spreadsheet with the results.
The second sample features a synchronous client that sends 32 input messages to a Symphony service via the COM API. The service takes the input data, performs the calculations, and returns the results.
Since both samples implement the same computational logic, the results are identical.
This sample executes locally on the Excel spreadsheet and all the code is contained within the spreadsheet.
The CommandButton2_Click event encapsulates the client logic. Follow these steps to locate the CommandButton2_Click event code in the spreadsheet:
The taskToSend variable represents the number of input values for the standard deviation algorithm.
We initialize a range of cells where the results will be displayed on the spreadsheet. Next, we declare and initialize a two-dimensional array (values) to hold the results. The array indices correspond to the rows and columns for displaying the results on the spreadsheet.
A for loop increments the row index of the array and cycles through the inputs for the standard deviation calculations, which are read from the spreadsheet. An amplification factor is included in the input to the StandardDeviation() function to increase the input value, if required. The return value of the function is assigned to the array which, in turn, is assigned to the range object that displays the results in the spreadsheet cells.
The StandardDeviation() function contains the algorithm for calculating the standard deviation. The data set that the algorithm works on is derived from each input value. The result is passed back to the CommandButton2_Click event code and displayed on the spreadsheet.
This sample invokes the COM API to access a Symphony service.
The CommandButton1_Click event encapsulates the client logic. Follow these steps to locate the CommandButton1_Click event code in the spreadsheet:
To send data to a service for processing, you must first connect to an application. You specify an application name, a user name, and password. The application name must match the one defined in the application profile. In this sample, the application name is read from the spreadsheet.
For Symphony Developer Edition, there is no security checking and login credentials are ignored—you can specify any user name and password, such as "Guest". 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.
A session is a way of logically grouping tasks that are sent to a service for execution. In this sample, the tasks are sent and received synchronously.
When creating a session, you need to specify the session attributes by using the CSoamSessionCreationAttributes object. We create a CSoamSessionCreationAttributes object called attributes and set three parameters in the object.
The first parameter is the session name. This is optional. It can be any descriptive name you want to assign to your session. It is for information purposes.
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.ReceiveSync. This flag indicates to Symphony that this is a synchronous session.
The taskToSend variable represents the number of individual data sets (messages) that will be sent to the service. Next, we initialize a range of 32 cells where the results will be displayed on the spreadsheet. We declare and initialize a two-dimensional array (values) to hold the results. The array indices correspond to the rows and columns for displaying the results on the spreadsheet.
The next step is to create the input messages to be processed by the service. We call the MyMessage constructor and pass four input parameters. Note the input parameters:
The first parameter is the number of samples. This value is the input data for each standard deviation calculation performed by the service.
The second parameter is the line number. This value represents the row in the spreadsheet. As each message is sent, the row value is incremented until all the messages are sent.
The third parameter is the column number, which represents the column in the spreadsheet. This value is fixed at 0 since the results will be displayed in a single column. The column value is echoed back to the client in each output message from the service.
The fourth parameter is an input message string. It is not used in this sample.
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.
For each message that is sent to the service, call the FetchTaskOutput() method to retrieve the output message that was produced by the service. By passing a "1" to the method, we are retrieving only one result at a time. Consequently, the return value is an enumeration containing only one completed task result. This was done for demonstration purposes only. Typically, you would pass a value to the FetchTaskOutput() method that represents the total number of tasks sent to the service.
Check that the output for each task was successful before using the PopulateTaskOutput() method to extract the message; otherwise an exception is thrown. Load the result into the array and assign the array to the range object so that the result can be displayed in the appropriate spreadsheet cell.
In this sample, calculations on input data are performed by a program that is implemented as a service. A service can be deployed on numerous compute hosts and run as concurrent service instances. For a service to be managed by Symphony, it needs to be in a container object. This is the service container.
In ExcelSampleService.cpp, MyServiceContainer inherits from the base class ServiceContainer.
The middleware triggers the invocation of the ServiceContainer's onInvoke() handler every time a task input is sent to the service to be processed. You must implement the onInvoke method to process the task input, perform your computation, and return the result of the computation to the client.
To gain access to the input message from the client, you call the populateTaskInput() 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.
Create the output message and set the following message properties. The values for these properties are read from the input message and echoed back to the client.
Pass the input data (m_number_of_samples) to the StandardDeviation() method and format the output message string with the result. Passing the output message to the SetTaskOutput() method generates the task output message that is sent to the client.
The service is implemented within an executable. As a minimum, we need to create an instance of the service container within our main function and run it.
The computational logic of the service is implemented in the StandardDeviation() method. The method generates a data set of integers in the range of 0 up to the numberOfSamples value and applies a standard deviation algorithm to it.