EJBTHREE-2198 EJB resource providers for switchboard and the dependency issues
jaikiran Nov 19, 2010 2:38 AMHere's a quick overview of what the @EJB, ejb-ref, ejb-local-ref resource provider is expected to do. More details about what a ResourceProvider is and what role it plays can be found in this wiki http://community.jboss.org/wiki/Switchboard
Goal:
Consider this @EJB reference (in a servlet, for example):
public class MyServlet { @EJB private MyBeanIntf bean; }
And then consider this EJB:
@Stateless public class MySLSB implements MyBeanIntf { ... }
So ultimately, when the web application is being deployed, the servlet container shouldn't "start" unless the Resource (check the above wiki for what it means) corresponding to:
@EJB private MyBeanIntf bean;
is made available in the ENC (java:comp/env) of the servlet.
EJB container implementation details:
The JBoss EJB3 container in AS6 is a MC bean. When the JBoss EJB3 container finds a EJB (MySLSB in this case), among various other things, it binds the proxies to (JBoss specific) jndi names during its "start" (MC) lifecycle method. This has been legacy since AS5.
Starting AS6 when we started supporting EJB3.1, we also bind the EJB proxies to a spec compliant JNDI name (along with the JBoss specific jndi names). The binding to EJB3.1 compliant JNDI names is done by the EJBBinder https://github.com/jbossejb3/jboss-ejb3-jndi/blob/master/binder/src/main/java/org/jboss/ejb3/jndi/binder/EJBBinder.java and has no interaction with the EJB containers. i.e. binding to EJB3.1 spec compliant jndi names is (intentionally) completely decoupled from EJB containers. The EJBBinder is deployed as a MC bean by the EJBBinderDeployer https://github.com/jbossejb3/jboss-ejb3-jndi/blob/master/deployers/src/main/java/org/jboss/ejb3/jndi/deployers/EJBBinderDeployer.java, so that the binding happens during the "start" lifecycle of that MC bean (when any necessary dependencies on the EJBBinder are satisfied)
Currently in AS6, we bind the EJB3.1 jndi names as LinkRefs to jboss specific jndi names. So the EJBBinder creates and returns a LinkRef to the JBoss specific jndi name which will be created by the JBoss EJB3 containers.
The ResourceProvider details and the problem:
The ResourceProvider for @EJB, ejb-local-ref and ejb-ref is responsible for resolving the MC bean name of the EJBBinder from a ejb-ref, ejb-local-ref and @EJB. How the resolution is done is currently not relevant for this discussion. Let's just assume that we somehow manage to resolve it to a EJBBinder. The ResourceProvider then return this EJBBinder back to switchboard which converts this to a MC dependency. i.e. SwitchBoard adds a dependency on the servlet container for this EJBBinder MC bean to be installed before the servlet container can make available the servlet. Ideally, this should all work out, but there's a minor little detail in this implementation which causes it to fail. Let's see why:
1) Web container (through SwitchBoard and RPs) adds a dependency on the EJBBinder responsible for setting up EJB3.1 spec compliant java:global jndi name of MySLSB
2) EJBBinder is added as a MC bean
3) EJBContainer corresponding to MyBean is added as a MC bean
4) MC starts installing MC beans. Let's assume it picks up EJBBinder first. EJBBinder "starts" and binds to java:global a LinkRef
5) MC sees that the EJBBinder dependency for web container is now satisfied and triggers the web container startup
6) Web container starts initialzing instances (like load-on-startup servlets, filters etc...)
7) While injecting from ENC to filter/servlet, container runs into error because the EJBContainer (#3) which is responsible for setting up the JBoss specific JNDI names, which are the target of the LinkRef created in #4, hasn't yet been triggered for "start" by MC.
Solution:
For AS6 we somehow need to add a dependency on the EJBBinder such that it isn't installed until the JBoss specific jndi names aren't bound into JNDI. It isn't easy because the code responsible for deploying EJBBinder as a MC bean (i.e. EJBBinderDeployer) somehow needs to know what the JBoss specific JNDI names are for each of the exposed view of the bean.
Note that this may not be the only solution and there might be other ways to get past this. But the goal is to get this up and running as quickly as possible without having to change a lot of stuff.