4 Replies Latest reply on Oct 14, 2011 7:44 AM by salaboy21

    jBPM5 and ObjectMarshallingStrategy

    mnorsic

      Hi All,

       

      I have a question about persistent JPA object marshalling strategies.

      I'd like to use jBPM5 in an already built project that uses custom ORM mapper (something similar to Hibernate, but uses its own persistency mechanism).

      Ideally, I'd love to use somethning similar to JPAPlaceholderResolverStrategy, to force jBPM5 to store only class name and its primary key.

       

      So I've started to look into jBPM5 code to see where can I plug in my persistency mechanism, and found that I have to add my custom object marshaller into enviroment:

      env.set(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES, new ObjectMarshallingStrategy[] {
      new MyCustomMarshallingStrategy(env),
       new JPAPlaceholderResolverStrategy(env),
       new SerializablePlaceholderResolverStrategy(ClassObjectMarshallingStrategyAcceptor.DEFAULT) });
      

       

      So, now my custom resolver is used in marshalling and unmarshalling to write and read object reference into database, instead storing whole serialized object, and that seems OK.

      But my custom Java objects do not implement Serializable, and I've spotted the following error:

       

      java.lang.RuntimeException: Unable to get session snapshot
       at org.drools.persistence.SessionMarshallingHelper.getSnapshot(SessionMarshallingHelper.java:75)
       at org.drools.persistence.info.SessionInfo.update(SessionInfo.java:81)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.ejb.event.BeanCallback.invoke(BeanCallback.java:23)
       at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:80)
       at org.hibernate.ejb.event.EntityCallbackHandler.preUpdate(EntityCallbackHandler.java:65)
       at org.hibernate.ejb.event.EJB3FlushEntityEventListener.invokeInterceptor(EJB3FlushEntityEventListener.java:41)
       at org.hibernate.event.def.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:330)
       at org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:270)
       at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:151)
       at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
       at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
       at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
       at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:504)
       ... 28 more
      Caused by: java.io.NotSerializableException: hr.mnorsic.test.bo.SomeClass
       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
       at java.util.HashMap.writeObject(HashMap.java:1001)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
       at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
       at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
       at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
       at java.util.ArrayList.writeObject(ArrayList.java:570)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:945)
       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
      at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
       at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
       at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
       at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
       at org.drools.marshalling.impl.SerializablePlaceholderResolverStrategy.write(SerializablePlaceholderResolverStrategy.java:53)
       at org.drools.marshalling.impl.OutputMarshaller.writeFactHandle(OutputMarshaller.java:305)
       at org.drools.marshalling.impl.OutputMarshaller.writeFactHandle(OutputMarshaller.java:325)
       at org.drools.marshalling.impl.OutputMarshaller.writeFactHandles(OutputMarshaller.java:267)
       at org.drools.marshalling.impl.OutputMarshaller.writeSession(OutputMarshaller.java:107)
       at org.drools.marshalling.impl.DefaultMarshaller.marshall(DefaultMarshaller.java:136)
       at org.drools.persistence.SessionMarshallingHelper.getSnapshot(SessionMarshallingHelper.java:72)
      

       

      My class (SomeClass) does not implement Serializable, but it seems weird that jBPM is trying to use SerializablePlaceholderResolverStrategy to store knowledge session info instead my own persistency strategy.

      Digging down into jBPM5 code, I have found that RuleFlowProcessInstance object is serialized by using SerializablePlaceholderResolverStrategy, and that object contains VariableScopeInstance object (in a subContextInstances HashMap).

      And VariableScopeInstance contains process instance variables, so they are serialized into a byte array instead using JPA strategy (or my own strategy, doesn't matter).

      At the same time, process instance is stored correctly (it uses JPA resolver strategy and stores only a reference to an object stored in a database).

       

      I think this is not correct, as process instance contains a reference to an object a database, and session info contains whole serialized objects?

       

      Could please someone from jBPM team review my observation?

      My guess is that when RuleFlowProcessInstance is persisted, subContextInstances Map should be examined, and for each element a query to a objectMarshallingStrategyStore accept() method should be called to determine the correct persistence strategy.

       

      Thanks,

      Miljenko

       

      P.S. forgot to mention: my process contains rule task and custom tasks (controlled by custom work item handler).