JBoss AS 7 – Remote JMS queue
12/11/2012 Leave a comment
Today I’d like to post a quick, laconic, and hopefully 100% correct sample of remote JMS queue utilization in JBoss 7 AS. Diagram posted below shows the target environment where one application server instance hosts JMS queue, and the other one acts as message producer and consumer.
JBoss2 (queue owner) configuration:
<hornetq-server> <security-domain>hornetq-security-domain</security-domain> ... <jms-destinations> <jms-queue name="RemoteQueue1"> <entry name="queue/RemoteQueue1"/> <entry name="java:jboss/exported/jms/queue/RemoteQueue1"/> </jms-queue> </jms-destinations> </hornetq-server> ... <security-domains> ... <security-domain name="hornetq-security-domain" cache-type="default"> <authentication> <login-module code="UsersRoles" flag="required"> <module-option name="usersProperties" value="/opt/jboss3/standalone/configuration/jms-users.properties"/> <module-option name="rolesProperties" value="/opt/jboss3/standalone/configuration/jms-roles.properties"/> </login-module> </authentication> </security-domain> </security-domains>
[jboss@jmsenv Desktop]$ cat /opt/jboss3/standalone/configuration/jms-users.properties jmsuser=jmspassword [jboss@jmsenv Desktop]$ cat /opt/jboss3/standalone/configuration/jms-roles.properties jmsuser=guest
The security related entries are not required if you decide to assign unauthorized users to “guest” group (which is by default allowed to send and receive messages). This can be achieved by adding <module-option name="unauthenticatedIdentity" value="guest"/>
to login module configuration.
JBoss1 (queue user) configuration:
<hornetq-server> ... <connectors> <connector name="remote-jms-nonmgmt"> <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class> <param key="host" value="192.168.117.159"/> <param key="port" value="5445"/> </connector> <netty-connector name="remote-jms-mgmt" socket-binding="remote-jms-binding"/> </connectors> <jms-connection-factories> ... <connection-factory name="ConnectionFactory1NonMgmt"> <connectors> <connector-ref connector-name="remote-jms-nonmgmt"/> </connectors> <entries> <entry name="java:/ConnectionFactory1NonMgmt"/> </entries> </connection-factory> <pooled-connection-factory name="ConnectionFactory1Mgmt"> <user>jmsuser</user> <password>jmspassword</password> <connectors> <connector-ref connector-name="remote-jms-mgmt"/> </connectors> <entries> <entry name="java:/ConnectionFactory1Mgmt"/> </entries> </pooled-connection-factory> </jms-connection-factories> </hornetq-server> ... <socket-binding-group name="full-ha-sockets" default-interface="public"> ... <outbound-socket-binding name="remote-jms-binding"> <remote-destination host="192.168.117.159" port="5445"/> </outbound-socket-binding> </socket-binding-group>
Producer code:
@Resource(mappedName = "java:/ConnectionFactory1Mgmt") private ConnectionFactory connectionFactory; public void sendMessage(String text) { Connection connection = connectionFactory.createConnection(); Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE ); Queue queue = session.createQueue( "RemoteQueue1" ); MessageProducer producer = session.createProducer( queue ); connection.start(); TextMessage message = session.createTextMessage(); message.setText( text ); producer.send( message ); session.close(); connection.close(); }
Message-Driven Bean consumer code:
import org.jboss.ejb3.annotation.ResourceAdapter; @ResourceAdapter("ConnectionFactory1Mgmt") @MessageDriven( name="ConsumerMdb", activationConfig = { @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/RemoteQueue1") }) public class ConsumerMdb implements MessageListener { ... }
Here you might need to import org.jboss.ejb3:jboss-ejb3-ext-api:2.0.0 library into you project, but don’t forget to mark it as provided by the runtime environment.
Manually consuming messages from EJB (inside container):
InitialContext context = new InitialContext(); ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup( "ConnectionFactory1NonMgmt" ); Connection connection = connectionFactory.createConnection( "jmsuser", "jmspassword" ); Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE ); Queue queue = session.createQueue( "RemoteQueue1" ); MessageConsumer consumer = session.createConsumer( queue ); connection.start(); Message message = consumer.receive();
General notes:
- Use <pooled-connection-factory> for MDBs and message producers deployed inside container.
- Use <connection-factory> for non-managed producers and consumers (including the remote once).
Reading:
- JBoss forum thread: https://community.jboss.org/message/722711.
- Justin Bertram explaining my doubts (thanks!): https://community.jboss.org/message/780778.