Wednesday, July 1, 2009

Adding Embedded ActiveMQ to Spring Container (on Maven 2 Project)

Today, we need to add a queue to our application to better manage long running transaction on our web application. The choice fell into using embedded ActiveMQ.We plan to use the latest version available (which currently ActiveMQ 5.2.0). Previous version of our application use our proprietary code which I believe was an example of reinventing the wheel. For our latest version of application, we try to use as much as possible open standard and open source technologies. ActiveMQ is under the Apache Software Foundation umbrella which is suitable for us.

First I add the dependency for the latest version of ActiveMQ (version 5.2.0):

[sourcecode lang="xml"]
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.2.0</version>
<optional>false</optional>
</dependency>
[/sourcecode]

Now it's time to add something into the Spring application context configuration file.
As suggested by the documentation, I added new namespace amq in my XML. It points to "http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd" schema location.

[sourcecode lang="xml"]
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
[/sourcecode]

I tried to run a JUnit test just to make sure that the new change in the configuration works well. There were some 2 errors. It turns to be a stale schema location. I figured it out from opening the URL http://activemq.apache.org/schema/core and see what's in there. So now need to modify a bit, change "http://activemq.apache.org/schema/core/activemq-core.xsd" to "http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd".

So here goes the correct version that works (syntactically correct XML):

[sourcecode lang="xml"]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd">
[/sourcecode]

Now the next beast coming in, when I tried to use the new namespace by adding this inside the <beans/> tag.

[sourcecode lang="xml"]
<amq:broker useJmx="false" persistent="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:0" />
</amq:transportConnectors>
</amq:broker>
[/sourcecode]

It produced this error:

[sourcecode lang="shell"]

java.lang.ExceptionInInitializerError
at com.triquesta.tcm.core.services.MessagingServiceTest.init(MessagingServiceTest.java:17)
[...deleted...]
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [tcm_configs.xml]; nested exception is org.springframework.beans.FatalBeanException: NamespaceHandler class [org.apache.xbean.spring.context.v2.XBeanNamespaceHandler] for namespace [http://activemq.apache.org/schema/core] not found; nested exception is java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:420)
[...deleted...]
Caused by: org.springframework.beans.FatalBeanException: NamespaceHandler class [org.apache.xbean.spring.context.v2.XBeanNamespaceHandler] for namespace [http://activemq.apache.org/schema/core] not found; nested exception is java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:134)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1292)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1287)
[...deleted...]
Caused by: java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)
at org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver.resolve(DefaultNamespaceHandlerResolver.java:123)
... 37 more
[/sourcecode]

2 comments:

  1. Please add xbean-spring-3.4.jar
    which is in the optional jar folder

    ReplyDelete
  2. Add xbean-spring-3.6.jar to your app. That should help.

    ReplyDelete