Announcement Announcement Module
Collapse
No announcement yet.
Example of a <jms:jca-listener-container> using JBoss JMS with a custom WorkManager Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Example of a <jms:jca-listener-container> using JBoss JMS with a custom WorkManager

    I know that I had a lot of difficulty putting all of the pieces together in order to wire a jms message listener to Jboss using the <jms:jca-listener-container> leveraging off of a custom WorkManager setup within JBoss. I wanted to share our configuration with the Spring community in hopes that it will help somebody else avoid the same difficulty in the future.

    Spring does provide the org.springframework.jca.work.jboss.JBossWorkManage rTaskExecutor, which will work fine for you if you intend to use the default JBoss WorkManager name 'WorkManager' that is typically setup during a common JBoss installation. Perhaps in the future, the JBossWorkManagerTaskExecutor will expose some attributes allowing us to specify the custom WorkManager ObjectName (hint, hint )
    However, we wanted a separate WorkManager for a highly used JMS queue, allowing us finer granularity to configure the WorkManager separately for our needs.

    The problem with the JBossWorkManagerTaskExecuter is that it uses the org.springframework.jca.work.jboss.JBossWorkManage rUtils to return the default WorkManager using the JBossWorkManagerUtils.getWorkManager() method, which is 'hard-coded' to only locate the default JBoss WorkManager named at the JMX ObjectName path: jboss.jca:service=WorkManager.

    There is currently no way to set a different ObjectName and use a different WorkManager.
    To get around this limitation, we have defined our own WorkManager and WorkManagerThreadPool within Jboss, which can be placed in a separate xml file in the server's depoy directory. Here is what our JBoss WorkManager and WorkManagerThreadPool looks like:

    Code:
    <deployment xmlns="urn:jboss:bean-deployer:2.0">
    
      <!-- ==================================================================== -->
      <!-- JBossCX setup, for J2EE connector architecture support               -->
      <!-- ==================================================================== -->
    
      <!-- THREAD POOL -->
      <bean name="MPlusWorkManagerThreadPool" class="org.jboss.util.threadpool.BasicThreadPool">
    
         <!-- Expose via JMX -->
         <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jca:service=MPlusWorkManagerThreadPool", exposedInterface=org.jboss.util.threadpool.BasicThreadPoolMBean.class)</annotation>
    
         <!-- The name that appears in thread names -->
         <property name="name">MPlusWorkManagerThread</property>
    
         <!-- The maximum amount of work in the queue -->
         <property name="maximumQueueSize">1024</property>
    
         <!-- The maximum number of active threads -->
         <property name="maximumPoolSize">100</property>
    
         <!-- How long to keep threads alive after their last work (default one minute) -->
         <property name="keepAliveTime">60000</property>
    
      </bean>
    
      <!-- WORK MANAGER -->
      <bean name="MessageHubWorkManager" class="org.jboss.resource.work.JBossWorkManager">
    
         <!-- Expose via JMX -->
         <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jca:service=MessageHubWorkManager", exposedInterface=org.jboss.resource.work.JBossWorkManagerMBean.class)</annotation>
    
         <!-- The thread pool -->
         <property name="threadPool"><inject bean="MPlusWorkManagerThreadPool"/></property>
    
         <!-- The xa terminator -->
         <property name="XATerminator"><inject bean="TransactionManager" property="XATerminator"/></property>
    
      </bean>
    
    </deployment>
    Spring has excellent JMX support and now that you have your custom WorkManager deployed in JBoss, you can easily located the WorkManager via JMX by it's ObjectName. Following, is our Spring configuration, showing the necessary beans defined. Particularly, note the messageHubWorkManager bean and how it is located within the mBeanServer. Finally, the MessageHubListener is simply a Message Driven Pojo (MDP) that implements the javax.jms.MessageListener interface, recieving messages via the onMessage(Message message) method.


    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans default-autowire="byName"
           xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jee="http://www.springframework.org/schema/jee"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:jms="http://www.springframework.org/schema/jms"
           xsi:schemaLocation="
             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
             http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
    
    
    	<bean id="mbeanServer" class="org.jboss.mx.util.MBeanServerLocator" factory-method="locateJBoss"/>
    
    	<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    		<property name="autodetectTransactionManager" value="true"/>
        	<!--<property name="transactionManagerName" value="java:/TransactionManager"/>-->
      	</bean>
    
      	<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
    
    	<bean id="jbossResourceAdapter" class="org.jboss.resource.adapter.jms.JmsResourceAdapter"/>
    
    	<bean id="messageHubWorkManager" factory-bean="mbeanServer" factory-method="getAttribute">
    		<constructor-arg>
    			<bean class="org.springframework.jmx.support.ObjectNameManager" factory-method="getInstance">
    				<constructor-arg value="jboss.jca:service=MessageHubWorkManager" />
    			</bean>
    		</constructor-arg>
    		<constructor-arg value="Instance" />
    	</bean>
    
    	<bean id="messageHubTaskExecuter" class="org.springframework.jca.work.WorkManagerTaskExecutor">
    		<property name="workManager" ref="messageHubWorkManager"/>
    	</bean>
    
    	<bean id="jbossResourceAdapterFactory" class="org.springframework.jca.support.ResourceAdapterFactoryBean">
    		<property name="resourceAdapter" ref="jbossResourceAdapter"/>
    		<property name="workManager" ref="messageHubTaskExecuter"/>
    	</bean>
    
    	<bean id="jbossActivationSpecFactory" class="org.springframework.jms.listener.endpoint.StandardJmsActivationSpecFactory">
    		<property name="activationSpecClass" value="org.jboss.resource.adapter.jms.inflow.JmsActivationSpec"/>
    		<property name="defaultProperties">
    			<props>
    				<prop key="sessionTransacted">false</prop>
    				<prop key="minSession">1</prop>
    				<prop key="maxSession">15</prop>
    			</props>
    		</property>
    	</bean>
    
    	<bean id="MessageHubListener" class="com.rbs.envoy.listener.MessageHub"/>
    
      	<jms:jca-listener-container
      		resource-adapter="jbossResourceAdapterFactory" activation-spec-factory="jbossActivationSpecFactory"
      		concurrency="5-5" acknowledge="auto">
    
        	<jms:listener destination="rbs.envoy.MessageHubQueue" ref="MessageHubListener"/>
    
      	</jms:jca-listener-container>
    </beans>
    Good luck and I hope this proves helpful to somebody else!
Working...
X