No suitable constructor: can not instantiate from JSON object

1,986 views
Skip to first unread message

Ingo Richtsmeier

unread,
Feb 24, 2015, 12:17:55 PM2/24/15
to camunda-...@googlegroups.com
Hi, 

I want to deserialize a complex object from JSON where some attributes are from class org.joda.money.Money. But I get this exception:

org.camunda.bpm.engine.ProcessEngineException: Cannot deserialize object in variable 'myVariable': SPIN/JACKSON-JSON-01006 Cannot deserialize '{"myObjec...' to java type '[simple type, class com.camunda.consulting.MyClass]'

Caused by: spinjar.com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class org.joda.money.Money]: can not instantiate from JSON object (need to add/enable type information?)

I found this example building a custom Serializer/Deserializer for joda.Money: http://stackoverflow.com/questions/23812273/json-deserialization-joda-money-using-fasterxml-objectmapper-cause-exception (Class is attached to show you the imports)

What is the best way to add a special serializer to the camunda spin environment?

Override the SpinProcessEnginePlugin?

Kind Regards, Ingo
SpinDeserializeTest.java

thorben....@camunda.com

unread,
Feb 25, 2015, 3:17:42 AM2/25/15
to camunda-...@googlegroups.com
Hi Ingo,

You can implement the SPI DataFormatConfigurator and make this available via a process engine plugin. Some details can be found here: [1]. Your configuraton is called with the detected json dataformat and you can exchange the Jackson ObjectMapper that it uses or add a module to the default ObjectMapper.

You'll also have to make sure to not use the library camunda-spin-dataformat-all, because it contains all of Spin's dependencies in relocated form. That means, we have relocated the Jackson classes to the packages spinjar.com.fasterxml... in that artifact. So make sure to use the dependencies listed in [2] under "camunda-spin-core". These will pull in the regular Jackson dependencies transitively and you can work with regular Jackson modules.

Best regards,
Thorben

[1] http://docs.camunda.org/latest/api-references/spin/#extending-spin-configuring-data-formats
[2] http://docs.camunda.org/latest/guides/user-guide/#data-formats-xml-json-other-configuring-spin-integration-maven-coordinates

Bernd Rücker

unread,
Feb 25, 2015, 8:11:25 AM2/25/15
to camunda-...@googlegroups.com
Hi Thorben.

Actually that sounds rather complicated to write a whole new DataFormat when the only thing you want to change is to adjust the ObjectMapper configuration.

What is your gut feeling - would the following work?

  DataFormats.getAvailableDataFormats();
  // search for JacksonJsonDataFormat in the result list
  ((JacksonJsonDataFormat)format).getObjectMapper()... // apply some changes...

Then the only thing we have to solve is to find the right lifecycle hook to do these changes (maybe a lifecycle plugin? Or the ProcessApplication startup hook?). 

What do you think?
Maybe we could support this better out-of-the-box in future - if the above works I could create a JIRA issue for this. The only downside I currently think of is that the changes are always classloader-wide - so I cannot easily do "Process Application specific srializations". 

Cheers
Bernd

thorben....@camunda.com

unread,
Feb 25, 2015, 8:27:17 AM2/25/15
to camunda-...@googlegroups.com
Hi Bernd,

Your code snippet is pretty much what you do when you implement DataFormatConfigurator (cf the interface [1]). You do not implement a new DataFormat. Instead, you implement the configurator that will be called with the json dataformat instance at the right point in the lifecycle and you can manipulate the ObjectMapper as you like.

To make it more clear, we could add an example to the examples repo.

I see the point that you have to add another library (no engine plugin required, that was incorrect in my first post) to the classpath that contains the spin libraries which might be cumbersome, but we discussed that in the team before 7.2.0 release and did not find a more convenient way of configuring data formats that are supposed to be globally available.

Cheers,
Thorben

[1] https://github.com/camunda/camunda-spin/blob/master/core/src/main/java/org/camunda/spin/spi/DataFormatConfigurator.java

Ingo Richtsmeier

unread,
Feb 25, 2015, 8:58:13 AM2/25/15
to camunda-...@googlegroups.com
Hi, 


Next step is the integration of the serializer into the engine.

Kind Regards,

Ingo


Ingo Richtsmeier

unread,
Feb 25, 2015, 10:11:59 AM2/25/15
to camunda-...@googlegroups.com
Hi Thorben,

I extended the example and use a process engine plugin to register the new serializer and deserilizer. 

Is there a better way to register them?

If not, I will clean up the example as a pure process engine plugin.

Kind Regards, Ingo

thorben....@camunda.com

unread,
Feb 25, 2015, 12:45:54 PM2/25/15
to camunda-...@googlegroups.com
Hi Ingo,

The problem with your example and in general the idea of retrieving the data format via DataFormats.getDataFormat(..) and then configuring it, is that you have no control over when your configuration gets invoked. Imagine you have many process applications that all use Spin. Now you create a new process engine that uses your process engine plugin. This will change the behavior of the data format for all applications that use it. Ultimately, the core problem with using a process engine plugin is that the lifetime of a Spin data format is not coupled to that of a process engine.

That's why we recommend to use the SPI DataFormatConfigurator. I created an example project under [1]. I'm going to add documentation in the next days. The important parts are the DataFormatConfigurator implementation [2], the file under META-INF/services [3], and the test case [4]. That is pretty much all you need. Of course you have to make sure that the jar containing the configurator is on Spin's classpath (no process engine plugin is needed). Then, Spin looks up the configurator when it initializes the data formats. That is probably a more clean way of configuring data formats because it happens before any application uses a format.

I hope that helps with understanding the idea.

Cheers,
Thorben

[1] https://github.com/camunda/camunda-bpm-examples/tree/master/spin/dataformat-configuration
[2] https://github.com/camunda/camunda-bpm-examples/blob/master/spin/dataformat-configuration/src/main/java/org/camunda/bpm/example/spin/dataformat/configuration/JacksonDataFormatConfigurator.java
[3] https://github.com/camunda/camunda-bpm-examples/blob/master/spin/dataformat-configuration/src/main/resources/META-INF/services/org.camunda.spin.spi.DataFormatConfigurator
[4] https://github.com/camunda/camunda-bpm-examples/blob/master/spin/dataformat-configuration/src/test/java/org/camunda/bpm/example/spin/dataformat/configuration/JacksonConfiguratorTest.java

Ingo Richtsmeier

unread,
Feb 26, 2015, 3:10:15 AM2/26/15
to camunda-...@googlegroups.com
Hi Thorben,

thank you for clarification. Your example is as easy as the process engine plugin and shows to extend the ObjectMapper. 

In the project we follow the approach of one shared engine in an application server. It's easier for the operations team to deploy a central process engine plugin to the appserver than an extension for the spin configuration plus a process engine plugin for listeners etc. The result should be the same.

Kind Regards,

Ingo

Daniel Meyer

unread,
Feb 26, 2015, 5:07:18 AM2/26/15
to camunda-...@googlegroups.com
Hi Ingo,

I don't understand your answer. Are you saying that you do not want to use a DataformatConfigurator? Why?

Regards,
Daniel

Ingo Richtsmeier

unread,
Feb 27, 2015, 9:54:30 AM2/27/15
to camunda-...@googlegroups.com
Hi Daniel, 

I want to create only one single artefact for engine extension. (A custom process engine plugin)

This should make the maintenance of the engine as easy as possible.

Kind Regards, Ingo

Ingo Richtsmeier

unread,
Feb 27, 2015, 2:39:17 PM2/27/15
to camunda-...@googlegroups.com
In an Integration test I got the results that you expected. I installed my process engine plugin in the JBoss distribution and got a null pointer exception during startup. (see first attachment).

Then I realized that the dataFormatConfigurator can be placed in the same jar, so my concerns about maintainability got away.

I build some new JBoss modules with the smartics jboss modules maven plugin and installed it on my jboss server.

The server starts without error, after I disabled the json-jackson and xml-dom modules and replaced them by the dataformat-all module in the spin-plugin-module (see attachment).

But I try to start a process that creates a complex object in a service task and stores it to the process engine I got an other exception: 

Caused by: org.camunda.bpm.engine.ProcessEngineException: Cannot find serializer for value 'Untyped value 'com.camunda.consulting.extendedSerializationProcess.ComplexDataObject@acc6cf9''.
        at org.camunda.bpm.engine.impl.variable.serializer.DefaultVariableSerializers.findSerializerForValue(DefaultVariableSerializers.java:69)
        at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntity.setValue(VariableInstanceEntity.java:264)
        at org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntity.create(VariableInstanceEntity.java:93)

Can you give me a hint, what's missing? In Junit test with the same DataFormatConfigurator, everything is fine.

Kind Regards, Ingo
process engine plugin with jsonSerializer.log
module.xml

Ingo Richtsmeier

unread,
Mar 4, 2015, 5:24:06 AM3/4/15
to camunda-...@googlegroups.com
I improved the configuration of the module and now everything works fine. All nessessary steps are documented in the README.MD.

Kind Reagrds,

Ingo
Reply all
Reply to author
Forward
0 new messages