Announcement Announcement Module
Collapse
No announcement yet.
Wrong messages received in JMS-backed channel Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wrong messages received in JMS-backed channel

    Hello everyone,

    I am trying to take my first steps with SI, which looks really promising for my needs. But unfortunately I am stucked trying to get around a problem.

    What I am trying to do is to simulate the following situation:

    - A fast producer
    - A slow consumer
    - A JMS-backed channel that connects them two and can buffer (on disk) messages for the slow consumer

    My platform is OSGi(Equinox)-SI-ActiveMq.

    The messages' payloads are just java.lang.String for testing purposes.

    My beans configuration looks like this:

    Code:
        <bean id="jmsServer" class="org.apache.activemq.broker.BrokerService"
            init-method="start">
            <property name="persistent" value="false" />
            <property name="transportConnectorURIs">
                <list>
                    <value>vm://mybroker</value>
                </list>
            </property>
            <property name="useJmx" value="false"/>
    
        </bean>
    
    	<bean id="myConnectionFactory"
    		class="org.springframework.jms.connection.SingleConnectionFactory"
    		depends-on="jmsServer">
    		<property name="targetConnectionFactory">
    			<bean class="org.apache.activemq.ActiveMQConnectionFactory">
    				<property name="brokerURL"
    					value="vm://mybroker" />
    			</bean>
    		</property>
    	</bean>
    
    	<int-jms:channel id="jmsChannel" connection-factory="myConnectionFactory"
    		queue-name="repliesJmsQueue" cache="none" message-driven="false"  />
    
    	<bean id="myMessageProducer" class="test_sjms.tests.MyMessageProducer"
    		depends-on="jmsChannel">
    		<property name="channel" ref="jmsChannel" />
    	</bean>
    
    	<bean id="myMessageReceiver" class="test_sjms.tests.MyMessageReceiver"
    		depends-on="jmsChannel">
    		<property name="channel" ref="jmsChannel" />
    	</bean>

    As for my Java code, the sender:

    Code:
    				String payload = someString; // some test String
    				Message<String> message = MessageBuilder.withPayload(payload).build();
    				this.channel.send(message);
    And the receiver:

    Code:
    channel.receive();
    Both 'channel' members are instances of org.springframework.integration.core.PollableChann el.

    When starting the application, the JMS broker starts up well and messages are sent into the queue normally. But at the receiver's side, when calling receive() on the channel, the following error happens:

    Code:
    javax.jms.JMSException: Failed to build body from bytes. Reason: java.io.IOException: org.springframework.integration.message.GenericMessage
    	at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:35)
    	at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:183)

    Perhaps I am missing something obvious, but this is driving me crazy.

    I've seen a thread on a (maybe) similar subject,

    http://forum.springsource.org/showthread.php?t=63106

    But I wasn't able to make it help, since I am making my tests in a single VM (even in a single Equinox bundle).

    I would appreciate very much any hint on this issue.

    Thanking You in advance.

    David
    Last edited by david_x; Jan 22nd, 2011, 08:20 PM. Reason: typo

  • #2
    I did a bit of debugging and at leas I was able to make the problem more clear, whilst not finding a solution.

    Indeed, just as it was suggested in this thread by mbogoevici, the problem is a ClassNotFoundException thrown by the ActiveMQ bundle. When ActiveMQ tries to use a ClassLoadingAwareObjectInputStream to deserialize the gotten message, it just cannot find the GenericMessage class and raises an exception.

    Comment


    • #3
      Ok, my next step led me to deeper water.

      I don't know how to solve it but the problem seems to have acquired quite common traits.

      It's about Equinox (OSGi-natured), the thread's context's ClassLoader and Class.forName().

      The ActiveMQ bundle attempts to deserialize an instance of SI's GenericMessage, that is the one received from the queue. And it does it by using the threads context's ClassLoader and Class.forName().

      The threads context's ClassLoader happens to be a Equinox' ContextFinder instance, which as far as I heard attempts to be a solution for Class.forName() issues in OSGi.

      That's all what I can say at the moment. I don't know how to solve this, but maybe someone had a similar problem?

      Anyway this looks an ActiveMQ issue, so probably it's a good idea to post my issue in their forum.

      Just in case someone happen to need it, I found a blog that talks quite interestingly about this subject.
      Last edited by david_x; Jan 23rd, 2011, 06:54 AM.

      Comment


      • #4
        Success!

        I managed to find a kind of solution to this problem. Let me post it here - it might be useful to someone.

        Well, it's just as simple as the creation of a fragment bundle for the bundle activemq-core. In its "standard" form, the ActiveMQ doesn't have injected dependencies to third-party libraries (e.g SI). So in principle its ClassLoader (every OSGi bundle has its own instance) won't see classes from those libraries (in my example, the 'invisible class' was SI's GenericMessage).

        There seem to be several solutions/workarounds to such common situations provided by OSGi: dynamic package imports, buddy policies and fragment bundles. I've chosen the third one because it doesn't require modifying the ActiveMQ bundle.

        So it's this easy: create a fragment bundle for the ActiveMQ bundle and add to the fragment's manifest as many import-package or require-bundle entries as you need for your 3rd-party classes to be visible to ActiveMQ.

        That worked so far for me.

        Cheers,

        David

        Comment

        Working...
        X