2 Replies Latest reply on Oct 3, 2017 2:02 PM by jfisherdev

    Migrating jboss-service.xml/SAR to Singleton Session Beans

    jfisherdev

      When initially migrating from JBoss AS 4.2.2 to WildFly 9.0.2.Final I continued to use jboss-service.xml/SAR deployments for singleton services.

       

      I got this to work with some adjustments [no xmbean descriptors, not using <depends/> for managed resources, etc]; however, I am looking to get away from this approach in favor

      of deploying them as standard Java EE Singleton Session Beans using annotations. The main reasons being portability, the benefits/capabilities of having these be managed EE resources, and the fact that many services do not necessarily need the JMX instrumentation provided by SAR deployments.

       

      So far, the process has not been too difficult and has mainly meant doing the following:

      - Replace the SAR deployment with a standard EJB JAR deployment and add an <ejb> module to the application.xml in EAR applications

      - Add @Singleton and @Startup annotations to the service implementation class

      - Annotate lifecycle start()/stop() methods with @PostConstruct and @PreDestroy

      - Instrument the service as a JMX resource if needed

       

      The one area where I do have questions is with expressing dependencies of two types that were previously expressed with the <depends/> element in jboss-service.xml descriptors:

       

      - Dependencies on other singleton services

      - Dependencies on managed resources which are accessed via JNDI  [Stateless Session Beans, JMS resources, such as connection factories and destinations]

       

      The first type, which you could still use the <depends/> element for in WildFly 9 SAR deployments, I believe can be expressed using the javax.ejb.DependsOn annotation.

       

      The second type, which you could NOT use in WildFly 9 SAR deployments, is the one I am less certain about. This one is especially of interest because one thing I found with using SAR deployments in WildFly 9 is that sometimes exceptions would be thrown from a service lifecycle methods that access EJBs or JMS resources via programmatic JNDI lookup and would usually say something to the effect that the resource could not be found in JNDI.

       

      To accomplish the equivalent of something like this:

       

      <depends>jboss.mq.destination:service=Topic,name=appTopic</depends>
      <depends>jboss.j2ee:jndiName=ejb/AppServiceBean</depends>
      

       

      I believe I would need to use resource injection like this:

       

      @Resource(lookup = "java:/topic/appTopic")
      private Destination appTopic;
      
      //Using portable namespace binding, but could use others
      @EJB(lookup ="java:/global/appName/moduleName/ejb/AppServiceBean")
      private AppService appService;
      

       

      I haven't used resource injection extensively, but if I'm understanding things correctly that would ensure these are available. Am I correct to say that the lookup values NOT resolved relative to the global "java:/" namespace if not specified like they are when accessed in a programmatic fashion [e.g. "topic/appTopic" is bound in the java:/ namespace, but can be found using Context.lookup("topic/appTopic") without the namespace qualifier]. This seems to be the case, because in my initial attempt at this the injection failed without including the namespace.

       

      Overall I think I'm moving in the right direction with this, but would appreciate confirmation or clarification on the items identified.

        • 1. Re: Migrating jboss-service.xml/SAR to Singleton Session Beans
          jaikiran

          The first type, which you could still use the <depends/> element for in WildFly 9 SAR deployments, I believe can be expressed using the javax.ejb.DependsOn annotation.

           

          There's a slight difference in the JBoss AS specific  <depends/> which was supported in previous versions and this EE spec's @DependsOn. I don't have the spec at hand right now, but the EJB spec explains what the DependsOn actually does and when it can be used.

           

          Josh Fisher wrote:

           

           

          The second type, which you could NOT use in WildFly 9 SAR deployments, is the one I am less certain about. This one is especially of interest because one thing I found with using SAR deployments in WildFly 9 is that sometimes exceptions would be thrown from a service lifecycle methods that access EJBs or JMS resources via programmatic JNDI lookup and would usually say something to the effect that the resource could not be found in JNDI.

           

          To accomplish the equivalent of something like this:

           

          1. <depends>jboss.mq.destination:service=Topic,name=appTopic</depends>
          2. <depends>jboss.j2ee:jndiName=ejb/AppServiceBean</depends>

           

          I believe I would need to use resource injection like this:

           

          1. @Resource(lookup="java:/topic/appTopic")
          2. privateDestinationappTopic;
          3. //Usingportablenamespacebinding,butcoulduseothers
          4. @EJB(lookup="java:/global/appName/moduleName/ejb/AppServiceBean")
          5. privateAppServiceappService;

           

          That's right. You either use annotation based injections or use the corresponding deployment descriptor constructs (like resource-ref) to setup these dependencies.

           

          Josh Fisher wrote:

           

          Am I correct to say that the lookup values NOT resolved relative to the global "java:/" namespace if not specified like they are when accessed in a programmatic fashion [e.g. "topic/appTopic" is bound in the java:/ namespace, but can be found using Context.lookup("topic/appTopic") without the namespace qualifier]. This seems to be the case, because in my initial attempt at this the injection failed without including the namespace.

           

           

           

          The @Resource annotation essentially boils down to the following:

           

          1. When used on the field, you are instructing the container to inject some value into that field. The injection into the field always happens through a JNDI source, so you either have to tell the container the source JNDI name (which you do with the "lookup" attribute) or the container has to infer it in some cases (based on the type of the field). The lookup attribute if specified, has to be the fully qualified JNDI name from where you want the field's value (that gets injected) to be sourced. There's also the mappedName which was meant to do the same thing as the lookup attribute, but the mappedName isn't portable and each container is allowed to implement its own semantics for it.

           

          2. In addition to the injection, that you get as noted in the previous point, the usage of @Resource also always creates a *new JNDI binding* in the component specific namespace of the component in which this @Resource is being used. Each EE component by default has a scoped JNDI namespace called the java:comp/ which is "private" to that component - no other component can lookup into other components environment naming context (ENC). So what the @Resource does is, it creates a new entry under this java:comp/ namespace for the injected field which ultimately is a reference to the object that was injected. So this new entry under the java:comp/ namespace, by default, gets a JNDI name (relative to java:comp/ namespace) and  that name is inferred by the container, using the field name and a few other details (the spec has the exact details). However, you can instruct the container to use a name of your choice by setting the value for the "name" attribute of the @Resource annotation. Unlike the lookup attribute of the Resource annotation, the name attribute is relative and is relative to the java:comp/ namespace.

          1 of 1 people found this helpful
          • 2. Re: Migrating jboss-service.xml/SAR to Singleton Session Beans
            jfisherdev

            Thank you for the very helpful response.

             

            This addresses the issue and has shown me the portability and capabilities of EJB 3.1 singleton beans. The migration efforts will certainly be worth it.