JPA integration not working 100% for transient variables???

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 04:52 AM
I've setup JPA integration and initially it seems to work, but I find a deviation.
My entity classes all extend an AbstractBean class where the code for a.o. property change events is present. This class also has the possibility to block (ignore) these events (this is required when setting up default values, you do not want the entity to become marked "dirty"). Anyhow, in order to block these events there is a transient property in the abstract bean class:
I've changed that property temporarly to public, so I can inspect it. Now, when a entity is put into the variables map at the starting of a workflow, this property naturally is not null:
A bit later in the process a task listener is called, which fetches this variable:
When this workflow is run, the following output appears on the console:
The transient property has not been initialized?!! This is very strange, since it is final and the constructor has finished.
So as a test I simply reloaded the entity from the EM.
The output now is:
So something is not going right when restoring the entity.
My entity classes all extend an AbstractBean class where the code for a.o. property change events is present. This class also has the possibility to block (ignore) these events (this is required when setting up default values, you do not want the entity to become marked "dirty"). Anyhow, in order to block these events there is a transient property in the abstract bean class:
@Transient transient final public AtomicInteger ignoreChangesGate = new AtomicInteger();
I've changed that property temporarly to public, so I can inspect it. Now, when a entity is put into the variables map at the starting of a workflow, this property naturally is not null:
Map<String, Object> lProcessVariables = new HashMap<>(); lProcessVariables.put("a", this); System.out.println("!!!1 iIgnoreChangesGate = " + this.ignoreChangesGate); ProcessInstance lProcessInstance = lProcessEngine.getRuntimeService().startProcessInstanceByKey("frozn", lProcessVariables);
A bit later in the process a task listener is called, which fetches this variable:
@Override public void notify(org.activiti.engine.delegate.DelegateTask delegateTask) { Application lApplication = (Application)delegateTask.getVariable("a"); System.out.println("!!!2 iIgnoreChangesGate = " + lApplication.ignoreChangesGate); …
When this workflow is run, the following output appears on the console:
!!!1 iIgnoreChangesGate = 0!!!2 iIgnoreChangesGate = null
The transient property has not been initialized?!! This is very strange, since it is final and the constructor has finished.
So as a test I simply reloaded the entity from the EM.
@Override public void notify(org.activiti.engine.delegate.DelegateTask delegateTask) { Application lApplication = (Application)delegateTask.getVariable("a"); System.out.println("!!!2 iIgnoreChangesGate = " + lApplication.ignoreChangesGate); // reload lApplication = (Application)lEntityManager.find(Application.class, lApplication.getApplicationId()); System.out.println("!!!3 iIgnoreChangesGate = " + lApplication.ignoreChangesGate); …
The output now is:
!!!1 iIgnoreChangesGate = 0!!!2 iIgnoreChangesGate = null!!!3 iIgnoreChangesGate = 0
So something is not going right when restoring the entity.
Labels:
- Labels:
-
Archive
5 REPLIES 5

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 05:32 AM
Hi,
Do you have async behavior in your process definition?
Can you create a unit test that shows this behavior?
Thanks,
Do you have async behavior in your process definition?
Can you create a unit test that shows this behavior?
Thanks,

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 06:02 AM
I do not have an async process.
I'vecreated my own implementation, which generates a String from an entity (classname:id) and reloads the entity based on the information in the listener. This works without a problem. (It also has the advantage that, because I mix and match workflow and regular code, it makes sure only one EntityManager is used; no conflicts.)
A unit test, well it is happening as part of my own unit test, so I could strip that down… I'll give it a try.
I'vecreated my own implementation, which generates a String from an entity (classname:id) and reloads the entity based on the information in the listener. This works without a problem. (It also has the advantage that, because I mix and match workflow and regular code, it makes sure only one EntityManager is used; no conflicts.)
A unit test, well it is happening as part of my own unit test, so I could strip that down… I'll give it a try.

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 06:45 AM
Yeah. Now that I've stripped it down far enough, the problem is gone. So there is some kind of conflict between what I do in the frame of my application, and how Activiti restores the entity. So I can't give you a simple unit test that reproduces the problem.
What I do know is that:
- in the activiti implementation a final field ends up being null (that is very strange)
- using my simple implementation of encode-as-string and find-using-string in the same context works fine
My question would be: what magic are you guys doing to restore the entity? It seems the constructor is somehow by passed. (Note that I have 5 layer deep entity classes.) As said, this simple piece of code works fine:
I can offer you to take a remote-desktop peek in my development environment.
What I do know is that:
- in the activiti implementation a final field ends up being null (that is very strange)
- using my simple implementation of encode-as-string and find-using-string in the same context works fine
My question would be: what magic are you guys doing to restore the entity? It seems the constructor is somehow by passed. (Note that I have 5 layer deep entity classes.) As said, this simple piece of code works fine:
static public <T> T fromId(Object id)
{
try
{
// preconditions
String lId = "" + id;
if ("null".equals(lId)) return null;
// split id
int lIdx = lId.indexOf(":");
String lClassname = lId.substring(0, lIdx);
BigInteger lPK = new BigInteger(lId.substring(lIdx + 1));
// get entity
EntityManager lEntityManager = EntityManagerFinder.find();
T lEntity = (T)lEntityManager.find(Class.forName(lClassname), lPK);
return lEntity;
}
catch (ClassNotFoundException e) { throw new IllegalStateException(e); }
}
I can offer you to take a remote-desktop peek in my development environment.

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 09:32 AM
Hmmm. I've taken a peek at what is in the ACT_RU_VARIABLE table and I see that my approach stores a "nl.o837.frozn.bm.Application:74" text. However, Activiti seems to store a serializable. Do you actually serialize and store the whole entity? That should not be, the user manual says "When the variable is requested the next time, it will be loaded from the EntityManager based on the class and Id stored.".

Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-06-2012 10:58 AM
It's the "transient" keyword; it tells Java's serializer to not serialize a field. And that is how you get a final field to become null…
