Search code examples
jmsjava-ee-6glassfish-3ibm-mqmessage-driven-bean

MDB under GlassFish listening to remote JMS Queue (MQ via GenericJMSRA)


I am trying to configure a MDB in Glassfish 3.1.2 to listen on a remote JMS Queue (MQ 7 via GenericJMSRA 2.0.1).

When I try to use the JNDI names to define my MDB like this

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "DestinationJndiName", propertyValue = "jms/MyQueue"),
    @ActivationConfigProperty(propertyName = "ConnectionFactoryJndiName", propertyValue = "jms/MyFactory") })
@TransactionManagement(TransactionManagementType.BEAN)
public class SimpleMdb implements MessageListener { ... }

I get this error (minimal extract from the stacktrace):

java.lang.RuntimeException: EJB Container initialization error
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:242)
Caused by: java.lang.Exception
    at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:233)
Caused by: javax.resource.spi.InvalidPropertyException: MyFactory
    at com.sun.genericra.util.ExceptionUtils.newInvalidPropertyException(ExceptionUtils.java:42)
Caused by: javax.naming.NameNotFoundException: MyFactory
    at com.sun.jndi.fscontext.RefFSContext.getObjectFromBindings(RefFSContext.java:400)

If I use the names of the Factory and Queue as defined in the .bindings file and in the resource-adapter definition like shown below, it works fine.

@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "DestinationJndiName", propertyValue = "SOME.REALLY.UGLY.LONG.NAME"),
    @ActivationConfigProperty(propertyName = "ConnectionFactoryJndiName", propertyValue = "THE_NAME_OF_THE_FACTORY") })
@TransactionManagement(TransactionManagementType.BEAN)
public class SimpleMdb implements MessageListener { ... }

When I only replace the factory's JNDI name with the "ugly" one, I get the same stacktrace as above but referring to the "MyQueue".

At the same time my setup of .bindings file, resource-adapter definition in the domain.xml (inserted via a tool) and queue usage in EJBs/Servlets seems to be fine. I can use the queue and its connection factory in the usual an desired way - this works fine:

QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("jms/MyFactory");
Queue asyncQueue = (Queue) ctx.lookup("jms/MyQueue");

Can someone provide insight on why this is happening? I would like to use the JNDI names like "jms/MyQueue" everywhere in the code - including the MDB definition.

Here is the relevant section of my domain.xml:

<resource-adapter-config thread-pool-ids="genericra-thread-pool" resource-adapter-name="genericra">
  <property name="SupportsXA" value="false"></property>
  <property name="ProviderIntegrationMode" value="jndi"></property>
  <property name="RMPolicy" value="OnePerPhysicalConnection"></property>
  <property name="LogLevel" value="FINEST"></property>
  <property name="JndiProperties" value="..."></property>
</resource-adapter-config>
<connector-connection-pool name="genericra-pool-1" resource-adapter-name="genericra" is-connection-validation-required="true" connection-definition-name="javax.jms.QueueConnectionFactory" fail-all-connections="true" transaction-support="NoTransaction">
  <property name="ConnectionFactoryJndiName" value="THE_NAME_OF_THE_FACTORY"></property>
</connector-connection-pool>
<connector-resource pool-name="genericra-pool-1" jndi-name="jms/MyFactory"></connector-resource>
<admin-object-resource res-adapter="genericra" res-type="javax.jms.Queue" jndi-name="jms/MyQueue">
  <property name="DestinationJndiName" value="SOME.REALLY.UGLY.LONG.NAME"></property>
  <property name="Name" value="jms/MyQueue"></property>
</admin-object-resource>
  • GlassFish 3.1.2.9
  • WebSphere MQ 7
  • genericra 2.0.1
  • Java 1.7/JEE 6/EJB 3.1

Solution

  • By now we managed to find a solution. With genericra it is not possible to redirect MDBs to a JNDI name that is given by genericra to the resource. Instead the MDB has to reference the name of the Queue as defined by the .bindings file (on the left side, not the remote name on the right side). Luckily we were able to adapt the .bindings files to our needs.

    Now we may use the JNDI name given to the resource in the genericra configuration for "normal" use in the code like this:

    QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("jms/MyFactory");
    Queue asyncQueue = (Queue) ctx.lookup("jms/MyQueue");
    

    But MDBs have to use the name as given in the .bindings:

    @ActivationConfigProperty(propertyName = "DestinationJndiName", propertyValue = "QUEUE_NAME_IN_BINDINGS")