您好!
我正在开发一个大型ActiveMQ消息中心。许多应用程序通过我们的集线器向各种ActiveMQ集群发送消息,我们的工作是路由这些消息(就像邮政服务一样)。我们希望利用Camel将消息从一个ActiveMQ集群路由到另一个集群。我们希望Camel做的部分工作是压缩集群之间的消息。
但是,大多数消息都是作为ObjectMessages传递的,我们无法访问jar文件(更确切地说:对象文件中没有任何内容,也没有数据,我们只想压缩数据并将其移动到另一个代理)。就像邮政服务一样,我们也不感兴趣也不允许阅读这些信息,只需传递它们即可。
当我尝试从一个ActiveMQ代理读取,压缩消息并将其发送到另一个代理时,我将得到一个ClassCastException,我的序列化类在类路径中不存在。
我不希望Camel / ActiveMQ将对象序列化回Java对象,而是希望它只是将消息作为字节读取并压缩它们。 Camel是否有可能从ActiveMQ / JMS读取并认为它只是一个字节/流/ gobligook?
我得到的最接近的是指定jmsMessageType = Bytes,如下所示,但它不起作用。我试图在http://camel.apache.org/jms找到答案,但我找不到解决方案。
我试图将一个TextMessage排队,但它完美无缺。但是,这必须适用于每种JMS消息类型,包括ObjectMessages。
我使用的是Redhat A-MQ 6.3,Camel 2.17.0,位于Karaf 2.4.0,ActiveMQ 5.11.0。
如果你可以通过提供XML DSL示例版本/代码片段而不是Java DSL(我对Camel很新,并且还没有习惯)来帮助我,那么你将获得“额外积分”(或者至少我会非常高兴)在这些之间进行翻译),但任何帮助都是张开双臂接受的!
非常感谢您提供的任何想法或解决方案!
我的骆驼文件是
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jmsone" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost" />
<property name="userName" value="admin" />
<property name="password" value="admin" />
</bean>
</property>
</bean>
<bean id="jmstwo" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://numbertwo:61616" />
<property name="userName" value="admin" />
<property name="password" value="admin" />
</bean>
</property>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<dataFormats>
<gzip id="compressor"/>
</dataFormats>
<route id="queueToOtherBroker">
<from uri="jmsone:andersPanders?jmsMessageType=Bytes" />
<marshal ref="compressor" />
<to uri="jmstwo:olleBandola" />
</route>
</camelContext>
</beans>
地址numberone和numbertwo是Docker容器,连接不是问题,他们可以互相交谈。
这是完整的例外
2017-01-27 14:54:43,003 | WARN | r[andersPanders] | EndpointMessageListener | rg.apache.camel.util.CamelLogger 213 | 192 - org.apache.camel.camel-core - 2.17.0.redhat-630187 | Execution of JMS message listener failed. 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: Anders not found by org.apache.activemq.activemq-osgi [162]. Message: ActiveMQObjectMessage {commandId = 5, responseRequired = true, messageId = ID:VeryGoodTea-42317-1485528882333-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:VeryGoodTea-42317-1485528882333-1:1:1:1, destination = queue://andersPanders, transactionId = null, expiration = 0, timestamp = 1485528882925, arrival = 0, brokerInTime = 1485528882928, brokerOutTime = 1485528882944, 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@57958b, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 1109, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = 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: Anders not found by org.apache.activemq.activemq-osgi [162]. Message: ActiveMQObjectMessage {commandId = 5, responseRequired = true, messageId = ID:VeryGoodTea-42317-1485528882333-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:VeryGoodTea-42317-1485528882333-1:1:1:1, destination = queue://andersPanders, transactionId = null, expiration = 0, timestamp = 1485528882925, arrival = 0, brokerInTime = 1485528882928, brokerOutTime = 1485528882944, 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@57958b, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 1109, properties = null, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false}
at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:160)[206:org.apache.camel.camel-jms:2.17.0.redhat-630187]
at org.apache.camel.component.jms.JmsMessage.createBody(JmsMessage.java:236)[206:org.apache.camel.camel-jms:2.17.0.redhat-630187]
at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:47)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.impl.DefaultUnitOfWork.<init>(DefaultUnitOfWork.java:90)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.impl.DefaultUnitOfWork.<init>(DefaultUnitOfWork.java:72)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.impl.DefaultUnitOfWorkFactory.createUnitOfWork(DefaultUnitOfWorkFactory.java:34)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.createUnitOfWork(CamelInternalProcessor.java:683)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.before(CamelInternalProcessor.java:651)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.before(CamelInternalProcessor.java:628)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:144)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:109)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:91)[192:org.apache.camel.camel-core:2.17.0.redhat-630187]
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:112)[206:org.apache.camel.camel-jms:2.17.0.redhat-630187]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:555)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:515)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:485)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1103)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1095)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:992)[205:org.apache.servicemix.bundles.spring-jms:3.2.16.RELEASE_2]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_121]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_121]
Caused by: javax.jms.JMSException: Failed to build body from content. Serializable class not available to broker. Reason: java.lang.ClassNotFoundException: Anders not found by org.apache.activemq.activemq-osgi [162]
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36)[162:org.apache.activemq.activemq-osgi:5.11.0.redhat-630187]
at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:208)[162:org.apache.activemq.activemq-osgi:5.11.0.redhat-630187]
at org.apache.camel.component.jms.JmsBinding.extractBodyFromJms(JmsBinding.java:135)[206:org.apache.camel.camel-jms:2.17.0.redhat-630187]
... 23 more
Caused by: java.lang.ClassNotFoundException: Anders not found by org.apache.activemq.activemq-osgi [162]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1556)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:77)[org.apache.felix.framework-4.4.1.jar:]
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1993)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)[:1.8.0_121]
at java.lang.Class.forName0(Native Method)[:1.8.0_121]
at java.lang.Class.forName(Class.java:348)[:1.8.0_121]
at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.load(ClassLoadingAwareObjectInputStream.java:140)[162:org.apache.activemq.activemq-osgi:5.11.0.redhat-630187]
at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:55)[162:org.apache.activemq.activemq-osgi:5.11.0.redhat-630187]
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1819)[:1.8.0_121]
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)[:1.8.0_121]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1986)[:1.8.0_121]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1535)[:1.8.0_121]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)[:1.8.0_121]
at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:206)[162:org.apache.activemq.activemq-osgi:5.11.0.redhat-630187]
... 24 more
Anders只是我用来测试压缩的一个类。
我在groovy的测试程序:
import org.apache.activemq.ActiveMQConnectionFactory
import javax.jms.*
class Anders implements Serializable {
String name = "Anders Andersson"
int age=120
}
def brokerUrl = 'tcp://localhost:61616'
def queue = 'andersPanders'
def reader = new BufferedReader(new InputStreamReader(System.in))
new ActiveMQConnectionFactory(brokerURL: brokerUrl, userName: "admin", password: "admin").createConnection().with {
start()
createSession(false, Session.AUTO_ACKNOWLEDGE).with {
def message = createObjectMessage(new Anders())
createProducer().send(createQueue(queue), message)
}
close()
}
答案 0 :(得分:1)
免责声明:ObjectMessage是JMS中的反模式,因为它引入了紧耦合,并且存在安全问题。
也就是说,这个解决方案只适用于ActiveMQ,而不适用于通用的JMS:
<route id="routeme">
<from uri="activemq:inputqueue?mapJmsMessage=false" />
<setBody>
<simple>${body.getContent().getData()}</simple>
</setBody>
<marshal ref="compressor"/>
<to uri="activemq:outputqueue" />
</route>
mapJmsMessage=false
使Camel避免读取实际的对象并将正文保持为ActiveMQObjectMessage
。使用该对象,您实际上可以获得支持ObjectMessage的byte[]
。上述路线的输出为BytesMessage
。