2 Replies Latest reply on Apr 29, 2009 5:45 AM by pgmjsd

    EJB lifecycle methods & injection

    jlemire

      Environment: JBossAS 5.0.0GA, Seam 2.1.1GA


      I am currently converting some POJO seam components to EJBs. I added the necessary annotations and took care of the additional EJB restrictions due to passivation/activation and concurrent access. I also decided to use @PostConstruct instead of @Create, as I didn't want to mix-up the seam and ejb component lifecycles more than necessary. Both @Create and @Destroy are commented like so:


      * Alternative to javax.annotations.PreDestroy for use in a pre Java EE 5 environment.
      



      Which seams to imply they are interchangeable and that I can code my components pretty much like a regular ejb and still have access to the seam magic such as bijection.


      I am now quite surprised to find out that none of the EJB callbacks have access to injected components, not even @PostConstruct and @PreDestroy.


      Maybe this is the intended behaviour, and then the @Create and @Destroy comments should be fixed. However, if it is technically feasible at all to have the interceptors intercepting the lifecycle methods, I think it should be done. Having access to some members and not others depending on what method is being called is clunky.


      If it is not feasible, @Create and @Destroy could be the way to go, but seam does not define hooks for activation and passivation... which means I will have to init transient fields differently depending if it is a new instance or a newly deserialized one...

        • 1. Re: EJB lifecycle methods & injection
          gonorrhea

          You have brought up a very interesting point.


          Bijection and EJB lifecycle callback methods interoperability.


          Here's my test SFSB:


          @Name("testInjectCreate")
          @Stateful
          public class TestInjectCreateAction implements TestInjectCreateLocal {
               
               @Logger 
               private Log log;
               
               @In(required=false, scope=ScopeType.SESSION)
               private String domainAndUsername;
               
               @In(required=false, scope=ScopeType.SESSION)
               private ApplicationUser applicationUser;
               
               @Remove @Destroy
               public void destroy(){}
               
               @PostConstruct
               public void init(){
                    log.info("begin init()!");
                    if (domainAndUsername != null)
                         log.info("domainAndUsername = "+domainAndUsername);
                    if (applicationUser != null)
                         log.info("applicationUser.getUserName() = "+applicationUser.getUserName());
               }
               
               public void submit(){
                    log.info("submitted!");
                    
                    if (domainAndUsername != null)
                         log.info("domainAndUsername = "+domainAndUsername);
                    if (applicationUser != null)
                         log.info("applicationUser.getUserName() = "+applicationUser.getUserName());
               }
          
          }



          Here is the output when submit() is invoked from JSF HtmlCommandButton:


          13:34:56,204 INFO  [TestInjectCreateAction] begin init()!
          13:34:56,220 INFO  [ProfilingInterceptor] *** Entering method: submit
          13:34:56,220 INFO  [TestInjectCreateAction] submitted!
          13:34:56,220 INFO  [TestInjectCreateAction] domainAndUsername = CORP\asookazi
          13:34:56,220 INFO  [TestInjectCreateAction] applicationUser.getUserName() = corp\asookazi
          13:34:56,220 INFO  [ProfilingInterceptor] *** Method public void com.cox.bets.session.TestInjectCreateAction.submit() executed in 0ms ***
          13:34:56,548 INFO  [ProfilingInterceptor] *** Entering method: destroy
          13:34:56,548 INFO  [ProfilingInterceptor] *** Method public void com.cox.bets.session.TestInjectCreateAction.destroy() executed in 0ms ***



          This exercise proves the fact that DI in Seam occurs after the @PostConstruct method has finished executing.  It would be nice if DI occurred prior to the @PostConstruct method but not sure if that's technically feasible (I'm pretty sure it's not b/c my custom ProfilingInterceptor did not output to the server.log for the init() method).


          Another limitation is outjection only occurs after the business method has successfully completed execution (i.e. if an exception like NPE, for example, is thrown during processing, outjection does not occur).


          So the question is, how will this all be handled in Seam 3 and/or JSR299 (JCDI)?

          • 2. Re: EJB lifecycle methods & injection
            pgmjsd

            Right, as long as Seam integrates using an interceptor the DI isn't going to happen until the object is fully constructed.   Is that really a problem?