Skip to main content
Skip table of contents

Developing an Extension

The first class that you need to define is your ServiceProvider, this class will contain a method that will be executed by Cantara Server when it is requested.

Below, you can find an example:

Developing an Extension

JAVA
package com.rinami.cantara.extension.script;
import com.rinami.cantara.core.CoreObjectFactory;
import com.rinami.cantara.core.DataUtility;
import com.rinami.cantara.core.MessageType;
import com.rinami.cantara.core.session.SessionData;
import com.rinami.cantara.extension.annotations.CantaraService;
import com.rinami.cantara.extension.annotations.Payload;
import com.rinami.cantara.schema.plan.Message;
 
public class ServiceProvider {
 
private final Logger log = LoggerFactory.getLogger(ServiceProvider.class);
@CantaraService(name = "scriptServiceRequest")
public ScriptResponse executeScriptRequest(@Payload(name = "scriptRequest") ScriptRequest scriptRequest, SessionData sd) {
	Message message = CoreObjectFactory.generateMessage(MessageType.EXTENSION_ERROR, null, MessageType.EXTENSION_ERROR.getDescription(), null);
	ScriptResponse scriptResponse = new ScriptResponse(scriptRequest.getName(), scriptRequest.getCantaraVersion());
	log.error(String.format(Locale.US, "Failed to execute script %s", scriptRequest.getName());
	return scriptResponse;
}
}

In our case, we are providing the possibility of executing any script so executeScriptRequest is an appropriate name but the method name can be anything that applies in your case. However, Cantara Server needs to know which method has to be executed therefore you must to specify which method has to be executed and which parameter is your payload.

@CantaraService is the annotation that you need to use to specify which method has to be executed, in our case, executeScriptRequest will be executed by Cantara Server when required.

@Payload is the annotation that you need to use to specify your payload, it means your needed parameters to execute your new behaviour.

In our example, we can also see 3 classes that we need to understand: SessionData, ScriptRequest and ScriptResponse.

SessionData is the class that contains the session information: user name, environment name, password, etc.

As your extension will be invoked by Cantara Server when an appropriate Extension HTTP Post is received, Cantara Server will validate that it has been sent with a valid Session.  

SessionData

JAVA
package com.rinami.cantara.core.session;
import com.rinami.cantara.core.environment.EnvironmentDefinition;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class SessionData implements Serializable{
    @XmlAttribute(name = "functionSessionId")
    private String functionSessionId;
    @XmlAttribute(name = "restSessionId")
    private String restSessionId;    
    @XmlAttribute(name = "origin")
    private String origin;
    @XmlAttribute(name = "username", required = true)
    private String username;
    @XmlAttribute(name = "proxyUsername", required = true)
    private String proxyUsername;
    @XmlAttribute(name = "password", required = true)
    private String password;
    @XmlAttribute(name = "apiKey", required = true)
    private String apiKey;
    @XmlAttribute(name = "tenantId", required = true)
    private Long tenantId;
    @XmlAttribute(name = "environmentName")
    private String environmentName;
    @XmlElement(name = "environmentDefinition", required = true)
    private EnvironmentDefinition environmentDefinition;
    @XmlAttribute(name = "application")    
    private String application;
    @XmlElement(name = "userRoles")
    private Set<String> userRoles;
    @XmlAttribute(name = "fcmRegistrationId")
    private String fcmRegistrationId;
    @XmlAttribute(name = "addressNo")
    private long addressNo;
    @XmlAttribute(name = "branch")
    private String branch;
    @XmlAttribute(name = "approvalRoute")
    private String approvalRoute;
    @XmlAttribute(name = "dateFormat")
    private DateFormat dateFormat;
    @XmlAttribute(name = "dateSeparator")
    private DateSeparator dateSeparator;
    @XmlAttribute(name = "decimalCharacter")
    private DecimalCharacter decimalCharacter;
    @XmlAttribute(name = "timeZone")
    private TimeZone timeZone;
    @XmlAttribute(name = "timeFormat")
    private TimeFormat timeFormat;
    @XmlAttribute(name = "daylightRule")
    private DaylightSavingsRule daylightRule;    
    @XmlAttribute(name = "aisJSToken")
    private String aisToken;    
    @XmlTransient
    private LoginEnvironment aisLoginEnvironment;
    @XmlAttribute(name = "lastAccessTime")
    private long lastAccessTime;    
    public static final String SESSION_DATA_KEY = "com.rinami.cantara.server.core.sessiondata";
    public SessionData() {
    }
}

ScriptRequest it may be any class that you need but this class must extends ExtensionRequest which is part of the Extension Framework.

Obviously, you have to generate getters and setters but the important point is that you have to use @XmlElement annotation for your attributes in order to support xml and JSON formats.

Extension Script Request

JAVA
package com.rinami.cantara.extension.script;
import com.rinami.cantara.extension.core.ExtensionRequest;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;

public class ScriptRequest extends ExtensionRequest{
    @XmlElement(name = "path", required = true )
    private String path;
    @XmlElement(name = "workingDirectory")
    private String workingDirectory;
    @XmlElement(name = "script", required = true )
    private String script; 
    @XmlElement(name = "timeOut", required = true )
    private Long timeOut;
    @XmlElement(name="params")
    private List<String> params;
}

Extension Request

JAVA
package com.rinami.cantara.extension.core;
import com.rinami.cantara.core.CantaraRelease;
import com.rinami.cantara.core.DataUtility;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ExtensionRequest")
public abstract class ExtensionRequest {
    @XmlAttribute(name = "name", required = true)
    protected String name;
    @XmlAttribute(name = "cantaraVersion")
    protected String cantaraVersion;
    @XmlAttribute(name = "tenantId", required = true)
    protected Long tenantId;
    @XmlAttribute(name = "apiKey", required = true)
    protected String apiKey;
    public ExtensionRequest(){        
    }    
    public ExtensionRequest(String name){
        this.name = name;
        this.cantaraVersion = CantaraRelease.FOUR_DOT_TWO.value();
    }
}

ScriptResponse it may be any class that you need but this class must extends ExtensionResponse which is part of the Extension Framework.

Obviously, you have to generate getters and setters but the important point is that you have to use @XmlElement annotation for your attributes in order to support xml and JSON formats.

Extension Script Response

JAVA
package com.rinami.cantara.extension.script;
import com.rinami.cantara.extension.core.ExtensionResponse;
import javax.xml.bind.annotation.XmlElement;

public class ScriptResponse extends ExtensionResponse{
    @XmlElement(name = "stdOutput")
    private String stdOutput;
    @XmlElement(name = "stdError")
    private String stdError;
    @XmlElement(name = "exitValue")
    private Integer exitValue;
    
    public ScriptResponse(String name, String cantaraVersion) {
        this.setName(name);
        this.setCantaraVersion(cantaraVersion);
    }   
}

Extension Response

JAVA
package com.rinami.cantara.extension.core;
import com.rinami.cantara.core.CantaraRelease;
import com.rinami.cantara.core.DataUtility;
import com.rinami.cantara.schema.plan.Message;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExtensionResponse", propOrder = {
    "message"
})
public abstract class ExtensionResponse {
    @XmlElement(name = "Message", required = true)
    protected Message message;
    @XmlAttribute(name = "name", required = true)
    protected String name;
    @XmlAttribute(name = "cantaraVersion")
    protected String cantaraVersion;    
      
    public ExtensionResponse(String name, Message message){
        this.name = name;
        this.message = message;
        this.cantaraVersion = CantaraRelease.FOUR_DOT_TWO.value();
    }
}

Extension Response Messages

You can easily return OK, Error or Customized Error Messages as part of your response.

Response Messages

JAVA
Message message1 = CoreObjectFactory.generateMessage(MessageType.OK, null, MessageType.OK.getDescription(), null);
Message message2 = CoreObjectFactory.generateMessage(MessageType.EXTENSION_ERROR, null, MessageType.EXTENSION_ERROR.getDescription(), null);
Message message3 = CoreObjectFactory.generateMessage(MessageType.EXTENSION_ERROR, null, String.format(Locale.US, "Script exited with value %d", process.exitValue()), null);
ScriptResponse scriptResponse = new ScriptResponse(scriptRequest.getName(), scriptRequest.getCantaraVersion());
scriptResponse.setMessage(message1);
return scriptResponse;

Extension logging

It is really easy to log errors or debug operations on your Extension. You need to declare a Logger attribute and to use it.

Extension logging

JAVA
private final Logger log = LoggerFactory.getLogger(ServiceProvider.class);
 
log.error(String.format(Locale.US, "Script %s finished by timeout - %d", scriptRequest.getName(), scriptRequest.getTimeOut()));    
log.debug(String.format(Locale.US, "Finished by timeout - StdError: %s StdOutput:%s", scriptResponse.getStdError(), scriptResponse.getStdOutput()));












JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.