Attempting to deserialize user-created objects doesn't work when ActiveMQ is
deployed in an OSGi container (e.g. ServiceMix 4)
------------------------------------------------------------------------------------------------------------------------------
Key: AMQ-2392
URL: https://issues.apache.org/activemq/browse/AMQ-2392
Project: ActiveMQ
Issue Type: Bug
Components: Broker
Affects Versions: 5.3.0
Environment: Apache ServiceMix 4 (FUSE ESB 4.1.0.2)
Apache ActiveMQ 5.3.0.3 (embedded in FUSE ESB)
Apache Camel 1.6.1 (embedded in FUSE ESB)
Reporter: Scott Parkerson
I am attempting to use the POJO sending and producing patterns as described.
Here is my setup:
In one class (a CXF-based RESTful webservice), I have the following set
up:
{noformat}
// OutboundFooRequestHandler is an interface (see below)
@Produce(uri="activemq:queue:outbound_foo_req")
private OutboundFooRequestHandler outboundFooRequestHandler;
@POST
@Path("/sendfoo")
public Response sendFoo(OutboundFooRequest sendFooRequest)
{
// (a bunch of web-specific code deleted)
// send this sendFooReqest object on the queue
outboundFooRequestHandler.handle(sendFooRequest);
// Return HTTP response 202 Accepted
return Response.status(202).build();
}
{noformat}
The interface that is annotated with {...@produce}} is shown below:
{noformat}
@InOnly
public interface OutboundFooRequestHandler
{
public void handle(OutboundFooRequest outboundFooRequest);
}
{noformat}
Here is the implementation of the interface:
{noformat}
public class OutboundFooRequestHandlerImpl implements
OutboundFooRequestHandler, InitializingBean, DisposableBean
{
private static final Logger logger =
LoggerFactory.getLogger(OutboundFooRequestHandlerImpl.class);
@Override
@Consume(uri="activemq:queue:outbound_foo_req")
public void handle(@Body OutboundFooRequest outboundFooRequest)
{
logger.debug("got it");
// TODO: actually *do* something
}
{noformat}
The producer's {{bundle-context.xml}} looks like this:
{noformat}
<camelContext
xmlns="http://activemq.apache.org/camel/schema/spring" />
<bean name="activemq"
class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://default" />
</bean>
</property>
</bean>
{noformat}
And the consumer's {{bundle-context.xml}} looks the same, except I'm
instantiating my Impl classes.
When I attempt to send a message through the system, the producer produces a
{{BeanInvocation}} object wrapping the {{SendFooRequest}} object. However, the
consumer thread barfs with this stacktrace:
{noformat}
4:20:24,843 | WARN | nerContainer-195 | DefaultMessageListenerContainer |
AbstractMessageListenerContainer 646 |
Execution of JMS message listener failed
org.apache.camel.RuntimeCamelException:
org.apache.camel.component.jms.RuntimeJmsException:
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.camel.component.bean.BeanInvocation.
Message: ActiveMQObjectMessage {commandId = 5, responseRequired = true,
messageId = ID:xyzzy.ateb.com-55483-1252952224263-2:5:1:1:1,
originalDestination = null, originalTransactionId = null, producerId =
ID:xyzzy.ateb.com-55483-1252952224263-2:5:1:1,
destination = queue://outbound_sms_req, transactionId = null, expiration = 0,
timestamp = 1252952424801, arrival = 0,
brokerInTime = 1252952424802, brokerOutTime = 1252952424822, 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.byteseque...@141bf9f, marshalledProperties =
null, dataStructure = null,
redeliveryCounter = 0, size = 1718, properties = null, readOnlyProperties =
true, readOnlyBody = true, droppable = false}
at
org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:850)
at
org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:95)
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.run(DefaultMessageListenerContainer.java:881)
at java.lang.Thread.run(Thread.java:636)
Caused by: org.apache.camel.component.jms.RuntimeJmsException: 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.camel.component.bean.BeanInvocation. Message: ActiveMQObjectMessage
{commandId = 5,
responseRequired = true, messageId =
ID:xyzzy.ateb.com-55483-1252952224263-2:5:1:1:1, originalDestination = null,
originalTransactionId = null, producerId =
ID:xyzzy.ateb.com-55483-1252952224263-2:5:1:1, destination =
queue://outbound_sms_req,
transactionId = null, expiration = 0, timestamp = 1252952424801, arrival = 0,
brokerInTime = 1252952424802, brokerOutTime = 1252952424822,
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.byteseque...@141bf9f, marshalledProperties = null,
dataStructure = null, redeliveryCounter = 0, size = 1718, properties = null,
readOnlyProperties = true, readOnlyBody = true, droppable = false}
at
org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:105)
at
org.apache.camel.component.jms.JmsMessage.createBody(JmsMessage.java:168)
at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:45)
at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:52)
at
org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:90)
at
org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:72)
... 8 more
Caused by: javax.jms.JMSException: Failed to build body from content.
Serializable class not available to broker. Reason:
java.lang.ClassNotFoundException: org.apache.camel.component.bean.BeanInvocation
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:91)
... 13 more
Caused by: java.lang.ClassNotFoundException:
org.apache.camel.component.bean.BeanInvocation
at
org.apache.felix.framework.searchpolicy.ModuleImpl.findClassOrResourceByDelegation(ModuleImpl.java:558)
at
org.apache.felix.framework.searchpolicy.ModuleImpl.access$100(ModuleImpl.java:59)
at
org.apache.felix.framework.searchpolicy.ModuleImpl$ModuleClassLoader.loadClass(ModuleImpl.java:1427)
at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
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:1592)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
at
org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:177)
... 14 more
{noformat}
A couple of relevant conversations on IRC. First, from {{#camel}}:
{quote}
<smerp> I don't suppose anyone would know what I need to do to the ActiveMQ
broker to pass BeanInvocation messages?
<-- mr_smith has quit (Ping timeout)
<smerp> Using @Consume, I'm getting 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.camel.component.bean.BeanInvocation
<cibsen> BeanInvocation is a internal camel class that is like meta data about
some bean to invoke
are you sure you want to route that?
chirino ccustine cibsen
<smerp> cibsen: Well, I was just following the examples for @Produce and
@Consume in the online docs
<smerp> cibsen: more background was posted on the camel-users mailing list.
Here's a URL to the current thread:
http://www.nabble.com/Using-%40Produce---%40Consume----What-am-I-missing--tt25437492.html
<cibsen> well you use OSGi then you got all the pain it brings along :(
smerp plays sadtrombone.wav
<smerp> :|
<cibsen> eg activemq.jar wants to deserialize the object it received over JMS
but OSGi forbids it to see the org.apache.camel classes
as its not importing them
{quote}
...and then a later one on {{#servicemix}}:
{quote}
<smerp> Can any SMX folks tell me what to do to get ActiveMQ embedded in SMX to
"see" the camel classes (BeanInvocation, specifically)
OSGi, as awesome as it is, is a pain sometimes.
Context is here ->
http://www.nabble.com/Using-%40Produce---%40Consume----What-am-I-missing--tt25437492.html
(see the last post)
<ccustine> smerp: I fear this would require a DynamicImport-Package in the
ActiveMQ bundle
<smerp> ccustine: :(
ccustine: is this a bug? or a feature? or perhaps a fug?
<ccustine> smerp: the correct option is probably to modify AMQ
ClassLoadingAwareObjectInputStream to be more OSGi aware
<smerp> crap.
<ccustine> smerp: probably fug :-/
<smerp> ccustine: any decent workarounds for now?
ccustine: I'll file a JIRA for it
Probably needs to be on ActiveMQ, right?
<ccustine> DynamicImport on AMQ is the fastest, but may have unanticipated
problems
well... good question
probably, but officially there isn't much OSGi specific in AMQ
this is getting kinda specific, but you can start there
I think this is something we need to figure out
so basically it sounds like any objectmessage that is serialized from a user
type will have this occur
<smerp> right... this is a tricky problem, as the problem is (a) caused by
something that is recommended in Camel (BeanInvocations on queues) and (b) is
broken only when using ActiveMQ in SMX 4 w/OSGi
<ccustine> right
<smerp> I think so -- it happens the object type is from Camel, but yes
<ccustine> seems like a general use case that is broken in OSGi, so I would
open the bug under AMQ and then we will work with them to figure out a solution
chirino ccustine
<smerp> ccustine: Alright, sounds good
smerp goes to JIRA
<ccustine> smerp: I may have a nasty workaround by modifying the activemq.xml
that we deploy in SMX....
<smerp> ccustine: that would be great for the short term -- it would get me
moving again
(if it works)
<ccustine> open the bug and I will look at this hack for a bit
yeah
{quote}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.