How to configure EJB3 MDBs for IBM Websphere MQ

You do not need deployment descriptors for ejb3.  The perferred method for configuring EJB3s would be with the annotations.

 

This is how you would define your ejb3 bean with all of the properties.

 

@MessageDriven( name="MyMDBName",
        activationConfig = 
        { 
            @ActivationConfigProperty(propertyName="messagingType",propertyValue="javax.jms.MessageListener"),
            @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "queueA"),
            @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
            @ActivationConfigProperty(propertyName = "channel", propertyValue = "SYSTEM.DEF.SVRCONN"),
            @ActivationConfigProperty(propertyName = "hostName", propertyValue = "devmq1sun"),
            @ActivationConfigProperty(propertyName = "queueManager", propertyValue = "DEVMQ1SUN"),
            @ActivationConfigProperty(propertyName = "port", propertyValue = "1416"),
            @ActivationConfigProperty(propertyName = "transportType", propertyValue = "CLIENT")

        }) 
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ResourceAdapter(value = "wmq.jmsra2.rar")

 

 

You can get rid of your desployment descriptors as the annotations take their place.(ejb-jar.xml, jboss.xml).  The above example uses your resource adapter and all of your activation configuration properties.  I think I got them all in there.  I did notice however that you are using the "wmq.jmsra2.rar" in your ejb descriptor, but your depends in the ds.xml file is using "wmq.jmsra.rar".  You may want to fix that to get the dependencies correct.

 

So this is how you would deploy one mdb with the queue's defined in your ds.xml file.

 

The next logical question would be how do I take the Activation Configuration Properties out of the mdb and

 

How do I take those settings and move them out to a global place where I can define them for all MDBs?
-------------------------------------------------------------------------------------------------------

 

JBoss EJB3's work similar to EJB2.x, but not quite.  In EJB3, the file that governs the interceptors and global settings is *NOT* the standard-jboss.xml file anymore.  EJB3 now uses the deploy/ejb3-interceptors-aop.xml file.  The default configuration(now it's called a domain) for all MDBs is "<domain name="Message Driven Bean">".

 

Defining your own domains.  You can define your own domains if you wish.  So if you wanted to you could copy the "Message Driven Bean" domain and rename it to something like "IBMMQ Message Driven Bean".  You could add a class annotation that looks like @AspectDomain("IBMMQ Message Driven Bean")

 

Defining Properties in the domain.  Here is the domain we were talking about.

 

<domain name="Message Driven Bean">
      <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
         <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
      </bind>
      <bind pointcut="execution(public * *->*(..))">
         <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
         <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
      </bind>
      <annotation expr="!class(@org.jboss.annotation.ejb.PoolClass)">
         @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
      </annotation>
   </domain>

 


Please notice that the <annotation> tag actaully inserts a new PoolClass annotation into each MDB.  This is so that you don't have to define the pool for each mdb.  We are going to do the same with your other defaults.  One more thing to note, the annotation expression, "<annotation expr="!class(@org.jboss.annotation.ejb.PoolClass)">" will look to see if there is a class annotation called PoolClass.  If the expression is true, then the contained PoolClass annotation is inserted.  This is an important point, becuase when we put our defaults in, we can't use activationConfig, because it is already being used in the mdb.  If we insert it and we already have one we will have problems.  So we have to come up with another annoation to insert default activationconfig properties, called DefaultActivationSpecs.  This is so that we can have some defaults along with the original activation specs that are in the mdb itself.

 

This would be the completed IBMMQ Message Driven Bean domain configuration.

 

<domain name="IBMMQ Message Driven Bean">
      <bind pointcut="execution(public * @javax.annotation.security.RunAs->*(..))">
         <interceptor-ref name="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory"/>
      </bind>
      <bind pointcut="execution(public * *->*(..))">
         <interceptor-ref name="org.jboss.ejb3.stateless.StatelessInstanceInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.tx.TxInterceptorFactory"/>
         <interceptor-ref name="org.jboss.ejb3.AllowedOperationsInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor"/>
         <interceptor-ref name="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory"/>
      </bind>
      <annotation expr="!class(@org.jboss.annotation.ejb.PoolClass)">
         @org.jboss.annotation.ejb.PoolClass (value=org.jboss.ejb3.StrictMaxPool.class, maxSize=30, timeout=10000)
      </annotation>
      <annotation expr="!class(@org.jboss.annotation.ejb.DefaultActivationSpecs)">
         @org.jboss.annotation.ejb.DefaultActivationSpecs ({@ActivationConfigProperty(propertyName = "channel", propertyValue = "SYSTEM.DEF.SVRCONN"),
             @ActivationConfigProperty(propertyName = "hostName", propertyValue = "devmq1sun"),
             @ActivationConfigProperty(propertyName = "queueManager", propertyValue = "DEVMQ1SUN"),
             @ActivationConfigProperty(propertyName = "port", propertyValue = "1416"),
             @ActivationConfigProperty(propertyName = "transportType", propertyValue = "CLIENT")})
      </annotation>
   </domain>

 


and your completed mdb annotations would look something like this using the new domain configuration..

 

@MessageDriven( name="MyMDBName",
        activationConfig = 
        { 
            @ActivationConfigProperty(propertyName="messagingType",propertyValue="javax.jms.MessageListener"),
            @ActivationConfigProperty(propertyName = "destinationType",propertyValue = "javax.jms.Queue"),
            @ActivationConfigProperty(propertyName = "destination", propertyValue = "queueA"),
            @ActivationConfigProperty(propertyName = "useJNDI", propertyValue = "true"),
        }) 
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ResourceAdapter(value = "wmq.jmsra2.rar")
@AspectDomain("IBMMQ Message Driven Bean")

 

References

[1] IBM outbound adapter properties

[2] IBM EJB 2.x instructions