Sunday, October 3, 2010

JBoss Application Server 5.1/ESB 4.5 GA and ActiveMQ 5.4 integration

On one of my last projects I had to integrate JBoss ESB 4.5 GA with ActiveMQ 5.4.0 and Spring 3. NOTE: the fixes below also work for integration with JBoss 5.1 Application Server.



My starting point was of course this post: Integrating Apache ActiveMQ with JBoss. (Or is this the original?)
Part of the requirements mentioned in that article (Apache ActiveMQ 4.0.1+ and JBoss 4.0.4+) got me worried that the steps described might not work for my version of JBoss and ActiveMQ. Even though there's a '+' after the version numbers :)

First I had quite a hard time finding the .rar file! Finally found it in \lib\optional in the ActiveMQ zip: activemq-rar-5.4.0.rar

After that I followed the steps including up to 'Configuring JBoss'. In there you also have to start JBoss again.
I didn't see any exceptions fly around so thought all was fine, so I started the consumer ('ant consumer').
But there I got:



[java] javax.jms.JMSException: Could not connect to broker URL:
tcp://localhost:61616. Reason: java.net.ConnectException:
Connection re[Thread-2] Caught: javax.jms.JMSException: Could not
connect to broker URL: tcp://localhost:61616. Reason:
java.net Connection Exception : connection refused


Strrrange, because I thought the server started fine. After quite some searching, I figured out the error message probably indicates that there's just nothing listening at localhost:61616.
After carefully checking the startup log (searching for 'activemq') I found out it hadn't started!



17:17:31,566 INFO [XBeanXmlBeanDefinitionReader] Loading XML bean
definitions from class path resource [broker-config.xml]
17:17:31,768 WARN [ActiveMQResourceAdapter] Could not start up embeded
ActiveMQ Broker 'xbean:broker-config.xml': Line 29 in XML document from
class path resource [broker-config.xml] is invalid; nested exception is
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration
of element 'beans'.


That's weird, some namespace problem?
Searching on the biggg internet I found this page (via), explaining that the namespaces are different from 5.1 onwards.

Since I'm using AMQ 5.4.0 I tried in broker-config.xml:



<beans xmlns="http://activemq.apache.org/schema/core">


But that still gave:



17:23:38,638 WARN [ActiveMQResourceAdapter] Could not start up embeded
ActiveMQ Broker 'xbean:broker-config.xml': Line 29 in XML document from
class path resource [broker-config.xml] is invalid; nested exception is
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration
of element 'beans'.


So now I just tried all the namespace definitions:



<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
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.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd
">
</beans>


Darn, still not ok:



17:27:42,265 WARN [ActiveMQResourceAdapter] Could not start up embeded
ActiveMQ Broker 'xbean:broker-config.xml': Line 49 in XML document from
class path resource [broker-config.xml] is invalid; nested exception is
org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard
is strict, but no declaration can be found for element 'persistenceAdapter'.


But that was easy, missing the namespace prefix. So I modified:



<amq:persistenceAdapter>
<amq:journaledJDBC journalLogFiles="5" dataDirectory="activemq-data"/>
<!-- To use a different datasource, use th following syntax : -->
<!--
<journaledJDBC journalLogFiles="5" dataDirectory="../data" dataSource="#postgres-ds"/>
-->
</amq:persistenceAdapter>


But again an error:



17:29:50,840 WARN [ActiveMQResourceAdapter] Could not start up embeded
ActiveMQ Broker 'xbean:broker-config.xml': Line 50 in XML document from
class path resource [broker-config.xml] is invalid; nested exception is
org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was
found starting with element 'amq:journaledJDBC'. One of
'{"http://activemq.apache.org/schema/core":amqPersistenceAdapter,
"http://activemq.apache.org/schema/core":jdbcPersistenceAdapter,
"http://activemq.apache.org/schema/core":journalPersistenceAdapter,
"http://activemq.apache.org/schema/core":kahaDB,
"http://activemq.apache.org/schema/core":kahaPersistenceAdapter,
"http://activemq.apache.org/schema/core":memoryPersistenceAdapter,
WC[##other:"http://activemq.apache.org/schema/core"]}' is expected.


So journaledJDBC is unknown. There must be something with a wrong namespace version or something. From the XSDs from here it seemed there was an element in the wrong place. So I just removed the whole persistenceAdapter element.

I also noted that there is a persistenceFactory element in the AMQ 450 broker-config.xml, which is not present in the Integrating Apache ActiveMQ with JBoss post.
So I also changed that one's dataDirectory to be the same as in the (just removed) persistenceAdapter:



<amq:persistenceFactory>
<amq:journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${jboss.server.data.dir}/activemq"/>
</amq:persistenceFactory>


Yes that did it! See the log part below:



17:45:01,215 INFO [XBeanXmlBeanDefinitionReader] Loading XML bean definitions
from classpath resource [broker-config.xml]
17:45:01,542 INFO [DefaultListableBeanFactory] Pre-instantiating singletons
in org.springframework.beans.factory.support.DefaultListableBeanFactory@157402b:
defining beans [org.apache.activemq.xbean.XBeanBrokerService#0]; root of
factory hierarchy
17:45:01,697 INFO [PListStore] PListStore:activemq-data\bruce.broker1\tmp_storage
started

... stuff deleted ...

17:45:02,896 INFO [BrokerService] ActiveMQ 5.4.0 JMS Message Broker
(bruce.broker1) is starting
17:45:02,911 INFO [BrokerService] For help or more information please
see: http://activemq.apache.org/
17:45:03,083 INFO [SchedulerBroker] Scheduler using directory:
activemq-data\scheduler
17:45:03,145 INFO [JournalPersistenceAdapter] Journal Recovery Started from:
Active Journal: using 5 x 20.0 Megs at: C:\jbossesb-server-4.5.GA\bin\${jboss.server.data.dir}\activemq\journal
17:45:03,176 INFO [JournalPersistenceAdapter] Journal Recovered: 0 message(s)
in transactions recovered.
17:45:03,207 INFO [TransportServerThreadSupport] Listening for connections at:
tcp://localhost:61616
17:45:03,223 INFO [TransportConnector] Connector bruce.broker1 Started
17:45:03,223 INFO [BrokerService] ActiveMQ JMS Message Broker (bruce.broker1,
ID:PC555-4930-1389432149-0:0) started


Also after that the consumer and producer worked fine.

And as a final optimization to not having to change the namespace for each new ActiveMQ version, I removed the version from the activemq-core xsd:



<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
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-2.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd
">


To summarize, this is the final broker-config.xml (some comments deleted for space):



<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: xbean -->
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
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-2.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd
">

<!-- shutdown hook is disabled as RAR classloader may be gone at shutdown -->
<amq:broker useJmx="true" useShutdownHook="false" brokerName="bruce.broker1">

<amq:managementContext>
<!-- use appserver provided context instead of creating one,
for jboss use: -Djboss.platform.mbeanserver -->
<amq:managementContext createConnector="false"/>
</amq:managementContext>

<amq:persistenceFactory>
<amq:journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${jboss.server.data.dir}/activemq"/>
</amq:persistenceFactory>

<amq:transportConnectors>
<amq:transportConnector name="bruce.broker1" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
</amq:transportConnectors>

</amq:broker>
</beans>


JBoss 5.1 AS specific stuff:

I just copied over the above created .rar dir to the jboss-5.1.0.GA/server/default/deploy/activemq-ra.rar/META-INF directory and started it.

Got one error trying:



18:00:48,611 ERROR [AbstractKernelController] Error installing to Parse:
name=vfsfile:/C:/jboss-5.1.0.GA/server/default/deploy/activemq-ra.rar/
state=Not Installed mode=Manual requiredState=Parse
org.jboss.deployers.spi.DeploymentException: Error creating managed object
for vfsfile:/C:/jboss-5.1.0.GA/server/default/deploy/activemq-ra.rar/
at org.jboss.deployers.spi.DeploymentException.rethrowAsDeploymentException(
DeploymentException.java:49)
...
Caused by: org.jboss.xb.binding.JBossXBException: Failed to parse source:
cvc-complex-type.2.4.d: Invalid content was found starting with element
'config-property-value'. No child element is expected at this point. @
vfsfile:/C:/jboss-5.1.0.GA/server/default/deploy/
activemq-ra.rar/META-INF/ra.xml[100,36]


Ah for some reason I had an empty in ra.xml. Removing that made the 5.1 server start fine and the producer produce and the consumer consume!

PS: the example consumer & producer now send out 2000 messages instead of the 10 you see in the Integrating Apache ActiveMQ with JBoss post.

Hope this might help somebody some time :)

3 comments:

Ramakrishna said...

Awesome Post.... really really helped me a lot in configuring the Apache MQ with JBoss. Thank you so much....

Dan Kibler said...

Thanks Techie for the very informative post- really interesting. Not sure if anyone will respond to this as the post is over a year old, however I'd like to know if your use of persistenceFactory is a recommended production configuration. We use amq 4 embedded in jboss 4.2.3 currently but are planning impact for jboss upgrade to 5 or possibly 6.

Techie said...

@pearl_blue: can't tell if it is a recommended production configuration. The only people who should able to tell you this are the JBoss people...