users@glassfish.java.net

Glassfish 2.1 doesn't use <message-destination-link> element for MDB descr

From: <glassfish_at_javadesktop.org>
Date: Wed, 11 Mar 2009 15:27:41 PDT

Hi,

I've been playing a bit with glassfish 2.1 (Sun Java System Application Server 9.1_02 (build b04-fcs)). I tried to setup a message link scenario between an SLSB bean and an MDB bean using a message-destination-link elements of the ejb-jar.xml deployment descriptor. The idea is that the MDB consumes messages produced by the SLSB bean.

For the SLSB ejb bean I have the following declaration in ejb-jar.xml:
[i]<session>
        <ejb-name>TestSLBean</ejb-name>
        <message-destination-ref>
            <message-destination-ref-name>jms/StockQueue</message-destination-ref-name>
            <message-destination-type>javax.jms.Queue</message-destination-type>
            <message-destination-usage>Produces</message-destination-usage>
            <message-destination-link>LogicalStockQueue</message-destination-link>
          </message-destination-ref>
</session>[/i]

The bean class for this EJB is annotaded with @EJB annotation, so the descriptor above only adds the message destinaion ref to its definition. In it's code this bean looks up the message destination in its JNDI environment and sends a message to it.

The MDB has the following descriptor:
[i]<message-driven>
        <ejb-name>TestMDB</ejb-name>
        <ejb-class>com.dembek.testapp.ejb.mdb.TestMDBBean</ejb-class>
        <message-destination-type>javax.jms.Queue</message-destination-type>
        <message-destination-link>LogicalStockQueue</message-destination-link>
</message-driven>[/i]

The logical destination 'LogicalStockQueue' is then described in the assembly-desriptor element of ejb-jar.xml:
[i]<message-destination>
        <message-destination-name>LogicalStockQueue</message-destination-name>
</message-destination>[/i]

It is also linked to a phisical destination in sun-ejb-jar.xml:
<message-destination>
      <message-destination-name>LogicalStockQueue</message-destination-name>
      <jndi-name>PhysicalQueueName</jndi-name>
</message-destination>

The 'PhysicalQueueName' queue is defined as a queue in JMS resources part of the admin console and linked to a physical destination as well.

Now to the problem: while deploying this ejb app, I get the following exception:
[i]com.sun.enterprise.connectors.ConnectorRuntimeException: JMS resource not created :
at com.sun.enterprise.connectors.system.ActiveJmsResourceAdapter.getPhysicalDestinationFromConfiguration(ActiveJmsResourceAdapter.java:1591)
at com.sun.enterprise.connectors.system.ActiveJmsResourceAdapter.updateMDBRuntimeInfo(ActiveJmsResourceAdapter.java:1421)
at com.sun.enterprise.connectors.inflow.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:170)
at com.sun.ejb.containers.MessageBeanContainer.<init>(MessageBeanContainer.java:209)
at com.sun.ejb.containers.ContainerFactoryImpl.createContainer(ContainerFactoryImpl.java:524)
at com.sun.enterprise.server.AbstractLoader.loadEjbs(AbstractLoader.java:527)
at com.sun.enterprise.server.ApplicationLoader.doLoad(ApplicationLoader.java:191)
at com.sun.enterprise.server.TomcatApplicationLoader.doLoad(TomcatApplicationLoader.java:126)
at com.sun.enterprise.server.ExtendedApplicationLoader.doLoad(ExtendedApplicationLoader.java:134)
at com.sun.enterprise.server.AbstractLoader.load(AbstractLoader.java:238)
.........
at com.sun.enterprise.admin.server.core.jmx.SunoneInterceptor.invoke(SunoneInterceptor.java:304)
at com.sun.enterprise.interceptor.DynamicInterceptor.invoke(DynamicInterceptor.java:174)
at com.sun.enterprise.deployment.client.DeploymentClientUtils.startApplication(DeploymentClientUtils.java:159)
at com.sun.enterprise.deployment.client.DeployAction.run(DeployAction.java:538)
at java.lang.Thread.run(Thread.java:619)[/i]

I digged a bit into the source code and found out, that Glassfish translates the deployment descriptor elements into activation config properties. This translation is performed for MDB's using the default resource adapter 'jmsra' (which is just the internal JMS implementation exposed as a RA).

For some reason, the 'Destination' activation config property is created from the jndiName of the bean (which happens to be the mappedName property of the MessageDriven annotation on the bean class). The message-destination-link element is totally ignored:
From com.sun.enterprise.connectors.system.ActiveJmsResourceAdapter.java:
[i]public void updateMDBRuntimeInfo(EjbMessageBeanDescriptor descriptor_,
           BeanPoolDescriptor poolDescriptor) throws ConnectorRuntimeException{

        String jndiName = descriptor_.getJndiName();
        
        //handling of MDB 1.3 runtime deployment descriptor
        //if no RA-mid is specified, assume it is a 1.3 DD
        if (jndiName == null) { //something's wrong in DD
            logger.log (Level.SEVERE, "Missing Destination JNDI Name");
            String msg = sm.getString("ajra.error_in_dd");
            throw new RuntimeException(msg);
        }
        
        String resourceAdapterMid = ConnectorRuntime.DEFAULT_JMS_ADAPTER;
        
        descriptor_.setResourceAdapterMid(resourceAdapterMid);


        String destName = getPhysicalDestinationFromConfiguration(jndiName);
        
        //1.3 jndi-name ==> 1.4 setDestination
        descriptor_.putRuntimeActivationConfigProperty(
                new EnvironmentProperty(DESTINATION,
                        destName, null));
...[/i]

So, instead of the line:

[i]String jndiName = descriptor_.getJndiName();[/i]

shouldn't we have:

[i]String jndiName = descriptor_.getMessageDestinationLinkName() [/i]

to read the destination name from the message-destination-link element and in case it is not present, fail into any other method (mappedName for instance)?

I know I can just simply specify an activation config properties for my mdb, or use the mappedName property of the MessageDriven annotation to link it to a certain queue, but the point is to adhere to the EJB spec and use the message-destination-link element of the deployment descriptor.

Does anybody know why Glassfish works in this way, using the mappedName of the bean instead of the message-destination-link to resolve the message destination the mdb listens to?

Does it qualify as a bug in the server code?

Thanks

Szymon Dembek
[Message sent by forum member 'szymondembek' (szymondembek)]

http://forums.java.net/jive/thread.jspa?messageID=336500