javasessionopen-libertyjboss-weldweld-se

OpenLiberty Database Session Replication - org.jboss.weld.module.web.HttpSessionBean$SerializableProxy - ClassNotFoundException


I'm using OpenLiberty 24.0.0.6 configured with session replication. The application uses JSF with PrimeFaces. Some of my business objects are store in the HTTP session (via. @SessionScoped annotation of the CDI package).

When the session is deserialized I get the following error (taken from the ffdc log):

Exception = java.lang.ClassNotFoundException
Source = com.ibm.ws.session.SessionLoader.loadObject
probeid = 82
Stack Dump = java.lang.ClassNotFoundException: org.jboss.weld.module.web.HttpSessionBean$SerializableProxy
    at com.ibm.ws.classloading.internal.UnifiedClassLoader.findClass(UnifiedClassLoader.java:167)
    at com.ibm.ws.classloading.internal.ThreadContextClassLoader.findClass(ThreadContextClassLoader.java:145)
    at com.ibm.ws.classloading.internal.UnifiedClassLoader.loadClass0(UnifiedClassLoader.java:141)
    at com.ibm.ws.classloading.internal.UnifiedClassLoader$Delegation.loadClass(UnifiedClassLoader.java:87)
    at com.ibm.ws.classloading.internal.UnifiedClassLoader.loadClass(UnifiedClassLoader.java:106)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:527)
    at com.ibm.ws.serialization.DeserializationObjectInputStream.loadClass(DeserializationObjectInputStream.java:64)
    at com.ibm.ws.serialization.internal.DeserializationObjectInputStreamImpl.loadClass(DeserializationObjectInputStreamImpl.java:50)
    at com.ibm.ws.serialization.DeserializationObjectInputStream.resolveClass(DeserializationObjectInputStream.java:135)
    at com.ibm.ws.serialization.DeserializationObjectInputStream.resolveClass(DeserializationObjectInputStream.java:173)
    at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2003)
    at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1870)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2201)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
    at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2390)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
    at java.base/java.util.Hashtable.readHashtable(Hashtable.java:1315)
    at java.base/java.util.Hashtable.readObject(Hashtable.java:1259)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
    at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
    at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
    at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
    at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
    at com.ibm.ws.session.utils.SessionLoader.loadObject(SessionLoader.java:64)
    at com.ibm.ws.session.store.db.DatabaseHashMap.getValue(DatabaseHashMap.java:1615)

The server is responding:

[15.08.24, 16:03:13:605 MESZ] 0000007c com.ibm.ws.session.WASSession                                E SESN0051E: Attempting to deserialize a session object from the backend resulted in a ClassNotFoundException..
[15.08.24, 16:03:13:605 MESZ] 0000007c com.ibm.ws.session.WASSession                                E ID: n3KSj82AVIMrmIK9ZH8A0WH
[15.08.24, 16:03:13:605 MESZ] 0000007c com.ibm.ws.session.WASSession                                E Exception: 
java.lang.ClassNotFoundException: org.jboss.weld.module.web.HttpSessionBean$SerializableProxy

My configuration in the OL:

<?xml version="1.0" encoding="UTF-8"?>
<server>
    <!-- https://openliberty.io/docs/latest/create-session-table.html -->
    <library id="SessionDriverLib">
        <fileset dir="${shared.resource.dir}/session" includes="*.jar"/>
    </library>

    <dataSource id="SessionDS">
        <jdbcDriver libraryRef="SessionDriverLib" />
        <properties.postgresql serverName="${postgres_server}"
                               portNumber="5432"
                               databaseName="httpSession"
                               user="session_user"
                               password="***"/>
    </dataSource>

    <httpSessionDatabase
            id="SessionDB"
            dataSourceRef="SessionDS"
            tableName="sessions"/>
    <httpSession storageRef="SessionDB" cloneId="${clone_id}"/>

</server>

And we are using the following features:

  <featureManager>
    <feature>javaee-8.0</feature>
    <feature>microProfile-3.3</feature>
    <feature>monitor-1.0</feature>
    <feature>sessionDatabase-1.0</feature>
  </featureManager>

I logged out the content of the HTTP session and I was wondering that a WELD proxy is part of the session:

attribute name: 
WELD_S#F_WELD%AbstractBuiltInBean%web_war_exploded#twl-web%HttpSession

attribute value (from toString())
Bean: ForwardingBean null for WELD%AbstractBuiltInBean%web_war_exploded#web%HttpSession; Instance: org.jboss.weld.module.web.HttpSessionBean$SerializableProxy@1bbaee59; CreationalContext: org.jboss.weld.contexts.CreationalContextImpl@27396b8a

I have no idea, why WELD is storing such a proxy class in the session. Btw. some content is stored in the database.

All the objects stored in the HTTP session are serializable. If not I think I would get an NotSerializableExcpeption (which is not in the logs or traces)

I was looking for the serialized data in the database and found the proxy class.

There are no WELD dependencies in the application (meaning the application war). The classpath look ok to me.

If you need more information, let me know.

Any ideas are welcome. :-)


Solution

  • I think your scenario should work and I'm fairly sure this is a bug in Liberty. (I've reproduced it on a later version of CDI and the version you're using appears to have the same issue.)

    I think the problem will occur when HttpSession is injected. Behind the scenes, Weld uses a SessionScoped bean to enable this which is why the object gets persisted as part of the session. The bug is that liberty doesn't look in the correct package to find the class to deserialize this object when the session is restored.

    Please open a Bug Report on github and we'll get it fixed.

    Update: the fix for this bug was included in 24.0.0.9