ActiveMQ
  1. ActiveMQ
  2. AMQ-2488

Unable to access Serializable class when receiving ObjectMessage in OSGi environment

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.3.0
    • Fix Version/s: 5.7.0
    • Component/s: Broker
    • Labels:
      None

      Description

      I have configured applications to use Log4J's JMSAppender in order to log messages on a queue as follows;

      log4j.appender.jms=org.apache.log4j.net.JMSAppender
      log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory
      log4j.appender.jms.ProviderURL=tcp://localhost:61616
      log4j.appender.jms.TopicBindingName=logTopic
      log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory
      

      Each application logging statement adds a new message to topic://logTopic on the broker. I have a bundle deployed that attempts to route the messages from this topic with camel;

      from("activemq:topic:logTopic")
        .convertBodyTo(String.class)
        .to("log:foo?level=DEBUG&showProperties=true&showHeaders=true");
      

      When using servicemix 4 (Fuse 4.1.0.4), a stack trace is seen with the following message (enhanced using felix.log.level=4);

      Caused by: java.lang.ClassNotFoundException: *** Class 'org.apache.log4j.spi.LoggingEvent' 
      was not found because bundle 56 does not import 'org.apache.log4j.spi' even though bundle 84 
      does export it. To resolve this issue, add an import for 'org.apache.log4j.spi' to bundle 56. ***
      

      Bundles as follows;

      smx@root:/> osgi/list|grep 56
      [  56] [Active     ] [       ] [   60] activemq-core (5.3.0.fuse)
      
      smx@root:/> osgi/list|grep 84
      [  84] [Active     ] [       ] [    8] OPS4J Pax Logging - API (1.3.0)
      
      1. SMX4-424.diff
        2 kB
        Gert Vanthienen
      2. amq-headers.log
        28 kB
        Darren Davison
      3. amq-error.log
        15 kB
        Darren Davison

        Activity

        Hide
        Darren Davison added a comment -

        complete stack trace attached in amq-error.log
        output of OSGi headers for activemq-core bundle attached in amq-headers.log

        Show
        Darren Davison added a comment - complete stack trace attached in amq-error.log output of OSGi headers for activemq-core bundle attached in amq-headers.log
        Hide
        Maciej Prochniak added a comment -

        Do you have this log4j import in your bundle (containing camel route)? I guess the felix debug message (... was not found because ...) can be misleading - I think it should be your camel bundle that imports 'org.apache.log4j.spi' package

        Show
        Maciej Prochniak added a comment - Do you have this log4j import in your bundle (containing camel route)? I guess the felix debug message (... was not found because ...) can be misleading - I think it should be your camel bundle that imports 'org.apache.log4j.spi' package
        Hide
        Gert Vanthienen added a comment -

        I think the message on the CNFE is correct: if you look at the stack traces, you'll notice that it's ActiveMQ's ClassLoadingAwareObjectInputStream class that is trying to load the org.apache.log4j.spi.LoggingEvent class.

        With the current OSGi bundle configuration for activemq-core, it can not access that class. The easy solution would be to add a dynamic import to the activemq-core bundle as in the attached SMX4-424.diff file. Another option would be to modify the ClassLoadingAwareObjectInputStream class to use OSGi's FrameworkUtil class to determine the correct classloader.

        Show
        Gert Vanthienen added a comment - I think the message on the CNFE is correct: if you look at the stack traces, you'll notice that it's ActiveMQ's ClassLoadingAwareObjectInputStream class that is trying to load the org.apache.log4j.spi.LoggingEvent class. With the current OSGi bundle configuration for activemq-core, it can not access that class. The easy solution would be to add a dynamic import to the activemq-core bundle as in the attached SMX4-424 .diff file. Another option would be to modify the ClassLoadingAwareObjectInputStream class to use OSGi's FrameworkUtil class to determine the correct classloader.
        Hide
        Gert Vanthienen added a comment -

        This issue was originally created for ServiceMix 4, but I think the real issue is inside the activemq-core bundle.

        Show
        Gert Vanthienen added a comment - This issue was originally created for ServiceMix 4, but I think the real issue is inside the activemq-core bundle.
        Hide
        Darren Davison added a comment -

        sorry, I thought I'd included those OSGi headers in one of the attachments. It does import that package. Here are the headers from my bundle with the camel route (line breaks added by me for formatting)

        Application Log Router (75)
        ---------------------------
        Manifest-Version = 1.0
        Bnd-LastModified = 1257721682850
        Tool = Bnd-0.0.238
        Bundle-Name = Application Log Router
        Built-By = darren
        Import-Package = org.apache.activemq;version="5.2.0.fuse",
          org.apache.camel; version="1.6.1.fuse",
          org.apache.camel.builder;version="1.6.1.fuse",
          org.apache.camel.component.jms;version="1.6.1.fuse",
          org.apache.camel.model;version="1.6.1.fuse",
          org.apache.camel.spring;version="1.6.1.fuse",
          org.apache.commons.logging,
          org.apache.log4j.spi,
          org.davisononline.fuselogger
        Bundle-SymbolicName = org.davisononline.fuse-logger
        Export-Package = org.davisononline.fuselogger;
          uses:="org.apache.camel.builder,org.apache.camel.model,
            org.apache.commons.logging,org.apache.camel,org.apache.camel.spring"
        Bundle-Version = 0.0.1.SNAPSHOT
        Build-Jdk = 1.6.0_16
        Created-By = Apache Maven Bundle Plugin
        Bundle-ManifestVersion = 2
        



        I queried this all with gertv on IRC, it was he that suggested this looked like an activemq bug and henced raised here.

        Show
        Darren Davison added a comment - sorry, I thought I'd included those OSGi headers in one of the attachments. It does import that package. Here are the headers from my bundle with the camel route (line breaks added by me for formatting) Application Log Router (75) --------------------------- Manifest-Version = 1.0 Bnd-LastModified = 1257721682850 Tool = Bnd-0.0.238 Bundle-Name = Application Log Router Built-By = darren Import-Package = org.apache.activemq;version="5.2.0.fuse", org.apache.camel; version="1.6.1.fuse", org.apache.camel.builder;version="1.6.1.fuse", org.apache.camel.component.jms;version="1.6.1.fuse", org.apache.camel.model;version="1.6.1.fuse", org.apache.camel.spring;version="1.6.1.fuse", org.apache.commons.logging, org.apache.log4j.spi, org.davisononline.fuselogger Bundle-SymbolicName = org.davisononline.fuse-logger Export-Package = org.davisononline.fuselogger; uses:="org.apache.camel.builder,org.apache.camel.model, org.apache.commons.logging,org.apache.camel,org.apache.camel.spring" Bundle-Version = 0.0.1.SNAPSHOT Build-Jdk = 1.6.0_16 Created-By = Apache Maven Bundle Plugin Bundle-ManifestVersion = 2 I queried this all with gertv on IRC, it was he that suggested this looked like an activemq bug and henced raised here.
        Hide
        Dejan Bosanac added a comment -

        Fixed with svn revision 898812

        Show
        Dejan Bosanac added a comment - Fixed with svn revision 898812
        Hide
        Darren Davison added a comment -

        I still appear to get similar issues even with the dynamic import in the manifest:

        21:35:46,565 | ERROR | tenerContainer-2 | EndpointMessageListener | rg.apache.camel.processor.Logger 248 | Caused by: [org.apache.camel.RuntimeCamelException - Failed to extract body due to: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent. Message: ActiveMQObjectMessage

        {commandId = 5, responseRequired = true, messageId = ID:hepburn-51431-1271622946297-0:0:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hepburn-51431-1271622946297-0:0:1:1, destination = topic://logTopic, transactionId = null, expiration = 0, timestamp = 1271622946535, arrival = 0, brokerInTime = 1271622946538, brokerOutTime = 1271622946539, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@13bef50, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false}

        ]
        org.apache.camel.RuntimeCamelException: Failed to extract body due to: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent. Message: ActiveMQObjectMessage

        {commandId = 5, responseRequired = true, messageId = ID:hepburn-51431-1271622946297-0:0:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hepburn-51431-1271622946297-0:0:1:1, destination = topic://logTopic, transactionId = null, expiration = 0, timestamp = 1271622946535, arrival = 0, brokerInTime = 1271622946538, brokerOutTime = 1271622946539, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@13bef50, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false}

        at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:158)
        at org.apache.camel.component.jms.JmsMessage.createBody(JmsMessage.java:183)
        at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:42)
        at org.apache.camel.impl.DefaultUnitOfWork.<init>(DefaultUnitOfWork.java:60)
        at org.apache.camel.processor.UnitOfWorkProcessor.processNext(UnitOfWorkProcessor.java:56)
        at org.apache.camel.processor.DelegateProcessor.process(DelegateProcessor.java:48)
        at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:67)
        at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:84)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:543)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:482)
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:451)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:323)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:261)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:974)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876)
        at java.lang.Thread.run(Thread.java:619)
        Caused by: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent
        at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:35)
        at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:179)
        at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:125)
        ... 16 more
        Caused by: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:468)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:398)
        at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:105)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)
        at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.load(ClassLoadingAwareObjectInputStream.java:63)
        at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:37)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
        at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:177)
        ... 17 more

        Show
        Darren Davison added a comment - I still appear to get similar issues even with the dynamic import in the manifest: 21:35:46,565 | ERROR | tenerContainer-2 | EndpointMessageListener | rg.apache.camel.processor.Logger 248 | Caused by: [org.apache.camel.RuntimeCamelException - Failed to extract body due to: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent. Message: ActiveMQObjectMessage {commandId = 5, responseRequired = true, messageId = ID:hepburn-51431-1271622946297-0:0:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hepburn-51431-1271622946297-0:0:1:1, destination = topic://logTopic, transactionId = null, expiration = 0, timestamp = 1271622946535, arrival = 0, brokerInTime = 1271622946538, brokerOutTime = 1271622946539, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@13bef50, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false} ] org.apache.camel.RuntimeCamelException: Failed to extract body due to: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent. Message: ActiveMQObjectMessage {commandId = 5, responseRequired = true, messageId = ID:hepburn-51431-1271622946297-0:0:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:hepburn-51431-1271622946297-0:0:1:1, destination = topic://logTopic, transactionId = null, expiration = 0, timestamp = 1271622946535, arrival = 0, brokerInTime = 1271622946538, brokerOutTime = 1271622946539, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@13bef50, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false} at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:158) at org.apache.camel.component.jms.JmsMessage.createBody(JmsMessage.java:183) at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:42) at org.apache.camel.impl.DefaultUnitOfWork.<init>(DefaultUnitOfWork.java:60) at org.apache.camel.processor.UnitOfWorkProcessor.processNext(UnitOfWorkProcessor.java:56) at org.apache.camel.processor.DelegateProcessor.process(DelegateProcessor.java:48) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:67) at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:84) at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:543) at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:482) at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:451) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:323) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:261) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:974) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876) at java.lang.Thread.run(Thread.java:619) Caused by: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:35) at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:179) at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:125) ... 16 more Caused by: java.lang.ClassNotFoundException: org.apache.log4j.spi.LoggingEvent at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:468) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:398) at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:105) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.load(ClassLoadingAwareObjectInputStream.java:63) at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:37) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351) at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:177) ... 17 more
        Hide
        PK Tan added a comment -

        Hi, any updates on this issue ? Is it fixed in version 5.5.0 or will there be any upcoming fix?

        I see a similar stacktrace on my side using activemq version 5.4.2. Is there any other way to verify that I have the same problem on my side other than using the stacktrace?

        For my case, I've deployed ActiveMQ embedded within WebLogic 10.

        Thank you for your time.

        Show
        PK Tan added a comment - Hi, any updates on this issue ? Is it fixed in version 5.5.0 or will there be any upcoming fix? I see a similar stacktrace on my side using activemq version 5.4.2. Is there any other way to verify that I have the same problem on my side other than using the stacktrace? For my case, I've deployed ActiveMQ embedded within WebLogic 10. Thank you for your time.
        Hide
        Edstrom Johan added a comment -

        Have confirmed the same on a 5.5 embedded in servicemix 4.0, possible to
        workaround by doing the serialization yourself and making sure that mapJmsMessage=false in camel.

        The problem is in :

        https://svn.apache.org/repos/asf/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java

        Will try to get a patch together against a 5.5 release.

        Show
        Edstrom Johan added a comment - Have confirmed the same on a 5.5 embedded in servicemix 4.0, possible to workaround by doing the serialization yourself and making sure that mapJmsMessage=false in camel. The problem is in : https://svn.apache.org/repos/asf/activemq/trunk/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java Will try to get a patch together against a 5.5 release.
        Hide
        Claus Ibsen added a comment -

        In the camel-sql component there is a JDBC based support for a persistent store for the aggregator EIP. And the serialization logic was a copy of that class mentioned above. We recently had this problem with class loading in OSGi, so we had to use an OSGi aware class loader. So I guess a similar issue exists now in AMQ when running under OSGi.

        Show
        Claus Ibsen added a comment - In the camel-sql component there is a JDBC based support for a persistent store for the aggregator EIP. And the serialization logic was a copy of that class mentioned above. We recently had this problem with class loading in OSGi, so we had to use an OSGi aware class loader. So I guess a similar issue exists now in AMQ when running under OSGi.
        Hide
        Edstrom Johan added a comment -

        The fallback strategy really is the problem.
        I think this whole classloader should be delegated back to the consumer of the object.

        The * dynamic import in a server is a kinda sorta solution to me.

        Show
        Edstrom Johan added a comment - The fallback strategy really is the problem. I think this whole classloader should be delegated back to the consumer of the object. The * dynamic import in a server is a kinda sorta solution to me.
        Hide
        Edstrom Johan added a comment -

        Just had this confirmed on a non osgi deploy as well.

        Show
        Edstrom Johan added a comment - Just had this confirmed on a non osgi deploy as well.
        Hide
        Johno Crawford added a comment -

        Any luck with the patch Edstrom?

        Show
        Johno Crawford added a comment - Any luck with the patch Edstrom?
        Hide
        Claus Ibsen added a comment -

        Working on using the classloader from the input stream as fallback.

        But ideally we may have to do as in Camel to have a ClassResover SPI, which can adapt to its environments, standalone, OSGi, jee etc.

        Show
        Claus Ibsen added a comment - Working on using the classloader from the input stream as fallback. But ideally we may have to do as in Camel to have a ClassResover SPI, which can adapt to its environments, standalone, OSGi, jee etc.
        Hide
        Claus Ibsen added a comment -

        Committed a fix to trunk that uses the classloader of the input stream as 2nd fallback.

        Fell free to give the code on trunk a try.

        Show
        Claus Ibsen added a comment - Committed a fix to trunk that uses the classloader of the input stream as 2nd fallback. Fell free to give the code on trunk a try.

          People

          • Assignee:
            Claus Ibsen
            Reporter:
            Darren Davison
          • Votes:
            3 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development