7 Replies Latest reply on Jul 2, 2009 6:55 AM by robert.geisler

    circular references

    robert.geisler Newbie

      hallo everybody...

      i met some problems with circular ejb references and already read postings like

      • http://www.jboss.org/index.html?module=bb&op=viewtopic&t=149299,
      • http://www.jboss.org/index.html?module=bb&op=viewtopic&t=148042
      • and some others,that explain me what the problem is and how to solve it (@IgnoreDependency).

        but my problem still occurs, because jaikiran always told us to remove the class level @EJB annotation. but if i only use @EJB on field level, than the corresponding ejb will always get injected, no matter if i will use it later.
        but i would like to declare some references at class level and lookup later through local jndi (java:comp/env), just when i really need the corresponding ejb.

        but i cannot do that without class level annotations, right?
        so is there a solution to
        • ignore class level dependencies or
        • lazy inject field level dependencies?
          thanks in advance
          robert


        • 1. Re: circular references
          jaikiran pai Master

           

          but i cannot do that without class level annotations, right?


          As far as i know, it's not possible to do this at class level.

          so is there a solution to

          * ignore class level dependencies or
          * lazy inject field level dependencies ?


          Can you please provide a bit more details about the issue you are running into? Preferably with the relevant code and the logs.


          • 2. Re: circular references
            robert.geisler Newbie

            you are always very fast, jaikiran :)
            god bless you ; )


            "jaikiran" wrote:

            As far as i know, it's not possible to do this at class level.

            to do what at class level? to @IgnoreDependency?

            "jaikiran" wrote:

            Can you please provide a bit more details about the issue you are running into? Preferably with the relevant code and the logs.

            our problem is, that we do not want to use dependency injection on some stateless beans, because we want to lazy lookup a few ejbs just when we really use them. earlier we achieved that through private getters that looked up the ejbs by their local jndi name (@LocalBinding). but we cannot use this pattern anymore, because we want our .ear to be portable to WebSphereAS (WAS doesnt have such a thing like @LocalBinding, but requires a "ejblocal:/" prefix for local business interfaces).
            thats why we put class level @EJBs annotation on that stateless beans and use getters that lookup the ejbs by the logical name declared in @EJB.
            we thought this way we may avoid injection of ejbs that mostly never will get used. but when we now deploy our .ear on JBoss, JBoss complains about circular references (as we would use dependency injection).

            please have a look at the simplified code below.

            here is one statless bean that declares dependency on class level. it dont use injection, but lazy lookup the referenced ejb through getter-method.
            @Stateless(name = "StatlessOne")
            @Local(value = StatlessOne.class)
            @EJBs(value = { //
             @EJB(name = "StatlessTwo", beanName = "StatlessTwo", beanInterface = StatlessTwo.class)
            })
            public class StatlessOneBean implements StatlessOne {
             @Resource
             private SessionContext sessionContext;
            
             // lookup "on-demand"
             public StatlessTwo getStatlessTwo() {
             return (StatlessTwo) sessionContext.lookup("java:comp/env/" + "StatlessTwo";
             }
            
             ...
            
            }

            here is the corresponding ejb. the first ejb gets injected, beause the second one will always use the first ejb.
            @Stateless(name = "StatlessTwo")
            @Local(value = StatlessTwo.class)
            public class StatlessTwoBean implements StatlessTwo {
             @Resource
             private SessionContext sessionContext;
            
             @EJB(beanName = "StatlessOne") // lookup "always"
             private StatlessOne statlessOne;
            
             public boolean hasStatlessOne() {
             return (statlessOne != null);
             }
            
             ...
            
            }

            and thats the errors, JBoss loggs when we deploy our .ear:
            2009-06-29 13:23:15,054 INFO [org.jboss.ejb3.EJB3Deployer] Starting java:comp multiplexer
            ...
            // all ejbs got deployed without errors:
            INFO [org.jboss.ejb3.EJB3Deployer] Deployed: file:/...MyServer.ear-contents/StatelessOne.jar
            INFO [org.jboss.ejb3.EJB3Deployer] Deployed: file:/...MyServer.ear-contents/StatelessTwo.jar
            ...
            INFO [org.jboss.deployment.EARDeployer] Started J2EE application: file:/...MyServer.ear
            // AFTER deployment these erros are shown:
            ERROR [org.jboss.deployment.scanner.URLDeploymentScanner] Incomplete Deployment listing:
            
            --- MBeans waiting for other MBeans ---
            ObjectName: jboss.j2ee:ear=MyServer.ear,jar=StatelessTwo.jar,name=StatelessTwo,service=EJB3
             State: NOTYETINSTALLED
             I Depend On:
             jboss.j2ee:ear=AfpsServer.ear,jar=StatelessOne.jar,name=StatelessOne,service=EJB3
            
            ObjectName: jboss.j2ee:ear=MyServer.ear,jar=StatelessOne.jar,name=StatelessOne,service=EJB3
             State: NOTYETINSTALLED
             I Depend On:
             jboss.j2ee:ear=MyServer.ear,jar=StatelessTwo.jar,name=StatelessTwo,service=EJB3
            
            ...
            
            INFO [org.jboss.system.server.Server] JBoss (MX MicroKernel) [4.2.2.GA [...] Started [...]


            maybe i missunterstood the @EJB annotation at all?
            i thought, that
            • @EJB on class level just declares a dependency and the application server puts the corresponding ejb into the local jndi context, while
            • @EJB on field level injects an instance of the corresponding ejb into the fieldam i wrong?


              regards robert



              ps:
              its complicated for me to explain all these things in english.
              so i hope you will forgive me if i confuse you O: )


            • 3. Re: circular references
              jaikiran pai Master

               

              to do what at class level? to @IgnoreDependency ?


              Yes, i meant you can't have an @IgnoreDependency at class level.

              i thought, that

              * @EJB on class level just declares a dependency and the application server puts the corresponding ejb into the local jndi context, while
              * @EJB on field level injects an instance of the corresponding ejb into the field


              That's correct.

              [ Some internal details - A @EJB adds an internal MC dependency on the bean which is being added to the ENC of another bean or being injected in another bean]

              Wouldn't this work:
              ...
              public class StatlessTwoBean implements StatlessTwo
              {
              ...
              @EJB(beanName = "StatlessOne") // lookup "always"
              @IgnoreDependency
               private StatlessOne statlessOne;


              ps:
              its complicated for me to explain all these things in english.
              so i hope you will forgive me if i confuse you O: )


              No problem with the language :)


              • 4. Re: circular references
                robert.geisler Newbie

                 

                "jaikiran" wrote:

                That's correct.

                i'm glad ; )

                "jaikiran" wrote:

                Wouldn't this work:
                public class StatlessTwoBean implements StatlessTwo {
                 @EJB(beanName = "StatlessOne") // lookup "always"
                 @IgnoreDependency
                 private StatlessOne statlessOne;


                yes, your are right, that should work. yesterday i thought about the problem only from the StatelessOneBeans point of view... but the other way around it should just work : ) my fault O: )
                i will give it a try and let you know what happened.

                thank you very much for your help, jaikiran.
                regards
                robert

                • 5. Re: circular references
                  robert.geisler Newbie

                  (sorry for double posting, i cannot edit me previous post)

                  jaikiran, i have a last question...
                  @IgnoreDependency -what does it actually mean?

                  Ignore the dependency created by an injection annotation applied

                  sadly, that does not make it clear for me :- \
                  how could one explain it in a few words?

                  thanks again
                  robert

                  • 6. Re: circular references
                    jaikiran pai Master

                    Whenever a @EJB is used, we internally add a micro container dependency on the bean being injected. That way we ensure that the bean being injected is available before the bean which uses the @EJB. With @IgnoreDependency, you can override this behaviour so that the MC dependency is not created.

                    • 7. Re: circular references
                      robert.geisler Newbie

                      update:
                      we put @IgnoreDependency on one side of the circular dependency as shown above.
                      our .ear gets deployed successfully and we didnt recognize any runtime error yet.
                      we will have a look at it the next few days... but it seems to work : )

                      jaikiran, thank you very much for your first-aid ; )
                      and thanks for explanation, too.