Convert getVariables Output to String on WildFly Does Not Work

I want to take the output of the execution.getVariables() method and create a string representation of all process variables. I am using Camunda 7.6.2-ee running in WildFly 10. The output works for variables types like string and integer, but for JSON objects, it only outputs a plain object.

If I simply print the output of execution.getVariables(), I can see the JSON object value, however when using the following code, it only provides a plain object:

ObjectMapper mapper = new ObjectMapper();

String processVariables = mapper.writeValueAsString(execution.getVariables());

This would produce a string like the snippet shown below:

	"timeStamp": "20170621120017",
	"rawMessage": {
		"null": false,
		"array": false,
		"value": false,
		"number": false,
		"object": true,
		"string": false,
		"boolean": false,
		"nodeType": "OBJECT",
		"dataFormatName": "application/json"
	},
	"sourceHost": "O119322F",

The value of “rawMessage” isn’t included, but all others are.

We have determined that we need to use Camunda’s version of ObjectMapper and have attempted to include the org.camunda.spin.camunda-spin-dataformat-all dependency in our project. However, when executed on a WildFly server, we get class not found errors consistently. We have placed this dependency in the POM file manifest and have set the dependency scope to compile so that it is included in the war file.

When I attempt to deploy it, WildFly throws the exception below. Any ideas on how we might fix this?

2017-06-28 08:53:12,375 INFO  [org.camunda.spin] (MSC service thread 1-7) SPIN-01010 Discovered Spin data format provider: org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormatProvider[name = application/json]
2017-06-28 08:53:12,381 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-7) MSC000001: Failed to start service org.camunda.bpm.platform.process-application-module."deployment.Process_PrintCounter1-0.0.4-SNAPSHOT.war:main".START: org.jboss.msc.service.StartException in service org.camunda.bpm.platform.process-application-module."deployment.Process_PrintCounter1-0.0.4-SNAPSHOT.war:main".START: Failed to start service
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ExceptionInInitializerError
	at org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormat.<clinit>(JacksonJsonDataFormat.java:54)
	at org.camunda.spin.impl.json.jackson.format.JacksonJsonDataFormatProvider.createInstance(JacksonJsonDataFormatProvider.java:37)
	at org.camunda.spin.DataFormats.registerProvider(DataFormats.java:152)
	at org.camunda.spin.DataFormats.registerCustomDataFormats(DataFormats.java:140)
	at org.camunda.spin.DataFormats.registerDataFormats(DataFormats.java:124)
	at org.camunda.spin.plugin.impl.SpinBpmPlatformPlugin.lookupSpinSerializers(SpinBpmPlatformPlugin.java:60)
	at org.camunda.spin.plugin.impl.SpinBpmPlatformPlugin.initializeVariableSerializers(SpinBpmPlatformPlugin.java:52)
	at org.camunda.spin.plugin.impl.SpinBpmPlatformPlugin.postProcessApplicationDeploy(SpinBpmPlatformPlugin.java:37)
	at org.camunda.bpm.container.impl.jboss.service.ProcessApplicationStartService.notifyBpmPlatformPlugins(ProcessApplicationStartService.java:173)
	at org.camunda.bpm.container.impl.jboss.service.ProcessApplicationStartService.start(ProcessApplicationStartService.java:146)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948)
	at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881)
	... 3 more
Caused by: java.lang.ClassCastException: org.camunda.spin.impl.json.jackson.JacksonJsonLogger cannot be cast to org.camunda.commons.logging.BaseLogger
	at org.camunda.commons.logging.BaseLogger.createLogger(BaseLogger.java:88)
	at org.camunda.spin.impl.json.jackson.JacksonJsonLogger.<clinit>(JacksonJsonLogger.java:35)
	... 15 more

2017-06-28 08:53:12,847 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 16) WFLYCTL0013: Operation ("full-replace-deployment") failed - address: ([]) - failure description: {
    "WFLYCTL0080: Failed services" => {"org.camunda.bpm.platform.process-application-module.\"deployment.Process_PrintCounter1-0.0.4-SNAPSHOT.war:main\".START" => "org.jboss.msc.service.StartException in service org.camunda.bpm.platform.process-application-module.\"deployment.Process_PrintCounter1-0.0.4-SNAPSHOT.war:main\".START: Failed to start service
    Caused by: java.lang.ExceptionInInitializerError
    Caused by: java.lang.ClassCastException: org.camunda.spin.impl.json.jackson.JacksonJsonLogger cannot be cast to org.camunda.commons.logging.BaseLogger"},
    "WFLYCTL0412: Required services that are not installed:" => ["org.camunda.bpm.platform.process-application-module.\"deployment.Process_PrintCounter1-0.0.4-SNAPSHOT.war:main\".START"],
    "WFLYCTL0180: Services with missing/unavailable dependencies" => undefined
}
2017-06-28 08:53:12,848 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 99) WFLYUT0022: Unregistered web context: /Process_PrintCounter1-0.0.4-SNAPSHOT
2017-06-28 08:53:12,850 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-7) WFLYJCA0019: Stopped Driver service with driver-name = Process_PrintCounter1-0.0.4-SNAPSHOT.war_com.mysql.jdbc.Driver_5_1
2017-06-28 08:53:12,850 INFO  [org.jboss.as.connector.deployers.jdbc] (MSC service thread 1-4) WFLYJCA0019: Stopped Driver service with driver-name = Process_PrintCounter1-0.0.4-SNAPSHOT.war_com.mysql.fabric.jdbc.FabricMySQLDriver_5_1
2017-06-28 08:53:13,505 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-5) WFLYSRV0028: Stopped deployment Process_PrintCounter1-0.0.4-SNAPSHOT.war (runtime-name: Process_PrintCounter1-0.0.4-SNAPSHOT.war) in 656ms
2017-06-28 08:53:13,505 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 16) WFLYCTL0190: Step handler org.jboss.as.server.deployment.DeploymentHandlerUtil$4@3c76020d for operation {"operation" => "full-replace-deployment","address" => [],"name" => "Process_PrintCounter1-0.0.4-SNAPSHOT.war","content" => [{"input-stream-index" => 0}],"enabled" => true,"operation-headers" => {"caller-type" => "user","access-mechanism" => "NATIVE"},"runtime-name" => undefined,"persistent" => true,"owner" => undefined} at address [] failed handling operation rollback -- java.util.NoSuchElementException: No child 'name' exists: java.util.NoSuchElementException: No child 'name' exists
	at org.jboss.dmr.ModelValue.requireChild(ModelValue.java:377)
	at org.jboss.dmr.ObjectModelValue.requireChild(ObjectModelValue.java:299)
	at org.jboss.dmr.ModelNode.require(ModelNode.java:870)
	at org.jboss.as.server.deployment.DeploymentHandlerUtil$4$1.handleResult(DeploymentHandlerUtil.java:277)
	at org.jboss.as.controller.AbstractOperationContext$Step.invokeResultHandler(AbstractOperationContext.java:1384)
	at org.jboss.as.controller.AbstractOperationContext$Step.handleResult(AbstractOperationContext.java:1366)
	at org.jboss.as.controller.AbstractOperationContext$Step.finalizeInternal(AbstractOperationContext.java:1328)
	at org.jboss.as.controller.AbstractOperationContext$Step.finalizeStep(AbstractOperationContext.java:1311)
	at org.jboss.as.controller.AbstractOperationContext$Step.access$300(AbstractOperationContext.java:1185)
	at org.jboss.as.controller.AbstractOperationContext.executeResultHandlerPhase(AbstractOperationContext.java:767)
	at org.jboss.as.controller.AbstractOperationContext.processStages(AbstractOperationContext.java:667)
	at org.jboss.as.controller.AbstractOperationContext.executeOperation(AbstractOperationContext.java:370)
	at org.jboss.as.controller.OperationContextImpl.executeOperation(OperationContextImpl.java:1329)
	at org.jboss.as.controller.ModelControllerImpl.internalExecute(ModelControllerImpl.java:400)
	at org.jboss.as.controller.ModelControllerImpl.execute(ModelControllerImpl.java:222)
	at org.jboss.as.controller.remote.ModelControllerClientOperationHandler$ExecuteRequestHandler.doExecute(ModelControllerClientOperationHandler.java:208)
	at org.jboss.as.controller.remote.ModelControllerClientOperationHandler$ExecuteRequestHandler.access$300(ModelControllerClientOperationHandler.java:130)
	at org.jboss.as.controller.remote.ModelControllerClientOperationHandler$ExecuteRequestHandler$1$1.run(ModelControllerClientOperationHandler.java:152)
	at org.jboss.as.controller.remote.ModelControllerClientOperationHandler$ExecuteRequestHandler$1$1.run(ModelControllerClientOperationHandler.java:148)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.jboss.as.controller.AccessAuditContext.doAs(AccessAuditContext.java:149)
	at org.jboss.as.controller.remote.ModelControllerClientOperationHandler$ExecuteRequestHandler$1.execute(ModelControllerClientOperationHandler.java:148)
	at org.jboss.as.protocol.mgmt.AbstractMessageHandler$ManagementRequestContextImpl$1.doExecute(AbstractMessageHandler.java:363)
	at org.jboss.as.protocol.mgmt.AbstractMessageHandler$AsyncTaskRunner.run(AbstractMessageHandler.java:472)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
	at org.jboss.threads.JBossThread.run(JBossThread.java:320)

Hi Michael,

For object type variables, would it be sufficient to display the serialized value? In your example, you ask the process engine to deserialize the variables (via execution#getVariables) only then to use Jackson to serialize them again to JSON. If all your object variables are serialized in a human-readable format, then you could directly use the serialized String value that can be accessed via execution#getVariablesTyped etc. In that case, you don’t need to use Jackson and things should get a lot easier.

Cheers,
Thorben

1 Like

I have to first state my relative ignorance in Java (sorry, I know, I’m pathetic), so I’ll try to answer the question. I think the answer is yes, we can use the serialized values. In most cases, these objects are actually JSON, sometimes JSON wrapped around JSON.

The values output be by the simple execution.getVariables() method are acceptable.

We’re trying a workaround right now to iterate through the map, classify each type, and then use an appropriate statement to craft a JSON entry, but even that is a challenge.

Sounds good to me. If you iterate over the result of execution.getVariablesTyped(), then you can check if a value is an instance of SerializableValue, then cast it to SerializableValue and use SerializableValue#getValueSerialized to access the JSON Camunda stores.

We did the following. The purpose was to put all the process variables into a JSON string.

ObjectMapper mapper = new ObjectMapper();

Iterator<Entry<String, Object>> variablesIterator = execution.getVariables().entrySet().iterator(); 


while(variablesIterator.hasNext()) 
{

    String variableName = null;
    try 
    { 

        Entry<String, Object> variableEntry = variablesIterator.next(); 
        variableName = variableEntry.getKey(); 
        Object variableObject = variableEntry.getValue(); 
        
        switch(variableObject.getClass().getSimpleName()) 
        { 
            case "String": 
                processVariables += "\"" + variableName + "\":" + mapper.writeValueAsString((String)variableObject); 
                break; 
            case "Integer": 
                processVariables += "\"" + variableName + "\":" + (Integer)variableObject; 
                break; 
            case "Boolean": 
                processVariables += "\"" + variableName + "\":" + (Boolean)variableObject; 
                break; 
            case "JacksonJsonNode": 
                JsonValue jsonValue = execution.getVariableTyped(variableName); 
                processVariables += "\"" + variableName + "\":" + jsonValue.getValueSerialized(); 
                break; 
            default: 
            processVariables += "\"" + variableName + "\":" + mapper.writeValueAsString(variableObject); 
        } 
        if(variablesIterator.hasNext()) 
        { 
            processVariables += ","; 
        } 
                            
    }
    catch(Exception exception) 
    { 
     ....
    }