3 Replies Latest reply on Nov 6, 2012 2:09 AM by Nicklas Karlsson

    Inter-module injection - the easy way (or even any way or alternative approaches)?

    tom-jb Newbie

      I am trying unsuccessfully to get Inter-module injection working.  I expected that I could have a cdi-enabled war @Inject beans from a bean archive in the same container after haing added a dependency to the bean-archive-as-module in the war's jboss-deployment-structure.xml file

       

      My ultimate goal is to enable a rapid development process for our team where developers working on the front end redeploy just a lean war that does not contain any backend services but has a module dependency on a "services" deployable (which is currently an ear but could be just a jar if need be).  Devs doing front-end work would ideally just @Inject any local dependency located in the services deployable with minimal/zero per-service configuration fuss. The services deployable is a fairly time-consuming redeploy, and a frequent redeploy seems unneeded for developers just doing front-end work.

       

      Normally, I might have liked to accomplish this goal by using an exploded ear, where the war is part of the ear, and the front end developer can just redeploy the war portion of the ear after making,say, a java file change, and only the war is redeployed, not the entire ear (which again is slow and seemingly unneeded). Other apps servers that I've worked with in the past offer this specific functionality, but it appears that AS7 does not (unless, hopefully, I'm wrong). On AS7 it seems only the entire ear can be redeployed, even if just the war needs redeployment.

       

      So, I am looking for alternative approaches to accomplish the same goal, such as using a front-end war external to the services deployable that uses inter-module injection (as described here under 5.1.4 in the CDI spec). However when I try this, I get "unsatisfied dependencies" errors.  I think I'm satisfying the requirements for inter-module injection (though the 4th part is unclear to me - "the bean class is required to be accessible to classes in the module, according to the class accessibility requirements of the module architecture"). I have confirmed that my war (which has a  reference in jboss-deployment-structure.xml to the ear module and to the ejb-jar subdeployment inside the ear) can do a jndi lookup for an example EJB using "java:global/my-ear.ear/my-ejb.jar/SomeService", but @Inject can not find the same bean. I'm confident that a have cdi enabled on both the war and on the ear (plus I've tried just a simple bean archive jar instead of my full-blown ear).

       

      Any workarounds or alternative approaches would be most welcome.

       

      Thanks all,

      #Tom

        • 1. Re: Inter-module injection - the easy way (or even any way or alternative approaches)?
          Nicklas Karlsson Master

          The CDI spec statement has an implied "according to the class accessibility requirements of the module architecture of the Java EE specification". Even if the classloading could be configured in an AS to do some special trick, CDI has the visibility rules of a standard EE app (EAR/WAR/JAR). 3rd party tools as JRebel are handy for doing front-end work that don't require heavy backing bean/entity reloads.

          • 2. Re: Inter-module injection - the easy way (or even any way or alternative approaches)?
            tom-jb Newbie

            Thanks much for your response and alternative productivity tip, JRebel. JRebel is a great tool , and I am already using it, but it only goes so far, and still requires redeploy for a variety of circumstances. Further, I'd like to find a solution for the team and the community at large that doesn't require a tool such JRebel, since not all folks and teams can obtain or manage use of JRebel.

             

             

            Nicklas Karlsson wrote:

             

            The CDI spec statement has an implied "according to the class accessibility requirements of the module architecture of the Java EE specification". Even if the classloading could be configured in an AS to do some special trick, CDI has the visibility rules of a standard EE app (EAR/WAR/JAR).

            What you characterize as a "special trick", I might characterize as a "useful application of the wonderful JBoss module system"

             

            It sounds like you are saying based on this spec that EARs, WARs, and even JARs should not have class visibility from say, another war.  If that is true, then it seems like the Inter-module injection part of the spec can never be satisfied in any useful way, since that class accessibility requirement can never be satisfied.

             

            Also, I can sort of understand this tight accessibility restriction for EARs and WARs, but surely just JAR deployables are accessible by other deployables, since jar deployable are basically the same as a module. I thought there was even a concept of a "bean archive" jar that other deployables can take advantage.

             

            Also, I'm a bit surprised that such an action is considered violating the visibility rules, since the classes are accessible.visible via jndi lookup and via Class.forName().  Unless I'm missing something, it seems like an inconsistency then that one can then currently do an @EJB("java:/global/my-ejb-jar.jar/SomeBean") but not do a simpler @Inject instead. The classes are clearly accessible from a jndi lookup perspective and and a Class.forName() perspective, but not accessible from a CDI @Inject perspective. From inside the war, I'm even able to use the BeanManager instance from the dependent jar to do getBeans() on beans from the dependent jar to get at a jar bean, but not with @Inject.

             

            Assuming there is no such solution, might it be possible to roll my own solution using a CDI hook/extension? If I am able to hook into the CDI bean resolution logic in the front-end war (I haven't studied if/how this can be done), then I would be able to lookup across the module using the technique that I have working described above where I have a bridge into the dependent jar exposing that deployable's BeanManager.

             

            ~Tom

            • 3. Re: Inter-module injection - the easy way (or even any way or alternative approaches)?
              Nicklas Karlsson Master

              I sounds a bit strange that a BeanManager would resolve beans that can't be used for injection.

              I'm not sure if an extension can hook into the visibility rules but if you don't mind getting your hands dirty, I'm sure you can modify Weld code and have your own version for development. Of course, you might get some surprises later on in production when switching to vanilla-Weld