loading table of contents...

5.4.4. Client-Side Actions

A client-side action consists of a client-side and a server-side implementation, so it's running partly on both sides. Whereas client-side actions run on behalf of the client user, server-side actions run on behalf of the workflow user. While the client part of the action is running, the server side transaction is still active. Client actions always have a timeout after which the action is aborted on the server side, the client side is not affected by this. ClientActions should not require user interaction, if possible, to save precious server resources.

Precisely, a client action consists of three parts:

  • A server-side action.

  • A client-side event listener.

  • A client-side command to execute.

The three parts will be executed in the following way:

  • Define the action from the workflow definition using the class attribute.

  • The CoreMedia Workflow Server executes the server-side stub. It creates the parameter list which it includes in the event.

  • The event will be received by the client which calls the handle() method of the client-side event listener.

  • The event listener has to return a callback ID to the server. You can evaluate the event and start some action from the event listener. For example, the event listener belonging to the Site Manager will execute the action the server noticed in the event.

[Caution]Caution

Using the Unified API, it is not possible to write the server-side parts of new client side actions. You still need the Workflow API for this. Note, however, that client-side actions can now be replaced by Unified API server-side actions in many cases, because the Unified API allows you to act on behalf of a particular user without having to open a separate connection.

Interface to implement

Basically, the server-side stub of a client-side action must implement the interface com.coremedia.workflow.WfAction. For convenience and to hide the details how events are created and dispatched, you must subclass com.coremedia.workflow.common.actions.AbstractClientAction. This class already includes implementations of all needed getter and setter methods, uses a condition as guard and contains all the event logic. AbstractClientAction also implements a default timeout for a client action. The default timeout time is 30 seconds and can be configured using the attribute timeout in the workflow definition. In Example 5.1, “Example of the server-side stub for a client-side action” you see a sample action which extends AbstractClientAction.

Server Side

The server-side implementation of a client action is a stub which:

  • Assembles the argument list and passes it to the client via an event. The AbstractClientAction class includes the command and GUI parameters in the argument list. The command is the one used as the parameter in the call of the super() constructor.

  • Receives the clients result and creates a WfActionResult from it.

Custom clients, that are not event driven, have to be aware that while performing a Task.accept or Task.complete operation on behalf of connected clients there may be callbacks of the client action for the pending call. The callbacks have to be executed before the server call can return.

1:  public class DemoClientAction extends AbstractClientAction
2:  {
3:    public DemoClientAction() {
4:      super("com.customer.example.workflow.action.
                   DemoActionCommand");
5:    }
6:  
7:    protected HashMultiMap 
8:    processArguments(WfTaskInstance taskInstance, 
                                   HashMultiMap map)
9:      throws WfException {
10:     map.put("documentType", "Article");
11:     return map;
12:   }
13: 
14:   protected WfActionResult 
15:   processResult(WfTaskInstance taskInstance, 
                             WfClientActionResult result) 
16:     throws WfException {
17:     // result processing...
18:     return new WfActionResult(values, warnings, success);
19:   }
20: }

Example 5.1. Example of the server-side stub for a client-side action


Line 1: Use the AbstractClientAction instead of the WfAction interface.

Line 3 - 5: The constructor of your server stub. The constructor of the super class is called with the command as a parameter which should be executed on client side. This command is automatically included in the event send to the client.

Line 7 - 12: This processes the arguments which will be included in the event. In line 10 the parameter docmentType is added to the HashMultiMap. This map already contains WfClientActionListener.GUI and WfClientActionListener.COMMAND as default entries.

Line 14 - 19: This process the result that has been received from the client.

Client Side

The client-side must have a WfClientActionListener installed (see Example 5.2, “Example of an action listener”) which handles the incoming action events.

  • The callback ID obtained by WfClientActionEvent.getCallbackId must be returned in the actions result so that the CoreMedia Workflow Server can associate request and callback.

  • WfClientActionEvent.getParameters returns the call parameters as encoded by the server side stub. For the previous example, the parameters would contain the strings documentType and Article.

  • The event's other methods are reserved for internal use.

  • All predefined client actions use a property/value encoding for the action parameters. Everything is encoded as a java.lang.String.

Note, that the Site Manager has a generic client listener, that tries to find and execute an appropriate hox.corem.editor.commands.Command. Have a look at the Editor Developer Manual for details.

1:  package com.customer.example.workflow.action;
2:  
3:  import com.coremedia.workflow.*;
4:  import 
     com.coremedia.workflow.common.actions.ClientActionResult;
5:
6:  public class DemoClientActionListener implements 
     WfClientActionListener {
7:    
8:      public DemoClientActionListener() {
9:      }
10:    
11:      public WfClientActionResult 
           handle(WfClientActionEvent actionEvent) {
12:        String[] parameters = actionEvent.getParameters();
13:        System.out.println("parameters.length="+
                                        parameters.length);
14:        for (int i=0; i < parameters.length; i++) {
15:          System.out.println("parameters["+i+"]="+
                                          parameters[i]);
16:        } 
17:        return new ClientActionResult(actionEvent.
                                getCallbackId());
18:      } 
19:  } 

Example 5.2. Example of an action listener


Line 6: The client listener must implement WfClientActionListener.

Line 11: This method must be implemented. It gets the event as a parameter. Here you can implement your functionality evaluating the information from the event.

Line 12 -15: This is only a simple example. The parameters of the event are read in an array and are printed out.

Line 17: An important line: The client listener must return a ClientActionResult containing at least the callback ID. It is also possible to return more information to the server. See the CoreMedia Workflow API documentation for more details on ClientActionResult.

Command for the Site Manager

In Example 5.3, “Command executable on the Site Manager” you see an example command which is executed on the client when an appropriate event is received by the event listener of the Site Manager. For this, the action defined in Example 5.1, “Example of the server-side stub for a client-side action” has to be executed.

1:  package com.customer.example.workflow.action;
2:  
3:  import hox.corem.editor.toolkit.*;
4:  
5:  public class DemoActionCommand implements Command {
6:    
7:    public boolean execute(Context context, Target target) {
8:      System.out.println("DemoActionCommand.execute() " +
                                    "context="+context+ " " +
                                    "target="+target);
9:      return true;
10:   }
11:   
12:   public boolean isExecutable(Context context, Target target) {
13:     return true;
14:   }
15:   
16: }

Example 5.3. Command executable on the Site Manager


Line 3: You need to import this package because you are working on the Site Manager.

Line 5: The name of the class must be the one called from the server.

Line 7 - 10: This is the method in which you implement your actual action. The example action only prints the content of context and target and returns true.

Line 12 - 14: This method returns whether the command is executable with the given target and context or not.