Something works!

After days of untested theories, head-scratching, dead ends, and rabbit trails, I’m happy to report that something now works.

The Beginning of Unstuckitude

First thing was, Keith got back, took a look at the class cast errors in the stack trace and said something along the lines of, “That looks like a dependency issue.”

And that is what it was: my .war project was including javax.jms.ConnectionFactory more than once. (There is also a Spring forum question and answer for this problem.)

Step 1: activemq-all to activemq-core

We browsed through the .jar files in the activemq-all .jar file (manually, by opening each enclosing .jar in WinZip — anyone have a better way of doing this?) and indeed it did have javax.jms.* classes in it.  Keith knew that having the same classes multiple times in your .war can cause problems as the app server may load the wrong ones, so in my project’s pom.xml we replaced the dependency on activemq-all with a dependency on activemq-core instead:


<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-core</artifactId>
    <version>5.0.0</version>
</dependency>

When we tried to do a Maven Install of this, though, we got:


Missing:
----------
1) org.apache.activemq:activeio-core:jar:3.1-SNAPSHOT
...
2) org.apache.activemq:activeio-core:test-jar:tests:3.1-SNAPSHOT
...
----------
2 required artifacts are missing.

Step 2: Exclude activeio-core dependency

We don’t need the activeio-core tests anyway, so we put in an exclusion for this:


<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-core</artifactId>
    <version>5.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activeio-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

This time Maven Install ran cleanly.

Step 3: Scope = Provided

When we deployed, though, we got errors like this:

10:12:59,417 WARN  [JBossManagedConnectionPool] Throwable while attempting to get a new connection: null
javax.resource.ResourceException: Could not create connection.
...
Caused by: javax.jms.JMSException: Could not create Transport. Reason: java.io.IOException: Transport scheme NOT recognized: [tcp]
...
08:35:36,453 INFO  [DefaultMessageListenerContainer] Could not refresh JMS Connection - retrying in 5000 ms
javax.jms.JMSException: Could not create Transport. Reason: java.io.IOException: Transport scheme NOT recognized: [tcp]
...

The DefaultMessageListenerContainer, finding itself unable to make a JMS connection, kept trying every five seconds —  boom, bang, bang, boom, zowie!  (I’m still getting acclimated to the spectacular errors you can get when deploying to an app server. :)

At first I didn’t notice one of the Caused Bys farther down, which said:

Caused by: java.lang.ClassCastException: org.apache.activemq.transport.tcp.TcpTransportFactory

But sure enough, it turns out that this error was caused by double-deployed classes.  This time, it was the activemq-core jar that is already contained inside the activemq-ra.rar file. Our project already depends on that .rar file being there, and we don’t want two copies of the jar, so we updated our pom file’s activemq-core dependency definition by setting scope to provided (line 5), as follows:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-core</artifactId>
    <version>5.0.0</version>
    <scope>provided</scope>
    <exclusions>
        <exclusion>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activeio-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Success

This time, our .war file deploys without stack traces (woohoo!),  and when I point my browser to the ActiveMQ Console I see that my “gloriousTest.Queue” queue shows up.  I use the ActiveMQ Console to send a message to the queue and… my MessageListener gets the message and prints its debug output to the JBoss console!

The Files That Worked

applicationContext.xml, the Spring bean file

<?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:context="http://www.springframework.org/schema/context" xmlns:amq="http://activemq.org/config/1.0"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://activemq.org/config/1.0 http://activemq.apache.org/schema/core/activemq-core-5.0.0.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

    <jee:jndi-lookup id="queueConnectionFactory" jndi-name="java:activemq/QueueConnectionFactory" />

    <amq:queue id="queue" physicalName="gloriousTest.Queue" />

    <bean id="messageListener" class="com.something.dmn.MessageListener" />

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="queueConnectionFactory" />
<property name="destination" ref="queue" />
<property name="messageListener" ref="messageListener" />
<property name="transactionManager" ref="transactionManager" />
    </bean>
</beans>

pom.xml (relevant portions)

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${springFramework.version}</version>
        </dependency>
        ...
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jms_1.1_spec</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-core</artifactId>
        <version>5.0.0</version>
        <scope>provided</scope>
        <exclusions>
            <exclusion>
                <groupId>org.apache.activemq</groupId>
                <artifactId>activeio-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
    </dependency>
    ...
</dependencies>
<properties>
    ...
    <springFramework.version>2.5.4</springFramework.version>
</properties>

activemq-jms-ds.xml

This file I was able to use without modification from the example on the ActiveMQ site.  I noticed, though, that the <ServerUrl> elements under connection-factories -> tx-connection-factory seem to be ignored.  (Maybe that is because in our case the ServerUrl is already being pre-specified in the activemq-ra.rar’s ra.xml file.)

ra.xml (in activemq-ra.rar)

I think the only change I had to make to this resource adapter archive was to the connector -> resourceadapter -> config-property-value element for the ServerUrl config-property-name, to change it from vm://localhost to tcp://localhost:61616.  (Or maybe it was already tcp… I don’t remember now.)

Next

Now that we have the JCA/JMS/JNDI/JBoss/Spring/ActiveMQ stuff playing nicely together, we can try to actually do some XA stuff!

Advertisements

, , , , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s