Service connectors

The service connectors framework allows developers to create their own connectors and to bind them to events thrown by various objects involved in the document manipulation.

The framework gives a standard way of defining :

  • an XML definition file: a configuration based on standard screen definition using sections and fields and the entry points within the Studio.
  • a service connector editor class: dynamic behavior to edit the configuration properties.
  • a service connector runtime class: class to use at runtime execution.
  • an XML resource file: localized string.

Connector definition

A connector is a package of several connectors (treatments or services). Any connector included in this package use the same type of connection.

<connectors>
	<connector name="navigation" version="1.0" company="Visiativ Software">
		...
	</connector>
</connectors>	

A connector is defined with the following attributes:

  • name: the system name of the connector. It should be unique on the Process Server;
  • ref-connection: the connection reference attribute. It should be valid;
  • version: the version of the connector;
  • company: the company which has developed the connector.

Service definition

Service connectors can be bind to several elements:

  • workflows
    • workflow;
    • resource definition and its associated properties;
    • diagram and some of its elements: tasks, actions and embedded processes;
    • forms and their fields.
  • dynamic tables
    • resource definition and its associated properties;
    • forms and their fields.
  • data universe tables
    • resource definition and its associated properties;
    • forms and their fields.

XML definition file

The XML service connector definition file should be deployed on the custom/connectors folder. Its name must be unique on the Process server. To prevent name conflicts it is recommended to use the following template: companyName-connectorsType.xml (e.i. visiativ-education.xml). This XML definition file provides all the necessary information to describe a service connector:

  • Service connector: it is defined with the following attributes:
    • name: the system name of the service connector;
    • execution: allows to specify if the connector is synchronous or asynchronous.
    • useExternalDataConnection: gives the choice to the designer to either select a connection or use the default configuration of the Process server.
      <connectors>
          <connector name="navigation" version="1.0" company="Visiativ Software">
              <services>
                  <service name="hideElements" useExternalDataConnection="false">
                      ...
                  </service>		
              </services>
          </connector>
      </connectors>
  • Connector runtime class: the execution unit called while changing state on a process document.
  • Connector configuration: a set of required fields to configure a service connector.

Runtime class

A runtime class is a Java class which will be called by the framework when a user changes the state of a process document. A runtime class must extend the com.axemble.vdoc.sdk.connectors.BaseServiceConnector class.

By creating a service connector runtime class you need to implement the following method:

  • execute(): the execute method receives the context of the user, the current process document (IWorkflowInstance) and the custom DOM element (retrieved from the XML configuration). The return value is an int value which can take one of the following values: IExecuteStatus.STOP, IExecuteStatus.CONTINUE, IExecuteStatus.STOP_ASYNCHRONOUS.

Three other methods could be overridden:

  • beforeCompletion(...): called just before committing the current transaction.
  • afterCompletion(...): called just after either a commit or a rollback operation on the current transaction.
  • asyncExecute(...): this method is called if the treatment connector has been set as an asynchronous treatment (set the execution attribute to asynchronous).

A runtime class is declared as follows:

<connectors>
	<connector name="navigation" version="1.0" company="Visiativ Software">
		<services>
			<service name="hideElements" useExternalDataConnection="false">
				<class qualifiedName="com.axemble.education.connectors.navigation.HideElementsServiceConnector" />

Configuration definition

The configuration definition allows developers to specify a list of <field> tags the designer could use to properly configure a treatment connector. These fields can be categorized into <section> tags. To make the configuration more dynamic an editor class could be specified.

<configuration>
	<class qualifiedName="com.axemble.education.connectors.navigation.HideElementsServiceConnectorEditor" />
	<section name="settings" label="service.navigation.hideElements.section.settings.label">
		<fields>
			<!-- hide elements -->
			<field name="fldElementsChoices" ctrl="textselectlist" mode="write" throw-events="true" mandatory="true" string-value="fromValue">
				<options>
					<option key="fromValue" labelid="LG_FROM_VALUE" />
					<option key="fromField" labelid="LG_FROM_FIELD" />
				</options>
			</field>
			<field name="fldElementsValue" ctrl="text" mandatory="true" maxlength="64" defaultValue="" />
			<field name="fldElementsField" ctrl="selector" mandatory="true" screen="Property" method="select" multiple="true" />
			<field name="fldValue" ctrl="checkbox" />
	   </fields>
   </section>
</configuration>

Editor class

An editor class is a Java class which allows developers to produce dynamic behaviors on the treatment connector configuration properties (XML definition file). An editor class must extend the com.axemble.vdoc.sdk.connectors.BaseConnectionEditor class.

The editor class works in the same way as the document or resource extensions. You can override the following standard methods:

  • init(): called at the instantiation time.
  • onBeforeLoad(): called just before the screen is loaded on the server side.
  • onAfterLoad(): called just after the screen is loaded on the server side.
  • onBeforeSave(): called just before saving the document.
  • onAfterSave(): called just after saving the document.

Specifically to treatment connector editor class, the connector Framework provides the following methods:

  • getCustomConfiguration(): returns the DOM element representing the custom tag within the configuration tag.
  • getParentContext(): returns the current IWorfklow object as a IConnectorParentContextSupport.
  • getResource(): allows to manipulate the document as a @IResource object.
  • getResourceController(): allows to to interact with the user interface.
  • getForm(): returns the current XMLForm screen.

An editor class is declared as follow:

<configuration>
	<class qualifiedName="com.axemble.education.connectors.navigation.HideElementsServiceConnectorEditor" />

Inputs

The <inputs> tag allows developer to specify which named values should be made available while the service is running. In order to make some named values available you need to declare the inputs as follow:

<inputs>
	<input name="iResource" type="com.axemble.vdoc.sdk.interfaces.IResource" />
	<input name="iWorkflowInstance" type="com.axemble.vdoc.sdk.interfaces.IWorkflowInstance" />
</inputs>

Outputs

The <outputs> tag allows developer to specify which named and localized values are made available for the designer. In order to make some values available you need to declare the outputs as follow:

<outputs>
	<output name="result" type="java.lang.Boolean" />
	<output name="error" type="java.lang.String" />
	<output name="errorMessage" type="java.lang.String" />		            
</outputs>		        

And use the addOutput method within the runtime class as follow:

this.getServiceOutputs().addOutput( "result", Boolean.FALSE );
this.getServiceOutputs().addOutput( "errorMessage", "None event found!" );
this.getServiceOutputs().addOutput( "error", -900 );

Entry points

The Studio makes some of its screen parts available for including new features (workflow library and connectors library). The <entry-points> tag allows developers to specify where a service will be included and how it will be categories within a specific screen part. Be aware this feature is not available yet in the current version.

<entry-points>
	<connectors-library familyName="education" />
</entry-points>

Supported events

The Studio declares several trigger events available on each element such as workflow, resource definition, property, form, and field. The available trigger events are very similar to the methods usually fired on document extensions and on JavaScript triggers. The connector Framework keeps the same life cycle for the trigger events as the callbacks executed on document extensions and JavaScript triggers.

The Studio declares two types of trigger events:

  • back-end trigger events: thrown either while a user manipulates a document or during the execution of an agent;
  • front-end trigger events: thrown while a user manipulates a document.

List of back-end trigger events

System name Label Description
onAbortWorkflowInstance During cancellation The connector will run on process cancellation.
onRemindWorkflowInstance During the operators remind The connector will run on remind of the current step(s) operators.
onCreateEmbeddedWorkflowInstance During the embedded process creation The connector will run on the creation of the embedded process document in the process.
onRemoveWorkflowInstance At the end of deletion of the process document The connector will run once the process document deleted.
onStartRemovingWorkflowInstance During deletion of the process document The connector will run when the process document is being deleted.
onEvaluateOperators At the evaluation of the next operators The connector will run on the next step ’s operators selection. Allow to define who will be the next step(s) operators. The connector will be called for each step.
onCreateTaskInstance At the start of the next step The connector will run on the start of the next step(s). Allow to define dynamic parameters on the step in creation (ie. time duration of the step).
onTerminateTaskInstance At the step closure The connector will run on the step closure.
onGenerateReference On the formatted reference’s generation The connector will run on the generation of the document’s or the data record’s reference.
onBeforeCreate During creation The connector will run when creating the document or the record.
onBeforeSave During saving The connector will run when saving the document or the record.
onAfterSave At the end of saving The connector will run once the document or data has been saved.
onPropertyChanged Au changement de valeur du champ Le connecteur s’exécutera au changement du contenu du champ.
onRemove At the end of deletion The connector will run once the resource has been deleted.
onStartRemoving During deletion The connector will run when the resource is being deleted.
onBeforeSummit During step change The connector will run on step change, once the user will have clicked on the action button from the step form and before the step change wizard displays. Allows to stop or not, depending on criteria, the display of the step change wizard.
onAfterSummit At the end of step change champ The connector will run after the form step change, once the step change wizard will be closed.

List of front-end trigger events

System name Label Description
onBeforeLoad Before form loading The connector will run before the form displays.
onAfterLoad After form loading The connector will run after the form displays.
onBeforeSave On click on the Save button The connector will run once the user will have clicked the Save button.
onAfterSave During saving The connector will run on the recording of form.
onBeforeClose Before closure The connector will run on form closure, once the user will have clicked on the Close button. Allows to stop or not, depending on criteria, the document closure.
onBeforeSendInformation On click on the Send an information email button The connector will run when the user will click the Send an information email button from the form. Allow to stop or not, depending on criteria, the display of the information sending wizard.
onAfterSendInformation On receipt of the information email The connector will run after the information email sending from the form, once the email has been received.
onBeforeSubmit On click on the step change button The connector will run on step change, once the user will have clicked on the action button from the step form and before the step change wizard displays. Allows to stop or not, depending on criteria, the display of the step change wizard.
onAfterSubmit During step change The connector will run during the form step change, once the step change wizard will be closed.
onBeforeAbort On click on the Cancel my request button The connector will run when the user will click on the Cancel delegation button from the process form. Allow to stop or not, depending on criteria, the display of the cancellation wizard.
onBeforeRemind On click on the Remind button The connector will run when the user will click on the Remind button from the process form. Allow to stop or not, depending on criteria, the display of the remind wizard.
onBeforeDelegate On click on the Delegate the document button The connector will run once the user will click on the Delegate the document button from the form. Allow to stop or not, depending on criteria, the display of the delegation wizard.
onAfterDelegate At the end of the document delegation The connector will run once the delegation ended.
onBeforeCancelDelegation On click on the Cancel delegation button The connector will run once the user will click on the Cancel delegation button from the form. Allow to stop or not, depending on criteria, the display of the delegation cancellation wizard.
onAfterCancelDelegation During the delegation cancellation The connector will run during the cancellation of the delegation request.
onBeforeRefuseDelegation On click on Refuse the delegation button The connector will run when the user will click on Refuse delegation before the wizard displays. Allow to stop or not, depending on criteria, the display of the delegation refusal wizard.
onAfterRefuseDelegation During the delegation refusal The connector will run during refusing the delegation, once the wizard will be closed.
onBeforeDelegateTaskOnly On click on the Delegate the step button The connector will run once the user will have clicked on the Delegate button from the step form.
onAfterDelegateTaskOnly At the end of the step delegation The connector will run once the step delegation ended.
onPropertyChanged On field value change The connector will run when the field will be modifying. Allow the cascading lists.

The <supported-events> tag allows developers to specify the events on which a service can be bind and to set the default one depending on the runtime execution context.

<supported-events>
	<front-end-events>
		<resource-definition>
			<form>
				<events>
					<event name="onAfterLoad" default="true" />
				</events>
			</form>
		</resource-definition>
	</front-end-events>
</supported-events>

Understand the lifecycle events

During the life of a document, the system calls a set of events depending on the actions of the user. The grey blocs indicate the active transactions.

Create wizard events - Before the wizard is launched, the document is saved: create wizard create wizard

Load form events: load wizard load wizard

Change step events - Events are launched on the task form and on the action form: change step wizard change step wizard

XML resource

In order to localize the configuration and the error messages of the service to different languages, you should always specify each string as a resource. The XML resource file should be deployed on the custom/internationalization folder. Its name must be unique on the Process server. To prevent name conflicts it is recommended to use the following template: companyName-connectionType-resources.xml (e.i. visiativ-education-resources.xml). This file must contain every string used for the service.

<?xml version="1.0" encoding="UTF-8"?>
<res>
	<id value="LG_STRING_EXAMPLE">
		<lang value="fr" flag="0">Exemple de chaine de traduite</lang>
		<lang value="en" flag="0">Translated string example</lang>
		<lang value="de" flag="1">Übersetzes String Beispiel</lang>
	</id>
</res>

Mapping component

The objective of this component is to enable the mapping of fields to be able to save or retrieve properties of heterogeneous objects. The original need is related to the setting of the connectors.

Graphic component

The graphical control to use is com.axemble.studio.expressions.components.MappingComponent. This control will allow us to set the mapping between the different elements.

To use this component, the following object providers must be defined:

  • sourceMappingProvider: input provider.
  • targetMappingProvider: output provider.

They can be defined directly in the XML definition in the case where the providers do not need parameters to their initialization. Otherwise, it is necessary that both providers be initialized at loading with the onAfterLoad() of the document.

XML Definition

The XML will define the name of the field associated to the MappingComponent and the target provider. The UserMappingProvider will implement BaseCustomMappingProvider.

<fields>
    <field name="fldUserMappingComponent" label="" ctrl="com.axemble.studio.expressions.components.MappingComponent" 
        target-provider="com.axemble.vdoc.connectors.directory.mapping.providers.UserMappingProvider" />
</fields>

onAfterLoad method

Here’s an example of the initialization of the mappingComponant in the onAfterLoad method.\

MappingComponent<?, ?> mappingComponent = (MappingComponent<?, ?>)getResourceController().getDefaultWidget( "fldUserMappingComponent" );
IMappingProvider<?> sourceMappingProvider = mappingComponent.createSourceProvider( TableCreationMappingProvider.class.getName(), getTableCreation() );
mappingComponent.setSourceMappingProvider( sourceMappingProvider );

Object provider definition

The provider must extend com.axemble.vdoc.sdk.components.BaseCustomMappingProvider. All external objects must be mapped to vdoc MappingStructure objects. The MappingStructure object allows to link external objects to vdoc objects.

MappingStructure object

The external object (MappingStructure) defined the following objects :

private String name;
private String label;
private String description;
private String dataType;
private boolean isMandatory;
private boolean isVisible;
private int mappingType;
private List<IMappingStructure> childValues = new ArrayList<>();
private List<IOption> options = new ArrayList<>();

Methods to implement by the provider

The provider must implement the following 3 methods :

Method Description
public List<IMappingStructure> getValues(); Returns the list of external objects linked to known Process objects
public abstract Object getValue( T mappedObject, String mappingStructureName); Get the value of the external object corresponding to mappingStructureName
public abstract void setValue( T mappedObject, String mappingStructureName, Object value ); Set the value of the external object corresponding to mappingStructureName

Assigning values

After having set the different binding components in the User interface (UI), the values assignment is done via com.axemble.vdoc.sdk.components.MappingObject.

Method Description
getTargetValue() This method is used to get the value of the target mappingStructure name.
applyMapping() This method is used to assign the values of the source object to the target object.

Example in CreateUserService.java

MappingObject<IResource, IUser> mappingObject = new MappingObject<>( new TableCreationMappingProvider<>( getTableCreation() ), new UserMappingProvider<>( null ) );

IOrganization organization = (IOrganization)mappingObject.getTargetValue( directoryContext, getResource(), getServiceDefinition().getValue( "fldUserMappingComponent" ), UserMappingProvider.FIELD_ORGANIZATION );

IUser user = directoryModule.createUser( directoryContext, "CreateUserServiceLoginTemp", "CreateUserServicePasswordTemp", organization );

mappingObject.applyMapping( directoryContext, getResource(), user, getServiceDefinition().getValue( "fldUserMappingComponent" ) );

Create a navigation service connector

Define a connector

This file should be available from the relative path WEB-INF\storage<custom><connectors>\education-sample.xml within the final connectors package.

<connectors>
    <connector name="navigation" label="navigation-connector.label" description="navigation-connector.description" version="1.0" company="Visiativ Software">
        <services>
            <service>
            </service>              
        </services>
    </connector>
</connectors>

Associate a runtime class to the service connector

<?xml version="1.0" encoding="UTF-8"?>
<connectors>
    <connector name="navigation" label="navigation-connector.label" description="navigation-connector.description" version="1.0" company="Visiativ Software">
        <services>
            <service name="fooService" label="sample.service.foo.label">
                <class qualifiedName="com.axemble.education.connectors.sample.DummyServiceConnector" />
            </service>              
        </services>
    </connector>
</connectors>

Create the runtime class for the service connector

package com.axemble.education.connectors.sample;

import java.util.Map;

import org.w3c.dom.Element;

import com.axemble.vdoc.sdk.connectors.BaseServiceConnector;
import com.axemble.vdoc.sdk.interfaces.IConnectorExecutionStatus;
import com.axemble.vdoc.sdk.interfaces.IContext;

public class DummyServiceConnector extends BaseServiceConnector {
  private static final long serialVersionUID = 1L;

  @Override
  public int execute(IContext context, int eventType, String eventName, Element customElement) {
    // retrieve the parameters
    Map<String, Object> inputs = getServiceDefinition().getValues();

    // add parameters to the local thread to make them available for the next services
    addParameter("onAbort", "parameterValue");

    // set the output values
    getServiceOutputs().addOutput("errorMessage", "labelerrorMessage");

    return IConnectorExecutionStatus.CONTINUE;
  }

  @Override
  public void beforeCompletion(IContext context, int eventType, String eventName, Element customElement) {
    super.beforeCompletion(context, eventType, eventName, customElement);

    LOGGER.error("[INFO] call beforeCompletion method ");
  }

  @Override
  public void afterCompletion(IContext context, int eventType, String eventName, Element customElement, boolean committed) {
    super.afterCompletion(context, eventType, eventName, customElement, committed);

    LOGGER.error("[INFO] call afterCompletion method with committed value = " + committed);
  }

  @Override
  public void asyncExecute(int eventType, String eventName, Element customElement) {
    super.asyncExecute(eventType, eventName, customElement);

    LOGGER.error("[INFO] call asyncExecute method with committed value = ");
  }
}

Set the configuration of the service connector

<?xml version="1.0" encoding="UTF-8"?>
<connectors>
  <connector name="navigation" label="navigation-connector.label" description="navigation-connector.description"
             version="1.0" company="Visiativ Software">
    <services>
      <service name="fooService" label="sample.service.foo.label">
        <class qualifiedName="com.axemble.education.connectors.sample.DummyServiceConnector"/>
        <icons>
          <icon name="small" path="mail/mail.png"/>
          <icon name="medium" path=""/>
          <icon name="large" path=""/>
        </icons>
        <configuration>
          <class qualifiedName="com.axemble.education.connectors.sample.DummyServiceConnectorEditor"/>
          <section name="cmis">
            <fields>
              <field name="folderName" label="Nom du dossier" ctrl="text" mandatory="true" maxlength="64" defaultValue=""/>
              <field name="parentFolder" label="Dossier parent" ctrl="com.axemble.vdoc.sdk.document.fields.SelectorField" mandatory="false"/>
              <field name="fldMailingList" label="treatment.mail.sendMail.mailingList.label" description="treatment.mail.sendMail.mailingList.description" ctrl="selector" mandatory="true" screen="mailingList" method="select" type="all"/>
            </fields>
          </section>
        </configuration>
        <inputs>
          <input name="folderName" type="java.lang.String"/>
          <input name="parentFolder" type="com.axemble.vdoc.sdk.interfaces.IFolder"/>
          <input name="fldMailingList" type="com.axemble.vdoc.sdk.interfaces.IMailingList"/>
        </inputs>
        <outputs>
          <output name="result" type="java.lang.Boolean"/>
          <output name="error" type="java.lang.String"/>
          <output name="errorMessage" type="java.lang.String"/>
          <output name="folder" type="com.axemble.vdoc.sdk.interfaces.IFolder"/>
          <output name="folders" type="java.util.Collection" collectionType="com.axemble.vdoc.sdk.interfaces.IFolder"/>
        </outputs>
        <entry-points>
          <connectors-library familyName="education"/>
        </entry-points>
        <supported-events>
          <front-end-events>
            <resource-definition>
              <form>
                <events>
                  <event name="onAfterLoad" default="true"/>
                </events>
              </form>
            </resource-definition>
          </front-end-events>
        </supported-events>
      </service>
    </services>
  </connector>
</connectors>

Create the editor class for the service connector

package com.axemble.education.connectors.sample;

import com.axemble.vdoc.sdk.connectors.BaseServiceConnectorEditor;

public class DummyServiceEditor extends BaseServiceConnectorEditor {

  private static final long serialVersionUID = 1L;

}

Retrieve the parameters from the configuration

By using the getServiceDefinition method you can retrieve the various values from the configuration.

// retrieve all the values from the configuration
Map<String, Object> inputObjects = getServiceDefinition().getValues();

// retrieve a specific value from the configuration by its name
Object inputObject = getServiceDefinition().getValue( "fldDescription" );

Make some result values available to the Studio

By using the addOutput method you can make available some values from the service execution to the Studio.

getServiceOutputs().addOutput( "errorMessage", "labelErrorMessage" );
getServiceOutputs().addOutput( "anyObjectValue", anyObjectValue );

Make some result values available for the next service execution

By using the addParameter method you can make available some values for the service the next service execution.

addParameter( "errorMessage", "labelErrorMessage" );
addParameter( "anyObjectValue", anyObjectValue );