JBoss.org Community Documentation
We will begin our tour of the EJB container by looking at the client view of an EJB through the home and remote proxies. It is the responsibility of the container provider to generate the javax.ejb.EJBHome
and javax.ejb.EJBObject
for an EJB implementation. A client never references an EJB bean instance directly, but rather references the EJBHome
which implements the bean home interface, and the EJBObject
which implements the bean remote interface. Figure 11.1, “The composition of an EJBHome proxy in JBoss.” shows the composition of an EJB home proxy and its relation to the EJB deployment.
The numbered items in the figure are:
The EJBDeployer (org.jboss.ejb.EJBDeployer
) is invoked to deploy an EJB JAR. An EJBModule
(org.jboss.ejb.EJBModule
) is created to encapsulate the deployment metadata.
The create phase of the EJBModule
life cycle creates an EJBProxyFactory
(org.jboss.ejb.EJBProxyFactory
) that manages the creation of EJB home and remote interface proxies based on the EJBModule
invoker-proxy-bindings
metadata. There can be multiple proxy factories associated with an EJB and we will look at how this is defined shortly.
The ProxyFactory
constructs the logical proxies and binds the homes into JNDI. A logical proxy is composed of a dynamic Proxy
(java.lang.reflect.Proxy
), the home interfaces of the EJB that the proxy exposes, the ProxyHandler
(java.lang.reflect.InvocationHandler
) implementation in the form of the ClientContainer
(org.jboss.proxy.ClientContainer
), and the client side interceptors.
The proxy created by the EJBProxyFactory
is a standard dynamic proxy. It is a serializable object that proxies the EJB home and remote interfaces as defined in the EJBModule
metadata. The proxy translates requests made through the strongly typed EJB interfaces into a detyped invocation using the ClientContainer
handler associated with the proxy. It is the dynamic proxy instance that is bound into JNDI as the EJB home interface that clients lookup. When a client does a lookup of an EJB home, the home proxy is transported into the client VM along with the ClientContainer
and its interceptors. The use of dynamic proxies avoids the EJB specific compilation step required by many other EJB containers.
The EJB home interface is declared in the ejb-jar.xml descriptor and available from the EJBModule metadata. A key property of dynamic proxies is that they are seen to implement the interfaces they expose. This is true in the sense of Java's strong type system. A proxy can be cast to any of the home interfaces and reflection on the proxy provides the full details of the interfaces it proxies.
The proxy delegates calls made through any of its interfaces to the ClientContainer
handler. The single method required of the handler is: public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
. The EJBProxyFactory
creates a ClientContainer
and assigns this as the ProxyHandler
. The ClientContainer
's state consists of an InvocationContext
(org.jboss.invocation.InvocationContext
) and a chain of interceptors (org.jboss.proxy.Interceptor
). The InvocationContext
contains:
the JMX ObjectName
of the EJB container MBean the Proxy
is associated with
the javax.ejb.EJBMetaData
for the EJB
the JNDI name of the EJB home interface
the transport specific invoker (org.jboss.invocation.Invoker
)
The interceptor chain consists of the functional units that make up the EJB home or remote interface behavior. This is a configurable aspect of an EJB as we will see when we discuss the jboss.xml
descriptor, and the interceptor makeup is contained in the EJBModule
metadata. Interceptors (org.jboss.proxy.Interceptor
) handle the different EJB types, security, transactions and transport. You can add your own interceptors as well.
The transport specific invoker associated with the proxy has an association to the server side detached invoker that handles the transport details of the EJB method invocation. The detached invoker is a JBoss server side component.
The configuration of the client side interceptors is done using the jboss.xml
client-interceptors
element. When the ClientContainer
invoke method is called it creates an untyped Invocation
(org.jboss.invocation.Invocation
) to encapsulate request. This is then passed through the interceptor chain. The last interceptor in the chain will be the transport handler that knows how to send the request to the server and obtain the reply, taking care of the transport specific details.
As an example of the client interceptor configuration usage, consider the default stateless session bean configuration found in the server/default/standardjboss.xml
descriptor. Example 11.1, “The client-interceptors from the Standard Stateless SessionBean configuration.” shows the stateless-rmi-invoker
client interceptors configuration referenced by the Standard Stateless SessionBean.
<invoker-proxy-binding> <name>stateless-rmi-invoker</name> <invoker-mbean>jboss:service=invoker,type=jrmp</invoker-mbean> <proxy-factory>org.jboss.proxy.ejb.ProxyFactory</proxy-factory> <proxy-factory-config> <client-interceptors> <home> <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor> <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor> <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor> <interceptor call-by-value="false"> org.jboss.invocation.InvokerInterceptor </interceptor> <interceptor call-by-value="true"> org.jboss.invocation.MarshallingInvokerInterceptor </interceptor> </home> <bean> <interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor> <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor> <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor> <interceptor call-by-value="false"> org.jboss.invocation.InvokerInterceptor </interceptor> <interceptor call-by-value="true"> org.jboss.invocation.MarshallingInvokerInterceptor </interceptor> </bean> </client-interceptors> </proxy-factory-config> </invoker-proxy-binding>
<container-configuration> <container-name>Standard Stateless SessionBean</container-name> <call-logging>false</call-logging> <invoker-proxy-binding-name>stateless-rmi-invoker</invoker-proxy-binding-name> <!-- ... --> </container-configuration>
Example 11.1. The client-interceptors from the Standard Stateless SessionBean configuration.
This is the client interceptor configuration for stateless session beans that is used in the absence of an EJB JAR META-INF/jboss.xml
configuration that overrides these settings. The functionality provided by each client interceptor is:
org.jboss.proxy.ejb.HomeInterceptor
: handles the getHomeHandle
, getEJBMetaData
, and remove methods of the EJBHome
interface locally in the client VM. Any other methods are propagated to the next interceptor.
org.jboss.proxy.ejb.StatelessSessionInterceptor
: handles the toString
, equals
, hashCode
, getHandle
, getEJBHome
and isIdentical
methods of the EJBObject
interface locally in the client VM. Any other methods are propagated to the next interceptor.
org.jboss.proxy.SecurityInterceptor : associates the current security context with the method invocation for use by other interceptors or the server.
org.jboss.proxy.TransactionInterceptor : associates any active transaction with the invocation method invocation for use by other interceptors.
org.jboss.invocation.InvokerInterceptor
: encapsulates the dispatch of the method invocation to the transport specific invoker. It knows if the client is executing in the same VM as the server and will optimally route the invocation to a reference invoker in this situation. When the client is external to the server VM, this interceptor delegates the invocation to the transport invoker associated with the invocation context. In the case of the Example 11.1, “The client-interceptors from the Standard Stateless SessionBean configuration.” configuration, this would be the invoker stub associated with the jboss:service=invoker,type=jrmp
, the JRMPInvoker
service.
org.jboss.invocation.MarshallingInvokerInterceptor
: extends the InvokerInterceptor
to not optimize in-VM invocations. This is used to force call-by-value
semantics for method calls.