]
Thomas Diesler updated JBPM-1914:
---------------------------------
Priority: Major (was: Critical)
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
Fix For: jBPM 3.3.2 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: