1 Reply Latest reply on Apr 15, 2008 4:36 PM by Clint Popetz

    Multiple EARs, cross-ear ejb invocation, wrong jsf el resolver

    Clint Popetz Apprentice

      I have an EAR with a SLSB that is also a seam component, and that uses injection.  Specifically, it uses injection of a component that is declared as an EL value expression factory.  So, for example:


      @Local
      public interface Authenticator { 
      
         public boolean authenticate(String user, String password);
      
      }
      



      and its implementation:


      @Name("authenticator")
      @Stateless
      public class AuthenticatorBean implements Authenticator {
           
           @In AnotherClass dependent;
       ...
      }
      
      



      and in components.xml:


      <factory name="dependent" 
               scope="stateless" auto-create="true"   
               value="#{someBean.someValueExpression}"/>
      



      Now let's say we have another EAR that has a seam component that does this in response to a jsf request:


      //this is mapped in the second EAR's components.xml to
      //find the Authenticator in the first EAR via JNDI.
      @In Authenticator authenticator;  
      authenticator.authenticate("foo","bar");
      
      



      Now if I'm very careful to ensure that only one copy of the ExternalAuthenticator class lives in jboss, this will work...almost.


      The call successfully makes it to the first deployment, and beginCall() sets up the contexts correctly, and the ejb method is invoked.  However, when AuthenticatorBean needs to be injected with the value expression, the resolution process will find the EL resolver from the calling deployment, because FacesExpressions uses FacesContext.getCurrentInstance(), which will happily return the current thread-local faces context from the jsf request that started this.


      That's obviously not correct.  There are a couple possibilities I see:




      • Move the JSF faces libs out of jboss-web.deployer into each ear's war's WEB-INF/lib.  That way we'll use a different ThreadLocal to find the FacesContext.  But, well, yuck.




      • Have Lifecycle.beginCall() communicate to FacesExpressions that it should not check FacesContext, but should instead default to the ELContext that org.jboss.seam.el creates for the cases where jsf isn't active. 




      • Have Expressions.instance() not look specifically in the APPLICATION scope.  Then have Lifecycle.beginCall() put an instance of Expressions (and not FacesExpressions) in one of the temporary/shorter scopes it creates, which will be found  before the FacesExpressions that is found in APPLICATION scope.  This avoids any cleanup and re-entrancy issues.  It does however make Expressions.instance() a little slower.




      I'm happy to implement either of the latter two options, if either is appropriate.


      Thanks,
      -Clint