glassfish
  1. glassfish
  2. GLASSFISH-20715

Cannot define a resource in app client and reference it from a MDB

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 4.0_b89_RC5
    • Fix Version/s: None
    • Component/s: standalone_client
    • Labels:
      None

      Description

      I have an enterprise application which consists of an EJB module and an application client module.

      Here's the application client code. This defines a JMS connection factory resource and a JMS queue resource, both in the java:app namespace:

      @JMSDestinationDefinition(
              name = "java:app/jms/testQueue1", 
              interfaceName = "javax.jms.Queue", 
              resourceAdapter = "jmsra", 
              destinationName = "testQueue1")
      
      @JMSConnectionFactoryDefinition(
              name = "java:app/jms/testConnectionFactory"
      )
      
      public class Main {
         
          @Resource(lookup="java:app/jms/testConnectionFactory") static ConnectionFactory connectionFactory;
          @Resource(lookup="java:app/jms/testQueue1") static Queue queue;
          
          public static void main(String[] args) {
              
              System.out.println("About to send message");
              try (JMSContext context = connectionFactory.createContext()){
                  context.createProducer().send(queue,"Hello world");
                  System.out.println("Successfully sent message");
              }
          }
      }
      

      Here's the EJB code. It consists of a MDB as follows:

      @MessageDriven(activationConfig = {
          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
          @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:app/jms/testQueue1")
      })
      public class MDB implements MessageListener {
          
          public MDB() {
          }
          
          @Override
          public void onMessage(Message message) {
              try {
                  System.out.println("MDB received message: "+message.getBody(String.class));
              } catch (JMSException ex) {
                  Logger.getLogger(MDB.class.getName()).log(Level.SEVERE, null, ex);
              }
          }
      }
      

      As can be seen, the MDB's destinationLookup references the queue resource that is defined in the applicaiton client module.

      However this enterprise application will not deploy. Here's the error message in the server log:

      WARNING:   RAR8501: Exception during endpoint activation for ra 
         [ jmsra ], activationSpecClass [ com.sun.messaging.jms.ra.ActivationSpec ] : 
         javax.resource.ResourceException: MQRA:EC:Invalid destinationLookup java:app/jms/testQueue1 
         configured in ActivationSpec of MDB for no JNDI name found
      SEVERE:   MDB00017: [MDB]: Exception in creating message-driven bean container: [java.lang.Exception]
      SEVERE:   java.lang.Exception
      java.lang.Exception
      	at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:215)
      	at org.glassfish.ejb.mdb.MessageBeanContainer.<init>(MessageBeanContainer.java:252)
      	at org.glassfish.ejb.mdb.MessageBeanContainerFactory.createContainer(MessageBeanContainerFactory.java:63)
      	at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:221)
      	at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:291)
      	at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:99)
      	at org.glassfish.internal.data.ModuleInfo.load(ModuleInfo.java:206)
      	at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:313)
      	at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:493)
      	at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
      	at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)
      	at java.security.AccessController.doPrivileged(Native Method)
      	at javax.security.auth.Subject.doAs(Subject.java:356)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:522)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:546)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1423)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1500(CommandRunnerImpl.java:108)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1762)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1674)
      	at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
      	at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
      	at org.glassfish.grizzly.http.server.StaticHttpHandler.service(StaticHttpHandler.java:297)
      	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:246)
      	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
      	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
      	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
      	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
      	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
      	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
      	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
      	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
      	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
      	at java.lang.Thread.run(Thread.java:724)
      Caused by: javax.resource.ResourceException: MQRA:EC:Invalid destinationLookup java:app/jms/testQueue1 
         configured in ActivationSpec of MDB for no JNDI name found
      	at com.sun.messaging.jms.ra.EndpointConsumer.setDestinationType(EndpointConsumer.java:756)
      	at com.sun.messaging.jms.ra.EndpointConsumer._init(EndpointConsumer.java:299)
      	at com.sun.messaging.jms.ra.EndpointConsumer.<init>(EndpointConsumer.java:190)
      	at com.sun.messaging.jms.ra.ResourceAdapter.endpointActivation(ResourceAdapter.java:458)
      	at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:207)
      	... 41 more
      Caused by: javax.naming.NamingException: Lookup failed for 'java:app/jms/testQueue1' 
         in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory,
         java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl,
         java.naming.factory.url.pkgs=com.sun.enterprise.naming} 
         [Root exception is javax.naming.NameNotFoundException: No object bound to name java:app/jms/testQueue1]
      	at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
      	at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
      	at javax.naming.InitialContext.lookup(InitialContext.java:411)
      	at javax.naming.InitialContext.lookup(InitialContext.java:411)
      	at com.sun.messaging.jms.ra.Util.jndiLookup(Util.java:333)
      	at com.sun.messaging.jms.ra.EndpointConsumer.setDestinationType(EndpointConsumer.java:753)
      	... 45 more
      Caused by: javax.naming.NameNotFoundException: No object bound to name java:app/jms/testQueue1
      	at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:741)
      	at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:715)
      	at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:167)
      	at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:471)
      	... 50 more
      

      However if I modify my MDB to reference the queue using the mappedName attribute:

      @MessageDriven(mappedName="java:app/jms/testQueue1", activationConfig = {
          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
      })
      

      It deploys OK and I can also run the application client.

      I see similar errors if the MDB references the queue using mappedName but I also use the connectionFactory activation property to reference the connection factory.

      I see similar errors if I use a namespace of java:global.

      I believe that this is a bug. When a MDB is being activated the resource adapter should have full access to all resources in the java:global namespeace, all resources in the java:app namespace (within the same application), all resources in the java:module namespace (within the same module) and all resources in the java:comp namespace (within the same component}. In this particular case, the resources were defined and referenced within the same application (though different modules and components), so I would have expected by examples to have worked using the java:app and java:global namespaces.

      I note that the JCA 1.7 specification section 13.4.4 states:

      The application server must make the application component environment
      namespace of the endpoint (that is being activated), available to the resource adapter
      during the call to the endpointActivation and endpointDeactivation
      methods. The resource adapter may use this JNDI context to access other resources.

      In my view this is not intended to exclude namespaces other than java:comp. It explicitly mentions "the application component environment namespace" since when endpoint activation is taking place the application component is still in the process of being set up, and so the spec needs to make clear that the java:comp is still available.

        Activity

        Hide
        Nigel Deakin added a comment -

        Test case attached. Download and unzip.

        The root directory ACCTOMDB is a Netbeans EAR project containing component EJB and ACC projects in their respective subdirectories.

        Start NetBeans and use File --> Open project to open the EAR project.

        In the projects view, select the ACCTOMDB project and choose "Resolve server configuration errors" (or something similar) from the right-mouse menu to configure it to point to your GlassFish installation.

        In the projects view, select the ACCTOMDB project and choose "deploy" from the right-mouse menu to build and deploy the EAR.

        The deployment will fail with javax.naming.NameNotFoundException: No object bound to name java:app/jms/testQueue1

        Browse under the ACCTOMDB project and open the component EJB and ACC projects. In the EJB project, edit the MDB to specify the destination using mappedName rather than destinationLookup (see the commented out line). This will deploy without an error.

        Note that there's no need to actually run the ACC, but if you select the ACC project and choose "run" from the right-mouse menu, it will send a message to the MDB and the MDB will log this in the server log.

        Show
        Nigel Deakin added a comment - Test case attached. Download and unzip. The root directory ACCTOMDB is a Netbeans EAR project containing component EJB and ACC projects in their respective subdirectories. Start NetBeans and use File --> Open project to open the EAR project. In the projects view, select the ACCTOMDB project and choose "Resolve server configuration errors" (or something similar) from the right-mouse menu to configure it to point to your GlassFish installation. In the projects view, select the ACCTOMDB project and choose "deploy" from the right-mouse menu to build and deploy the EAR. The deployment will fail with javax.naming.NameNotFoundException: No object bound to name java:app/jms/testQueue1 Browse under the ACCTOMDB project and open the component EJB and ACC projects. In the EJB project, edit the MDB to specify the destination using mappedName rather than destinationLookup (see the commented out line). This will deploy without an error. Note that there's no need to actually run the ACC, but if you select the ACC project and choose "run" from the right-mouse menu, it will send a message to the MDB and the MDB will log this in the server log.
        Hide
        David Zhao added a comment -

        Forward it to Amy for a closer look.

        Show
        David Zhao added a comment - Forward it to Amy for a closer look.
        Hide
        amy.yang added a comment - - edited

        Based on my investigation, currently the appclient container processes all resource definitions later than the MDB setup. Details are forwarded by Marina through email to Tim Quinn, Hong Zhang and Jagadish Ramu.
        We need the ACC resource definitions to be processed first.

        Show
        amy.yang added a comment - - edited Based on my investigation, currently the appclient container processes all resource definitions later than the MDB setup. Details are forwarded by Marina through email to Tim Quinn, Hong Zhang and Jagadish Ramu. We need the ACC resource definitions to be processed first.
        Hide
        Hong Zhang added a comment -

        Assign to Tim to take a look.

        Show
        Hong Zhang added a comment - Assign to Tim to take a look.
        Hide
        Tim Quinn added a comment -

        One clarification and then some questions.

        Clarification: The app client container is involved only when an app client is running, not during deployment. There is a separate app client deployer which does run, as do the other deployers, during application deployment.

        Questions: If the JMSDestinationDefinition or JMSConnectionFactoryDefinition are defined in the app client, doesn't that imply that they will become active - and therefore present in JNDI - only when the app client runs? If so, shouldn't we expect the name look-up to fail if the app client is not running - which it will not be during deployment?

        Show
        Tim Quinn added a comment - One clarification and then some questions. Clarification: The app client container is involved only when an app client is running, not during deployment. There is a separate app client deployer which does run, as do the other deployers, during application deployment. Questions: If the JMSDestinationDefinition or JMSConnectionFactoryDefinition are defined in the app client, doesn't that imply that they will become active - and therefore present in JNDI - only when the app client runs? If so, shouldn't we expect the name look-up to fail if the app client is not running - which it will not be during deployment?
        Hide
        Nigel Deakin added a comment - - edited

        The resources are defined in the application client module, which is part of an enterprise application (ear file) deployed on the server. They are defined as being application-scoped (not component- or module-scoped) so I would expect them to exist for the lifetime of the enterprise application and be available to all modules in the application, including the EJB module. (But ultimately this is a Java EE platform spec feature and we may need to ask the spec leads).

        Show
        Nigel Deakin added a comment - - edited The resources are defined in the application client module, which is part of an enterprise application (ear file) deployed on the server. They are defined as being application-scoped (not component- or module-scoped) so I would expect them to exist for the lifetime of the enterprise application and be available to all modules in the application, including the EJB module. (But ultimately this is a Java EE platform spec feature and we may need to ask the spec leads).
        Hide
        Tim Quinn added a comment -

        It's not clear why this problem should be specific to resources defined in app clients. Defining resources in one component and referring to them from other components seems like a more general requirement for any type of component.

        I've written separately to Hong, who has included Jagadish.

        Show
        Tim Quinn added a comment - It's not clear why this problem should be specific to resources defined in app clients. Defining resources in one component and referring to them from other components seems like a more general requirement for any type of component. I've written separately to Hong, who has included Jagadish.
        Hide
        Roland2 added a comment -

        This might be related, the MDB starts consuming messages before the server is fully up, thus giving exceptions when trying to access services:

        https://www.java.net/forum/topic/glassfish/glassfish/mdbmessage-driven-bean-failing-server-startup?force=153

        Show
        Roland2 added a comment - This might be related, the MDB starts consuming messages before the server is fully up, thus giving exceptions when trying to access services: https://www.java.net/forum/topic/glassfish/glassfish/mdbmessage-driven-bean-failing-server-startup?force=153

          People

          • Assignee:
            Tim Quinn
            Reporter:
            Nigel Deakin
          • Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: