Search code examples
javajmsactivemq-classicclassnotfoundexceptionnoclassdeffounderror

Introducing a middle base class causes ActiveMQ/JMS NoClassDefFoundError


Currently I have an application that sends a JMS ObjectMessage to an ActiveMQ destination. The messages are all derived from class base.

However, I needed to add a class between certain derived classes and the base class, so class middle extends base. Now, all the messages that extends middle fail to send, giving the following error:

26 18:53:04.524 [ListenerContainer-1] WARN  - Execution of JMS message listener failed
java.lang.NoClassDefFoundError: com/google/protobuf/ProtocolMessageEnum
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
...

Caused by: java.lang.ClassNotFoundException: com.google.protobuf.ProtocolMessageEnum
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

The messages that do not extend middle work still, only the messages that derives from middle now cause the problem. Any help is appreciated. Thanks!

Edit: The sending is handled by session.createObjectMessage(msg) where msg is of type base.


Solution

  • Given the fact that you're sending a JMS ObjectMessage it looks to me like your client simply doesn't have the proper classes on the classpath to deserialize the message. Ensure the clients have the "middle" class and any new parameter types on their classpath. At the very least they'll need com.google.protobuf.ProtocolMessageEnum (as indicated by the exception).

    For what it's worth, JMS ObjectMessage is often avoided for this and other reasons. It's usually simpler to send raw byte buffers or some simple object representation (e.g. XML, JSON, etc.) rather than actual Java objects. Also, Java serialization and deserialization are notoriously slow and this pattern can open your application to security vulnerabilities as well.