[
https://jira.jboss.org/jira/browse/JBPM-1914?page=com.atlassian.jira.plug...
]
Alejandro Guizar commented on JBPM-1914:
----------------------------------------
Thanks to Alexandre's insights I was able to understand this problem. Effectively the
original issue reported in JBPM-1024 was never resolved. Instead, attention got diverted
to a related, but not equal, issue: the process class loader was not involved in the
revert operation.
My understanding of the problem is:
1. The jBPM configuration is either parsed from a String or from a resource other than
"jbpm.cfg.xml".
2. The configuration contains a custom jbpm-type description containing a nonstandard
converter.
3. When a variable is set to a value matched by the custom jbpm-type description, the
nonstandard converter is invoked to transform the value to its persistent form.
4. The Hibernate session is managed outside jBPM; for instance, injected through
JbpmContext.setSession or taken from SessionFactory.getCurrentSession.
5. The jBPM context is closed before the Hibernate session is. As a consequence, the
custom jBPM configuration is no longer available to the ConverterEnumType, and the default
configuration, which does not describe the nonstandard converter, is used instead.
6. The column JBPM_VARIABLEINSTANCE.CONVERTER_ is set to null, because the nonstandard
Converter is not specified in the default jbpm.converter.properties.
7. When the variable is read, no converter is applied to the value because none was saved
in the database. Therefore the value is returned in its persistent form.
I was able to reproduce this problem in JBPM1914Test.
A possible explanation to Mauro's observations is:
4. The Hibernate session is managed by jBPM.
5. The Hibernate session is closed before the jBPM context is.
6. The column JBPM_VARIABLEINSTANCE.CONVERTER_ is set to the database ID of the
nonstandard Converter.
7. The variable is read back in a context where the nonstandard Converter specification is
unavailable. Hence no coverter is applied to the persistent form of the value.
How, or why, the above problem can occur with a standard Converter, like the
SerializableToByteArrayConverter, escapes me. Nonetheless, the fact that the
ConverterEnumType causes the default jBPM configuration to be unduly read is already an
issue to deal with.
Problem in retrieving variables of Serializable objects
-------------------------------------------------------
Key: JBPM-1914
URL:
https://jira.jboss.org/jira/browse/JBPM-1914
Project: JBoss jBPM
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: Core Engine
Affects Versions: jBPM 3.3.0 GA
Reporter: Mauro Molinari
Assignee: Alejandro Guizar
Fix For: jBPM 3.2.6 GA
I have encountered a serious problem working with variables whose value is a serializable
object.
The problem is that sometimes (not always!) an error like the following is given when
retrieving a variable:
java.lang.ClassCastException: org.jbpm.bytes.ByteArray$$EnhancerByCGLIB$$cc67d06e
The code is like:
MySerializableClass obj = (MySerializableClass)
contextInstance.getVariable("myVariable");
(of course, "myVariable" is a variable that I previously have set with a
MySerializableClass object)
Apart from the CGLIB awful problem with proxies, even if I extract the value from the
proxy with the following:
public static Object getCGLIBProxiedObject(final Object proxy)
{
if(proxy instanceof HibernateProxy)
{
final LazyInitializer initializer =
((HibernateProxy) proxy).getHibernateLazyInitializer();
return initializer.getImplementation();
}
return proxy;
}
the problem is that the variable value is retrieved as a org.jbpm.bytes.ByteArray instead
of a MyClass instance!
I did some debugging and discovered that:
- in org.jbpm.context.exe.VariableContainer.getVariable(String), when
org.jbpm.context.exe.VariableContainer.hasVariableLocally(String) is called, Hibernate
lazily retrieves a org.jbpm.context.exe.variableinstance.ByteArrayInstance instance from
the database and creates it using its empty constructor
- unfortunately, when a org.jbpm.context.exe.VariableInstance (extended by
ByteArrayInstance) is constructed using its constructor, its converter instance variable
remains null
- the VariableInstance converter instance variable is set to something only when a
VariableInstance is created using org.jbpm.context.exe.JbpmType.newVariableInstance(), but
this is not the case when a VariableInstance is lazily loaded by Hibernate; in fact, in my
case, org.jbpm.context.exe.JbpmType.newVariableInstance() is never called and the
converter field of my ByteArrayInstance instance is always null!
- this causes org.jbpm.context.exe.VariableInstance.getValue() to return the value given
by org.jbpm.context.exe.variableinstance.ByteArrayInstance.getObject() without applying
the necessary conversion (deserialization)
Please note that my variable values are stored in jBPM database in JBPM_VARIABLEINSTANCE
table with the CONVERTER column correctly populated with "R".
I think this is a critical problem. By now, the only workaround I have found is to always
apply the following utility method when retrieving variable values, before returning them
to the client code:
public static Object extractVariableValue(final Object rawValue)
{
Object result = CardinisJbpmUtilities.getCGLIBProxiedObject(rawValue);
if(result instanceof ByteArray)
try
{
result =
new ObjectInputStream(new ByteArrayInputStream(((ByteArray) result)
.getBytes())).readObject();
}
catch(final Exception e)
{
throw new RuntimeException(e);
}
return result;
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira