JBoss and Resteasy: ClassNotFoundException when deserializing a Java serialized object

Context: we use Activiti as a process engine and Activiti-Rest as an interface to our application. Since the question is about REST services returning objects serialized by Java, I did not add this to the header.

Scenario: we have a JBoss Wildfly instance that contains an EAR with a module (lets call it X for reference) that contains the class "ProcessContext". Activiti runs inside this EAR, and ServiceTasks (Java fragments called from processes to do some work) depend on this class. They use this class to instantiate a process variable and add some data to it.

We have a second deployment (WAR, currently on the same Wildfly instance, but later on the remote server) that accesses Activiti using the REST api, and now we need to access the ProcessContext data. This WAR also has an X dependency, and its class loader can solve the "ProcessContext" problem without problems.

Good Excellent. It was easy to do. Call:

GET history/historic-process-instances/{processInstanceId}/variables/{variableName}/data

This returns a response with MediaType "application / x-java-serialized-object", and checking it with a debugger seems fine. But when I tried to deserialize the object, I got this error:

Caused by: java.lang.ClassNotFoundException: xxx.commons.metadata.ProcessMetadata from [Module "org.jboss.resteasy.resteasy-jaxrs:main" from local module loader @103f852 (finder: local module finder @587c290d (roots: /opt/wildfly/modules,/opt/wildfly/modules/system/layers/base))]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:213) [jboss-modules.jar:1.3.3.Final]
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:459) [jboss-modules.jar:1.3.3.Final]
at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:408) [jboss-modules.jar:1.3.3.Final]
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:389) [jboss-modules.jar:1.3.3.Final]
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:134) [jboss-modules.jar:1.3.3.Final]
at java.lang.Class.forName0(Native Method) [rt.jar:1.8.0_20]
at java.lang.Class.forName(Class.java:340) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:626) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) [rt.jar:1.8.0_20]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) [rt.jar:1.8.0_20]
at org.jboss.resteasy.plugins.providers.SerializableProvider.readFrom(SerializableProvider.java:76) [resteasy-jaxrs-3.0.10.Final.jar:]
... 131 more

After thinking about this, I found that the Classloader, which is used to deserialize an object, if the Resteasy module-Classloader module is instead a local (modular) class loader.

, , , "ProcessContext" JBoss, , .

Resteasy , - ? , , . , .

, ?

+4
2

, , , Resteasy . web.xml, , .

, similr, . :

@Provider
@Consumes("application/x-java-serialized-object")
public class ActivitiObjectMessageBodyReader implements MessageBodyReader<ProcessMetadata> {

@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return (type == ProcessMetadata.class && "application/x-java-serialized-object".equals(mediaType.toString()));
}

@Override
public ProcessMetadata readFrom(Class<ProcessMetadata> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {

    BufferedInputStream bis = new BufferedInputStream(entityStream);
    ObjectInputStream ois = new ObjectInputStream(bis);
    try {
        return ProcessMetadata.class.cast(ois.readObject());
    } catch (ClassNotFoundException e) {
        throw new WebApplicationException(e);
    }
}

}

, , , isReadable - , ...

:

ResteasyProviderFactory factory = new ResteasyProviderFactory();
factory.register(new ActivitiObjectMessageBodyReader());
Configuration configuration = new ClientConfiguration(factory);

:

Client client = ClientBuilder.newClient(configuration);

, Java REST.

----- , , . -----

- resteasy. , :

Providers current = ResteasyProviderFactory.getContextData(Providers.class);
ResteasyProviderFactory.pushContext(Providers.class, configuration);

web.xml RegisterBuiltin.register(factory), , , . , , factory Resteasy, - . , , . resteasy.scan web.xml, .

factory , , ( bean), .

+2

Jboss SerializableProvider web.xml

https://github.com/resteasy/Resteasy/blob/master/jaxrs/resteasy-jaxrs/src/main/java/org/jboss/resteasy/plugins/providers/SerializableProvider.java

<context-param>
        <param-name>resteasy.scan.providers</param-name>
        <param-value>true</param-value>
</context-param>
0

All Articles