How to declare service lifecycle dependencies (such as EJB) between deployments in JBoss EAP 8 / 7 / 6

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 8.x
    • 7.x
    • 6.x

Issue

  • How to declare service lifecycle dependencies (such as EJB) between deployments in JBoss EAP 6
  • We have a startup bean that depends on an MBean. They're both in the same ear file. Can we make the startup bean delay until the MBean is ready?
  • My application uses QueueReceiver in the code and when I shutdown jboss I stop consume the messages from the queue by stopping my thread from the ServletListener.
    the problem is that HornetQ shutdown asynchronously and we get exceptions when trying to access the Queue.
    How can I depend on the hornetQ service from servletListener so that it won't stop before my application stops?
  • We have two JBoss-Servers with configuration standalone-full-ha.xml. Both have two JMS-Servers. We have often the problem, that our application doesn´t get
    deployed because of an missing dependency to a JMS connection factory. The JMS Connection factory gets active after the deployment failure.
    And most times when I simply restart the server . Is this a kind of timing issue? How can we fix this?

Resolution

JBoss EAP 7 / 6 starts all services in parallel, it will look at annotations and deployment descriptors to determine dependencies and the start up order for services that require other services to be started. It looks for @EJB or ejb-ref in ejb-jar.xml, resource references will be checked with @Resource or resource-ref in deployment descriptor, and also looks at env-entries in the deployment descriptor. For Singleton EJBs, it looks at @DependsOn. JBoss also allows @DependsOn to be used between Session EJBs.

For EJBs

Using @EJB

import javax.ejb.EJB;

public class EJBClientBean {

   @EJB(lookup="java:global/helloWorld/helloWorld-ejb/HelloBean!com.jboss.examples.ejb3.Hello")
   private Hello helloEJB;

}

Using ejb refs in ejb-jar.xml or web.xml

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
      version="3.0">
  <enterprise-beans>
    <session>
        <ejb-name>HelloBean</ejb-name>
        <session-type>Stateless</session-type>
        <transaction-type>Container</transaction-type>
        <ejb-local-ref>
            <ejb-ref-name>ejb/StatelessBean2Remote</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <local>com.jboss.examples.ejb3.StatelessLocal</local>
            <ejb-link>StatelessBean2</ejb-link>
        </ejb-local-ref>
    </session>
  </enterprise-beans>
</ejb-jar>

For other resources

Using @Resource

import javax.annotation.Resource;

public class BackingBean {

   @Resource(lookup="java:jboss/datasources/ExampleDS")
   private DataSource exampleDS;

}

Using resource-ref in ejb-jar.xml / web.xml

Example of resource-ref in web.xml, showing the war depends on the JMS Queue bound at java:/jms/queue/test. The resource-ref creates java:comp/env/testQueue for the war which is linked to the global JNDI address of the JMS Queue at java:/jms/queue/test. The war can then lookup the JMS Queue at java:comp/env/testQueue and JBoss EAP will know the war depends on the JMS Queue such that it will be started before the war.

<?xml version='1.0' encoding='UTF-8'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

  <!-- Example of JMS Destination -->
  <resource-ref id="testQueue">
         <res-ref-name>testQueue</res-ref-name>
         <res-type>javax.jms.Queue</res-type>
         <res-auth>Container</res-auth>
         <lookup-name>java:/jms/queue/test</lookup-name>
  </resource-ref>

  <!-- Example of Datasource -->
  <resource-ref>
      <description>SQL server</description>
      <res-ref-name>myDatasource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      <lookup-name>java:jboss/datasources/ExampleDS</lookup-name>
  </resource-ref>

    <!-- lookup ejb ref example -->
    <ejb-ref>    
        <ejb-ref-name>RemoteInterfaceBean</ejb-ref-name>
        <lookup-name>java:global/ejb-test-ear/ejb/RemoteInterfaceBean!org.jboss.as.test.integration.ejb.injection.ejbref.lookup.RemoteInterface</lookup-name>
    </ejb-ref> 

</web-app>

application.xml example:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"
  version="6">

<!-- this becomes java:app/env/ExampleDS => java:jboss/datasources/ExampleDS --> 
  <resource-ref>
    <res-ref-name>ExampleDS</res-ref-name> 
    <lookup-name>java:jboss/datasources/ExampleDS</lookup-name>
  </resource-ref>
...
</application>

These are 'start' dependencies where one service needs to be able to access the other service as soon as it gets started such as the use case where one service has @PostConstruct and tries to call an EJB it depends on as soon as it is started. If you have class dependencies and need access to classes in another deployment, then see this article1. For general top level deployment ordering see this article2. To control the initialization order of an EAR's subdeployments / modules, see this article3.

If an EJB injects or depends on a resource such as an @Singleton which has not been started (for example, this @Singleton has a @PostConstruct method which takes some time to finish), then this EJB should not be remotely accessible until all of its dependencies have been started. There is a known This content is not included.bug4 related on JBoss EAP 6.0 and 6.1.

Spring applications typically do not use @Resource and should define a resource-ref in their web.xml for datasources and other JNDI related resources as described in this related solution 5.

To ensure JNDI resources are available at startup/shutdown of an application, a resource-ref, @Resource or other is needed so the container knows there is a dependency 6.

1

How to declare classloading dependencies between deployments in JBoss EAP 6
https://access.redhat.com/site/solutions/308003

2

How to control the order of deployed applications on JBoss Enterprise Application 6
https://access.redhat.com/site/solutions/88763

3

How to control the initialization order of an EAR's subdeployments / modules in JBoss Enterprise Application 6
https://access.redhat.com/site/solutions/524873

4

Remote EJB client hangs trying to connect to a clustered EJB which has not fully started in JBoss EAP 6.1.x
https://access.redhat.com/site/solutions/524823

5

Spring Application starting before its Datasource and Messaging dependencies in JBoss EAP 6 results in NameNotFoundException
https://access.redhat.com/solutions/1200843

6

How to ensure JNDI resources are available for application during startup/shutdown of JBoss EAP 7 / 6 https://access.redhat.com/solutions/380473

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.