Start case automatically with InterfaceB

Printer-friendly version

To instantiate a workflow with YAWL, usually an administrator or a user with the privilege "Manage Cases" needs to use the YAWL Resource Service. But often a workflow should be started automatically according to some arbitrary condition (e.g. each month or every time a user submits some inquiry) or by an unprivileged user.

As YAWL is built upon a service oriented architecture it is possible to use an interface of the YAWL Engine to accomplish such tasks. The interface needed in that case is the InterfaceB of the YAWL Engine. YAWL includes already an implementation InterfaceB_EnviromentBasedClient, that provides easy access to this interface. There are two methods available that may be used to start an instance of a specification (i.e. workflow):

 String launchCase(YSpecificationID specID, String caseParams, String sessionHandle, YLogDataItemList logData, String completionObserverURI)
          Override of launchCase to provide the ability to add a listener for the Case-Completion event
 String launchCase(YSpecificationID specID, String caseParams, YLogDataItemList logData, String sessionHandle)
          Launches a case instance of the latest version of the specification loaded.

The first method is only needed, if you an observer completionObserverURI should be notified after the case is completed. Usually, you use the second launchCase method that takes the following parameters:

  • the specID,
  • the caseParams,
  • an empty YLogDataItemLIst
  • and a valid YAWL Engine sessionHandle.

A java servlet that starts a specific YAWL specification may look like this:

    /**
     * Username of an administrative account
     */
    private static final String ADMIN_PASSWORD = "YAWL";

    /**
     * Password of an administrative account
     */
    private static final String ADMIN_USERNAME = "admin";

    /**
     * URL of YAWL Engine InterfaceB
     */
    private static final String INTERFACEB_URL = "http://127.0.0.1:8080/yawl/ib";

    /**
     * A valid specification:<br/>
     * identifier: Can be found in the .yawl file of a specification<br/>
     * version: Can be found with the YAWL Editor in the properties of a
     * specification (Version Number)<br/>
     * uri: Can be found with the YAWL Editor in the properties of a
     * specification (Specification ID)
     */
    private static final YSpecificationID SPECIFICATION = new YSpecificationID(
            "UID_47e1bbf0-7677-4469-ba47-2f77a24bab97", "1.3",
            "SimpleMakeTripProcess.ywl");

    /**
     * XML of the input parameters of the starting net, in this case empty
     */
    private static final String INPUT_PARAMETER = "<Make_Trip_Process></Make_Trip_Process>";

These parameters are constant here for the sake of simplicity and usually the method doPost would be used instead of doGet:

    /*
     * (non-Javadoc)
     *
     * @see
     * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest
     * , javax.servlet.http.HttpServletResponse)
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        PrintWriter out = response.getWriter();

        // Engine InterfaceB, usually http://127.0.0.1:8080/yawl/ib
        InterfaceB_EnvironmentBasedClient client = new InterfaceB_EnvironmentBasedClient(
                INTERFACEB_URL);

        String handle = null;

        try {
            // Connect with valid credentials, usually admin / YAWL
            handle = client.connect(ADMIN_USERNAME, ADMIN_PASSWORD);
        } catch (IOException e) {
            out.println("Problem connecting to engine. " + e.getMessage());
        }

        if (handle != null) {
            try {
                // May be empty
                YLogDataItemList yLog = new YLogDataItemList();
                // Launch case from the specification with input parameters
                String caseID = client.launchCase(SPECIFICATION, INPUT_PARAMETER,
                        yLog, handle);
                out.println("Case started! CaseID: "+ caseID);               
            } catch (Exception e) {
                out.println("Case not started. " + e.getMessage());
            }
        }

    }

To use the InterfaceB_EnviromentBasedClient in your own project, you need to include the yawl-lib-2.2.jar (yawl-lib-2.3.jar in case of YAWL 2.3) in the classpath. You can build the YAWL library from the YAWL sources or download YAWL_2.2_LibraryJars.zip at Sourceforge.

An example project with the just presented servlet, which starts the example workflow "Simple Make Trip Process" (distributed with YAWL) can be downloaded below. There is a pre-built WAR-file for immediate deployment to a running YAWL instance. Just copy the InterfaceBServlet.war into the '/engine/apache-tomcat-6.0.18/webapps' directory of YAWL and then open 'http://localhost:8080/InterfaceBServlet/interfaceB' in your web browser.

The sourcecode of the example project is available for download as 'InterfaceB.tgz' and 'InterfaceB.zip'. It is packaged as a Eclipse project that needs Java 1.6 and the Apache Tomcat 6.0 runtime environment.

 

(Notice: This tutorial is based on  YAWL version 2.3.x)

Comments

Thank you for uploading this tutorial to help us understand how to use InterfaceB. I downloaded the War file but I could not find the lib to download.

May someone direct me or share another working tutorial with the current version of YAWL or YAWL 4.1 which I am using.

Note: error page is below

Thank you

#################################

HTTP Status 500 - Servlet execution threw an exception

type Exception report

message Servlet execution threw an exception

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Servlet execution threw an exception
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64
org.yawlfoundation.yawl.util.PasswordEncryptor.encrypt(PasswordEncryptor.java:43)
org.yawlfoundation.yawl.util.PasswordEncryptor.encrypt(PasswordEncryptor.java:50)
org.yawlfoundation.yawl.engine.interfce.interfaceB.InterfaceB_EnvironmentBasedClient.connect(InterfaceB_EnvironmentBasedClient.java:73)
org.yaug.sample.InterfaceBServlet.doGet(InterfaceBServlet.java:79)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
org.yawlfoundation.yawl.util.PasswordEncryptor.encrypt(PasswordEncryptor.java:43)
org.yawlfoundation.yawl.util.PasswordEncryptor.encrypt(PasswordEncryptor.java:50)
org.yawlfoundation.yawl.engine.interfce.interfaceB.InterfaceB_EnvironmentBasedClient.connect(InterfaceB_EnvironmentBasedClient.java:73)
org.yaug.sample.InterfaceBServlet.doGet(InterfaceBServlet.java:79)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

note The full stack trace of the root cause is available in the Apache Tomcat/8.5.5 logs.
Apache Tomcat/8.5.5