Java, Spring, JMS, JBoss – dev made hard ;)

0

Well I’m still dead busy at work – the project I am working on is probably our biggest ever, and while a lot of it is a package and 3rd party implementation team, there’s still plenty for us internal devs to get our teeth into.

I am working on the Interfaces between one of our internal Java apps, and the 3rd party package.  The method of choice (not our choice mind you) is Java JMS queues to do all the interfacing.  That brings benefits of loose coupling, but has the negatives of lack of single transaction between the two systems.

The good news is, it’s something new for me, using Spring to wire in the JMS objects required – the internal application is a Swing client talking to server side Spring managed business objects via Spring HTTP remoting.  The business objects talk to the Oracle DB via the Spring JDBC templates (some nice simple ORM goes on here, but ORM you can actually understand and debug, as it’s result sets, pojos, and reflection).

My application had to talk to the JMS queues sitting on a different JBoss server (JBoss messaging rather than JBoss MQ, which we’ve been warned against using).  It actually took me longer than I would have liked to get it working, for how little code there is.  Do you know how hard it is to get good (FULL) information on the net on how to actually set this stuff up?  Very little – snippets here and there, but never the whole picture.

So how do you connect to a remove JBoss app server running JMS queues using Jboss messaging?  Well I’ll tell you 🙂

1)  in my Spring servlet xml file, I added the following entries – it creates 3 queues, a JmsTemplate object (which hides all the boilerplate code), and a connection factory.  Now one thing that took me the time is that the client (my software) needs a lot of the JBoss jar files – so while JMS is a J2EE standard, with standard java interfaces – YOU NEED THE VERY SPECIFIC JAR FILES FOR YOUR VERSION OF JMS MESSENGING!  (note: the jars now appear to be compiled under 1.5 java, so if you have a 1.42 client, you’re STUFFED – JBoss don’t support java 1.4 now for JMS messaging – you are warned).  Oh and I use the Spring provided way to use an external property file to replace some of the implementation specific settings (like the jms queue locations and names)…

<bean id=”jndiTemplate”
class=”org.springframework.jndi.JndiTemplate”>
<property name=”environment”>
<props>
<prop key=”java.naming.factory.initial”>
org.jnp.interfaces.NamingContextFactory
</prop>
<prop key=”java.naming.provider.url”>
${jms.provider.url}
</prop>
<prop key=”java.naming.factory.url.pkgs”>
org.jnp.interfaces:org.jboss.naming
</prop>
</props>
</property>
</bean>

<!– Spring JMS Queue Connection Factory –>
<bean id=”jmsQueueConnectionFactory”
class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiTemplate”>
<ref bean=”jndiTemplate” />
</property>
<property name=”jndiName”>
<value>XAConnectionFactory</value>
</property>
</bean>
<bean id=”magIssueDestination”
class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiTemplate”>
<ref bean=”jndiTemplate” />
</property>
<property name=”jndiName”>
<value>${tapsMagIssueQueue}</value>
</property>
</bean>
<bean id=”publisherDestination”
class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiTemplate”>
<ref bean=”jndiTemplate” />
</property>
<property name=”jndiName”>
<value>${tapsPubQueue}</value>
</property>
</bean>
<bean id=”accountingPeriodDestination”
class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiTemplate”>
<ref bean=”jndiTemplate” />
</property>
<property name=”jndiName”>
<value>${tapsAccPeriodQueue}</value>
</property>
</bean>
<bean id=”jmsTemplate”
class=”org.springframework.jms.core.JmsTemplate”>
<property name=”connectionFactory”>
<ref bean=”jmsQueueConnectionFactory” />
</property>
<property name=”defaultDestination”>
<ref bean=”magIssueDestination” />
</property>
<property name=”receiveTimeout”>
<value>30000</value>
</property>
<property name=”deliveryMode” value=”2″/>
<property name=”sessionTransacted” value=”true” />

</bean>

<bean id=”jmsManager” class=”uk.co.flgroup.taps.jmsmanager.JmsManager”>
<constructor-arg ref=”jmsTemplate” />
<constructor-arg ref=”magIssueDestination” />
<constructor-arg ref=”publisherDestination” />
<constructor-arg ref=”accountingPeriodDestination” />
</bean>

The last bean is my own class to manage the queues, and it takes the JmsTemplate and 3 queues as constructor args.

Notice how very little of the beans are actually implementation specific – they are all the spring provided factory object – I think it class loads the correct JBoss objects (Jboss Queues, connection factories etc) at connection time (which is runtime in my case, as Spring wires up the object graph).  To do that runtime ‘switch’, it does require that the client have access to (in the class path) the JBoss Jar files.  And there are quite a few of em!

  • jboss-messaging-client.jar, jbossall-client.jar, jboss-aop.jar, javassist.jar ,trove.jar, log4j

(source; http://www.redhat.com/docs/manuals/jboss/jboss-eap-4.3/doc/messaging/JBoss_Messaging_User_Guide/html/inst.remoteclient.html)

I actually found out the hard way, working through the classNotFound exceptions, and findjar.com website to discover what jars they classes were in.  I copied those Jar files from the Jboss app server lib directory – that’s the target JBoss app server – as you need the SAME VERSION files/classes in the client as the server.

What this says to me is – programming ‘by interface’ doesn’t really work with JMS – you still need the very very specific and correct version jars/classes.  So if the remote JMS application upgrades, all clients need to upgrade 🙁

To send a message with the Spring wired in JmsTemplate object?  Well if you just want to fire and forget, all I required was the following line;

jmsTemplate.convertAndSend(this.getAccPeriodQueue(), xmlMessage.toXML());

Obviously I’m missing the getters and setters etc – my xmlMessage object is a simple pojo which I load up with data, and provide a toXML() method on (I’ve got an ‘XMLRenderable’ interface, and pass by that interface – the interface also contains a ‘getDestinationQueue()’ method, so the object tells my JmsManager controller which queue it should be sent to, and provides it’s payload).   The Spring convertAndSend() method automatically takes the String of XML and turns it into a JMS text message.  And that’s really it.

Author: Krispy

Webmaster of this and many websites over the years. I've been a Senior developer (Java JEE and Oracle DB, specialising in SEAM/JSF/Hibernate web development). Ex Lead Developer at New Scientist magazine, where I worked on creating a new WordPress based website, using almost 100% custom created widgets, plugins and theme. My own projects include websites created in WordPress and custom written with PHP and MySQL, and have my own dedicated linux server to run them from. Currently proud of; Mags Direct - a site I created for my work at the Frontline Group. An online magazine shop, which I created with almost zero budget within a week (since had a full theme upgrade). Found at https://magsdirect.co.uk/ Married, one cat. Beer fanatic (wife probably says bore) - real ales and craft beers. I have spent for too much on home brew gear, I create full mash craft beers. I spend a lot of time either going to gigs or organising them - I'm part of a small bunch of friends putting on DIY Punk shows called "The Scary Clown Presents..." our website can be found here; https://thescaryclownpresents.co.uk/ Also a fan of the local footy team - UP THE POSH!

Share This Post On

Submit a Comment

Your email address will not be published. Required fields are marked *