Spring provides an abstraction layer that eases this pain.
In the following example I'm using ActiveMQ (which needs to be started before running any of the code below) but Spring works with other major JMS implementations as well.
In order to send a JMS message we can use JMS template. Here's our sender that's using it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JmsSender { | |
private JmsTemplate jmsTemplate; | |
public void sendText(final String text) { | |
jmsTemplate.send(new MessageCreator() { | |
public Message createMessage(Session session) throws JMSException { | |
return session.createTextMessage(text); | |
} | |
}); | |
} | |
public void setJmsTemplate(JmsTemplate jmsTemplate) { | |
this.jmsTemplate = jmsTemplate; | |
} | |
} |
Spring beans needs to be configured in a context. Let's define Spring configuration in Java code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
public class JmsSenderSpringConfig { | |
@Bean | |
public JmsTemplate jmsTemplate() { | |
JmsTemplate jmsTemplate = new JmsTemplate(); | |
jmsTemplate.setDefaultDestination(new ActiveMQQueue("jms.queue")); | |
jmsTemplate.setConnectionFactory(connectionFactory()); | |
return jmsTemplate; | |
} | |
@Bean | |
public ActiveMQConnectionFactory connectionFactory() { | |
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(); | |
activeMQConnectionFactory.setBrokerURL("tcp://localhost:61616"); | |
return activeMQConnectionFactory; | |
} | |
@Bean | |
public JmsSender jmsSender() { | |
JmsSender jmsSender = new JmsSender(); | |
jmsSender.setJmsTemplate(jmsTemplate()); | |
return jmsSender; | |
} | |
} |
JMS template must have a connection factory with a broker url and a destination (in our case it's a queue).
The XML configuration equivalent would look like:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<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.xsd | |
http://www.springframework.org/schema/context | |
http://www.springframework.org/schema/context/spring-context.xsd"> | |
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> | |
<property name="brokerURL" value="tcp://localhost:61616"/> | |
</bean> | |
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> | |
<property name="connectionFactory" ref="connectionFactory"/> | |
<property name="defaultDestinationName" value="jms.queue"/> | |
</bean> | |
<bean id="jmsSender" class="pl.mjedynak.jms.sender.JmsSender"> | |
<property name="jmsTemplate" ref="jmsTemplate"/> | |
</bean> | |
</beans> |
Java configuration provides not only compile-time checking but in my opinion it is more straightforward and easier to control.
Unfortunately we can't escape XML completely, we need to turn on component scanning so that Spring will read configuration from classes in our package:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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" | |
xsi:schemaLocation="http://www.springframework.org/schema/beans | |
http://www.springframework.org/schema/beans/spring-beans.xsd | |
http://www.springframework.org/schema/context | |
http://www.springframework.org/schema/context/spring-context.xsd"> | |
<context:component-scan base-package="pl.mjedynak"/> | |
</beans> |
The example code that would run the sender:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JmsSenderRunner { | |
public static void main(String[] args) { | |
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("sender-context.xml"); | |
JmsSender jmsSender = (JmsSender) applicationContext.getBean("jmsSender"); | |
jmsSender.sendText("hellooooo " + new Date()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JmsReceiver implements MessageListener { | |
@Override | |
public void onMessage(Message message) { | |
System.out.println("Received: " + message); | |
} | |
} |
The Spring config looks as follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
public class JmsReceiverSpringConfig { | |
@Bean | |
public JmsReceiver jmsReceiver() { | |
return new JmsReceiver(); | |
} | |
@Bean | |
public ActiveMQConnectionFactory connectionFactory() { | |
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(); | |
activeMQConnectionFactory.setBrokerURL("tcp://localhost:61616"); | |
return activeMQConnectionFactory; | |
} | |
@Bean | |
public DefaultMessageListenerContainer messageListenerContainer() { | |
DefaultMessageListenerContainer messageListenerContainer = new DefaultMessageListenerContainer(); | |
messageListenerContainer.setConnectionFactory(connectionFactory()); | |
messageListenerContainer.setDestinationName("jms.queue"); | |
messageListenerContainer.setMessageListener(jmsReceiver()); | |
return messageListenerContainer; | |
} | |
} |
Our receiver is set in the message listener container with the connection factory and the destination.
Receiver is missing the same XML configuration as sender, and the running code is analogical.
Here's the list of maven dependencies:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-context</artifactId> | |
<version>3.1.1.RELEASE</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-jms</artifactId> | |
<version>3.1.1.RELEASE</version> | |
</dependency> | |
<dependency> | |
<groupId>cglib</groupId> | |
<artifactId>cglib</artifactId> | |
<version>2.2</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.activemq</groupId> | |
<artifactId>activemq-core</artifactId> | |
<version>5.5.1</version> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.xbean</groupId> | |
<artifactId>xbean-spring</artifactId> | |
<version>3.5</version> | |
</dependency> |