Start an Activiti Process via Rest Script in Crafter CMS

Activiti is a powerful open source workflow engine built by Alfresco.  Incorporating a workflow engine into your customer and employee facing sites and portals is an excellent solution for automating complex workflows that cross system boundaries while providing the user with a simple to use, contextual user experience.   Working for a bank or an insurance company and need to workflow contracts with customers?  No problem. Crafter CMS (an open source Java based CMS) paired with Alfresco is a perfect solution.  It’s customer friendly, highly scalable and about as powerful as enterprise technology gets!

In this blog, I’ll demonstrate the most straightforward example of a Crafter CMS REST service being used to start an Activiti Process.

Prerequisites

  • You have Activiti (http://www.activiti.org/) installed
    NOTE:
    The authentication and process are hard coded to simplify the example

Step 1: Create a REST Controller

  • Under Scripts/rest right click and click create controller
    • Enter start-process.get as the controller name
  • Add the following code to the controller. This code assumes Activiti is deployed into the same container as Crafter Engine.
@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
@Grab('oauth.signpost:signpost-core:1.2.1.2')
@Grab('oauth.signpost:signpost-commonshttp4:1.2.1.2')

import groovyx.net.http.HTTPBuilder
import groovyx.net.http.ContentType
import groovyx.net.http.Method
import groovyx.net.http.RESTClient

def http = new HTTPBuilder("http://localhost:8080")
def user = "kermit"
def password = "kermit"
def authPair = user + ":" + password
def authEncoded = authPair.bytes.encodeBase64().toString()

http.setHeaders([Authorization: "Basic "+authEncoded])

def ret = null

http.request( Method.POST ) {
    uri.path = "/activiti-rest/service/runtime/process-instances"
    // ACTIVITI ENTERPRISE URL
    // uri.path = "/activiti-app/api/enterprise/process-instances"

    requestContentType = ContentType.JSON
    body =  [ processDefinitionKey: "vacationRequest", variables:[  [name:"employeeName", value: "Russ"], [name:"numberOfDays", value: "5"],[name:"startDate", value:"10-08-2015 11:11"],[name:"vacationMotivation", value: "rest"]    ]]

    response.success = { resp, reader ->
        ret = reader
    }
}

return ret

Step 2: Execute the Service

Step 3: Verify that a new process instance has been started

Active Cache a RESTful Response in Crafter CMS

This article will demonstrate how to create a RESTful service in Crafter Engine that has predictable performance and reliability when your service relies on an external service.

Any time your services depend on another service there is a cause for concern. You can’t control the performance or the availability of the external service. Further, if the response of the external service is not unique across calls then there may be no real need to call out to it on each request you receive.

In this case, what you want to do is cache the request from the external service and have your service attempt to get the content from the cache. Active cache is a built in Crafter CMS capability that makes building these sort of solutions much easier. You tell Active Cache what you want, how to get it and how often to refresh it in the background. From there on, you simply ask Active cache for whatever the current response is.

Step 1: Create a REST Controller

Under Scripts/rest right click and click create controller
Enter my-data.get as the controller name
Add the following code to the controller.

 import org.craftercms.core.cache.CacheLoader
 import org.craftercms.core.service.CachingOptions
 import groovy.json.JsonSlurper

 def cacheService = applicationContext["crafter.cacheService"]
 def cacheContext = siteContext.getContext()
 def myCacheKey = "aServiceCallResponse"
 def loader = new ExternalServiceLoader()

 def value = ""
 def responseItem = cacheService.get(cacheContext, myCacheKey)

 if(responseItem == null) {
    // item is not cached, get the value
    def myObject = loader.load()
    value = myObject

   // cache the value with a loader to periodically refresh its value
    def cachingOptions = CachingOptions.DEFAULT_CACHING_OPTIONS
    // def cachingOptions = new CachingOptions() // define your own options
    // cachingOptions.setRefreshFrequency(1) // set the number of ticks for refresh

    try {
        cacheService.put(cacheContext, myCacheKey, myObject, [], cachingOptions, loader)
    }
    catch(err) {
        logger.error("error adding ${myCacheKey} to cache: ${err}")
     }
 }
 else {
    value = responseItem
 }

 return value

/**
 * Define an active cache loader that will be used to prime and then
 * periodically refresh the cache with the latest data from an external
 * service.
 */
 class ExternalServiceLoader implements CacheLoader {
    Object load(Object... parameters) throws Exception {
       def externalServiceHost = "http://api.population.io/1.0"
       def externalServiceURL = "/population/United%20States/today-and-tomorrow/"

       // call the service
       def response = (externalServiceHost+externalServiceURL).toURL().getText()

       // parse service's the JSON response to an object
       def result = new JsonSlurper().parseText( response )

       return result
    }
 }

Step 2: Execute the Service

Open a browser and hit the following URL: http://localhost:8080/api/1/services/my-data.json
Note that your hostname, ports and pageId values may differ than the example
See results