Commands

In the PureWeb SDK, commands are simply a request sent from a client to a service. Commands may include an optional response sent from the service back to the client.

Commands are one of the primary means that the SDK uses to link client-side interface elements into service-side application logic.

Their anatomy is fairly simple:

  • The service registers a function as a command handler to receive requests.
  • A client sends a request, and may register a callback.
  • An API call is sent to the previously registered handler, including any data that was attached to the request.
  • Once the function is complete, the API sends response data back to the client for processing, if any.

The function executed by the command handler doesn't have to be pre-existing in the application logic, you can add it in your service specifically to address the needs of a PureWeb client. Commands therefore allow you to customize the feature set of your web and mobile clients as required.

Commands can originate from any client, but are only sent from a single client to the service. This limits their use: they are not suitable, for example, in collaborative scenarios where interface element properties need to be shared by several users. For situations where commands aren't appropriate, use application state instead.

Handling Commands on the Service

On the service side, there are three parts to setting up commands:

  • define the command handler: this is the function that is triggered when the service receives the defined command
  • register the command handler: this is the code that specifies which command handler will fire for which command string
  • populate the response object: this is optional, the command handler provides a response object which can be populated with information for the client application upon completion of the command request

Registering a Command Handler

Registering a command handler consists in a single line of code that associates the handler to a specific command name.

You can add the handler to either the UI thread (AddUiHandler) or the I/O thread (AddIoHandler).

Here’s an example, taken from the Scribble sample application:

C++

CScribbleApp::StateManager().CommandManager().AddUiHandler("Clear", Bind(this, &CScribbleView::OnExecuteClear));

.Net

Program.StateManager.CommandManager.AddUiHandler("Clear", OnExecuteClear);

Java

stateManager.getCommandManager().addUiHandler("Clear", new OnExecuteClear());

In the example above, when a user clicks on the Erase All button to restore the canvas to its blank state, the client application sends a Clear command. The command handler OnExecuteClear is called whenever the Clear command is received from the client.

To ensure that all commands are correctly caught and handled by the service application, command handlers should be added early on in the program initialization.

The client APIs also include RemoveUiHandler functions. Command handlers should be removed early in the termination of the service application.

Defining the Service-Side Function

Normally, the function that the client command is asking the service to execute will already exists in the service application. However, the SDK allows you to expand the functionality of your original service application. If needed, you can therefore create a new function in your service to respond to a command that addresses a specific need of a PureWeb client application.

Populating Command Responses

Client applications can register an optional response callback function in their queueCommand call. Instructions for writing client-side commands are provided further down this page.

If the client has specified a callback, the service application can define (populate) response parameters for that callback.

  It is possible to send binary data as a response to a command, but in this case the data must be encoded as a Base64 string.

C++

void CScribbleView::OnExecuteClear(Guid sessionId, Typeless command, Typeless responses)
{
    //Add responses to the provided response object.
	responses.Add("Foo");
}

.Net

private void OnExecuteClear(Guid sessionId, XElement command, XElement responses)
    {
	    //Add responses to the provided response object.
		responses.Add("Foo");
	}			

Java

private class OnExecuteClear implements CommandHandler
{
    public void invoke(UUID sessionID, Element command, Element responses)
	{
	    //Add responses to the provided response object.
		responses.Add("Foo");
	}
}

Any content added to responses will be made available to the client callback function in the form of an XML element.

You can see a more complex example of this in the screen capture example for the Resource Manager.

Sending Commands from the Client

In the client application, commands are sent to the service application using the client API's queueCommand function. This function adds the command, including any of its arguments, to the outgoing command queue, which delivers the commands.

The command name registered on the client must match the name as set up in the service side precisely, otherwise the command will not be correctly handled.

There are two sets of code examples below: one for a basic command with no arguments and no callback, and a more complex command with all of these.

Examples of Simple Commands

iOS

NSDictionary *params = [NSDictionarydictionaryWithObjectsAndKeys:@"Value1",@"Key1",@"Value2",@"Key2"];
[[PWFramework sharedInstance].client queueCommand:@"FooCommand" withParameters:params];

Android

Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("argumentName", “firstArgumentValue”);
framework.getWebClient().queueCommand("Clear", parameters);			

Silverlight

Framework.Instance.Client.QueueCommand("Clear");

Example of Commands with Arguments and Response Callback

Below are examples of commands with a response callback.

HTML5

In this Javascript/HTML5 example, the callback is used to alter the user interface:

<script type=’text/javascript’>
    function clearCanvas() {
	    pureweb.client.getClient().queueCommand("Clear", null, clearCallback);
	}

	function clearCallback()  {
	    document.getElementById('clearButton').innerHTML = 'Cleared';
	}
</script>

<button id=”clearButton” onclick="clearCanvas();">Clear</button>			

In this example, the queueCommand function takes a callback, which locates the relevant button on the page and changes its label to indicate that the command was successfully processed by the service.

iOS

[[PWFramework sharedInstance].client queueCommand:@"Ping" onComplete:^(PWCommandResponseEventArgs *args)
{
	PWXmlElement* resp = args.response;
	NSLog(@"Response was: %@", resp);
}];

Linking UI Elements to Commands

Commands can be used to link native user interface elements such as buttons and drop-down boxes to the service-side application logic.

For example, in the Scribble sample application, when the end user interacts with the interface elements for erase all the existing scribbles on the canvas, the client sends a command to the service, which triggers the service to execute the function associated with clearing the screen.

The examples below illustrate how client-side native interface elements can use commands to control the behaviour of an application.

Example of a Native UI Element Using a Command

The example below illustrates how a client-side native element can use the queueCommand function to point to the service-side application logic.

HTML5

This example uses the native HTML5 <button> element to create the Erase All button. When a user clicks this button, the client executes the clearCanvas function, which uses queueCommand to send the Clear command to the service.

<script type=’text/javascript’>
	function clearCanvas() {
		pureweb.client.getClient().queueCommand("Clear");
	}
</script>

<button onclick="clearCanvas();">Erase All</button>		

iOS

This example uses the Objective-C native elements to create a Set Counter to Five button. When a user taps this button, the client executes the sendFiveCommand function, which uses queueCommand to send the SendFiveCommand command to the service.

- (void) viewDidLoad
{
    UIButton *exampleButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	exampleButton.frame = CGRectMake(100, 100, 300, 30);
	exampleButton.titleLabel.text = @"Set Counter to Five";

	[exampleButton addTarget:self action:@selector(sendFiveCommand) forControlEvents:UIControlEventTouchUpInside];

	[self.view addSubview:exampleButton];
}

- (void) sendFiveCommand
{
	[[PWFramework sharedInstance].client queueCommand:@"SendFiveCommand" withParameters:@{@"Value" : @(5)}];
}

Flex

This example uses the Flex native element to create the Erase all button. When a user clicks this button, the client executes the Clear function, which uses queueCommand to send the Clear command to the service.

<mx:Button id="eraseAllBn" label="Erase all" click="viewModel.clear()" />

public function clear():void
{
    framework.client.queueCommand("Clear");
}