The EJB Client-Side View


Let's 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; rather, it references EJBHome, which implements the bean home interface, and EJBObject, which implements the bean remote interface. Figure 5.1 shows the composition of an EJB home proxy and its relationship to the EJB deployment.

Figure 5.1. The composition of an EJBHome proxy in JBoss.


The numbered items in Figure 5.1 are as follows:

  1. 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.

  2. 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 they EJBModule invoker-proxy-bindings metadata. There can be multiple proxy factories associated with an EJB, and we will look at this more closely shortly.

  3. 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.

  4. 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. The dynamic proxy instance is bound into JNDI as the EJB home interface that clients look up. 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. Using dynamic proxies avoids the EJB-specific compilation step required by many other EJB containers.

  5. The EJB home interface is declared in the ejb-jar.xml descriptor and is available from the EJBModule metadata. A key property of dynamic proxies is that they implement the interfaces they expose. This is true in the sense of Java's strong typing 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.

  6. 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 following:

    • The JMX ObjectName of the EJB container MBean that 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. As discussed later in this chapter, this is a configurable aspect of an EJB, 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.

  7. 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.

You configure the client-side interceptors by 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 is 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 that is found in the server/default/standardjboss.xml descriptor. Listing 5.1 shows the stateless-rmi-invoker client interceptor configuration, referenced by the Standard Stateless SessionBean.

Listing 5.1. The Client Interceptors from the Standard Stateless SessionBean Configuration

[View full width]

<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>

Listing 5.1 shows 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 client interceptors provide the following functionality:

  • org.jboss.proxy.ejb.HomeInterceptor This interceptor 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 This interceptor 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 This interceptor associates the current security context with the method invocation for use by other interceptors or the server.

  • org.jboss.proxy.TransactionInterceptor This interceptor associates any active transaction with the invocation method invocation for use by other interceptors.

  • org.jboss.invocation.InvokerInterceptor This interceptor encapsulates the dispatch of the method invocation to the transport-specific invoker. It knows whether the client is executing in the same VM as the server, and it optimally routes the invocation to a by-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 configuration in Listing 5.1, this would be the invoker stub associated with the jboss:service=invoker,type=jrmp, which is the JRMPInvoker service.

  • org.jboss.invocation.MarshallingInvokerInterceptor This interceptor extends the InvokerInterceptor to not optimize in VM invocations. This is used to force call-by-value semantics for method calls.

Specifying the EJB Proxy Configuration

To specify the EJB invocation transport and the client proxy interceptor stack, you need to define an invoker-proxy-binding in either the EJB JAR META-INF/jboss.xml descriptor or the server standardjboss.xml descriptor. There are several default invoker-proxybinding elements defined in the standardjboss.xml descriptor for the various default EJB container configurations and the standard RMI/JRMP and RMI/IIOP transport protocols. The current default proxy configurations are as follows:

  • entity-rmi-invoker This is an RMI/JRMP configuration for entity beans.

  • clustered-entity-rmi-invoker This is an RMI/JRMP configuration for clustered entity beans.

  • stateless-rmi-invoker This is an RMI/JRMP configuration for stateless session beans.

  • clustered-stateless-rmi-invoker This is an RMI/JRMP configuration for clustered stateless session beans.

  • stateful-rmi-invoker This is an RMI/JRMP configuration for stateful session beans.

  • clustered-stateful-rmi-invoker This is an RMI/JRMP configuration for clustered stateful session beans.

  • message-driven-bean This is a JMS invoker for message-driven beans.

  • singleton-message-driven-bean This is a JMS invoker for singleton message-driven beans.

  • message-inflow-driven-bean This is a JMS invoker for message inflow-driven beans.

  • jms-message-inflow-driven-bean This is a JMS inflow invoker for standard message-driven beans.

  • iiop This is an RMI/IIOP for use with session and entity beans.

Introducing a new protocol binding, customizing the proxy factory, or customizing the client-side interceptor stack requires defining a new invoker-proxy-binding. The full invoker-proxy-binding DTD fragment for the specification of the proxy configuration is shown in Figure 5.2.

Figure 5.2. The invoker-proxy-binding schema.


These are the invoker-proxy-binding child elements:

  • name The name element gives a unique name for the invoker-proxy-binding. The name is used to reference the binding from the EJB container configuration when setting the default proxy binding as well as the EJB deployment level to specify additional proxy bindings. You will see how this is done later in this chapter, when we look at the jboss.xml elements that control the server-side EJB container configuration.

  • invoker-mbean The invoker-mbean element gives the JMX ObjectName string of the detached invoker MBean service that the proxy invoker will be associated with.

  • proxy-factory The proxy-factory element specifies the fully qualified classname of the proxy factory that must implement the org.jboss.ejb.EJBProxyFactory interface. The EJBProxyFactory handles the configuration of the proxy and the association of the protocol-specific invoker and context. The current JBoss implementations of the EJBProxyFactory interface include the following:

    • org.jboss.proxy.ejb.ProxyFactory The RMI/JRMP-specific factory.

    • org.jboss.proxy.ejb.ProxyFactoryHA The cluster RMI/JRMP-specific factory.

    • org.jboss.ejb.plugins.jms.JMSContainerInvoker The JMS-specific factory.

    • org.jboss.proxy.ejb.IORFactory The RMI/IIOP-specific factory.

  • proxy-factory-config The proxy-factory-config element specifies additional information for the proxy-factory implementation. Unfortunately, it is currently an unstructured collection of elements. Only a few of the elements apply to each type of proxy factory. The child elements break down into the three invocation protocols: RMI/RJMP, RMI/IIOP, and JMS.

For the RMI/JRMP-specific proxy factories org.jboss.proxy.ejb.ProxyFactory and org.jboss.proxy.ejb.ProxyFactoryHA, the following elements apply:

  • client-interceptors client-interceptors defines the home, remote, and, optionally, the multivalued proxy interceptor stacks.

  • web-class-loader web-class-loader defines the instance of the org.jboss.web.WebClassLoader that should be associated with the proxy for dynamic class loading.

The following proxy-factory-config is for an entity bean accessed over RMI:

[View full width]

<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.EntityInterceptor</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> <list-entity> <interceptor>org.jboss.proxy.ejb.ListEntityInterceptor</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> </list-entity> </client-interceptors> </proxy-factory-config>

For the RMI/IIOP-specific proxy factory org.jboss.proxy.ejb.IORFactory, the following elements apply:

  • poa This specifies the portable object adapter usage. Valid values are per-servant and shared.

  • register-ejbs-in -jnp-context This specifies a flag which indicates whether the EJBs should be registered in JNDI.

  • jnp-context This specifies the JNDI context in which to register EJBs.

  • web-class-loader This defines the instance of the org.jboss.web.WebClassLoader that should be associated with the proxy for dynamic class loading.

The following is a proxy-factory-config for EJBs accessed over IIOP:

 <proxy-factory-config>     <web-class-loader>org.jboss.iiop.WebCL</web-class-loader>     <poa>per-servant</poa>     <register-ejbs-in-jnp-context>true</register-ejbs-in-jnp-context>     <jnp-context>iiop</jnp-context> </proxy-factory-config> 

For the JMS-specific proxy factory org.jboss.ejb.plugins.jms.JMSContainerInvoker, the following elements apply:

  • MinimumSize This specifies the minimum pool size for MDB processing. The default is 1.

  • MaximumSize This specifies the upper limit to the number of concurrent MDBs that will be allowed for the JMS destination. The default is 15.

  • MaxMessages This specifies the maxMessages parameter value for the createConnectionConsumer method of the javax.jms.QueueConnection and javax.jms.TopicConnection interfaces, as well as the maxMessages parameter value for the createDurableConnectionConsumer method of javax.jms.TopicConnection. It is the maximum number of messages that can be assigned to a server session at one time. The default is 1. You should not modify this value from the default unless your JMS provider indicates that doing so is supported.

  • KeepAliveMillis This specifies the keep-alive time interval, in milliseconds, for sessions in the session pool. The default is 30000 (30 seconds).

  • MDBConfig This specifies the configuration for the MDB JMS connection behavior. Among the elements supported are the following:

    • ReconnectIntervalSec The time to wait (in seconds) before trying to recover the connection to the JMS server.

    • DeliveryActive Whether the MDB is active at startup. The default is true.

    • DLQConfig Configuration for an MDB's dead-letter queue, which is used when messages are redelivered too many times.

    • JMSProviderAdapterJNDI The JNDI name of the JMS provider adapter in the java:/ namespace. This is mandatory for an MDB and must implement org.jboss.jms.jndi.JMSProviderAdapter.

    • ServerSessionPoolFactoryJNDI The JNDI name of the session pool in the java:/ namespace of the JMS provider's session pool factory. This is mandatory for an MDB and must implement org.jboss.jms.asf.ServerSessionPoolFactory.

Listing 5.2 gives a sample proxy-factory-config fragment taken from the standardjboss.xml descriptor.

Listing 5.2. A Sample JMSContainerInvoker proxy-factory-config
 <proxy-factory-config>     <JMSProviderAdapterJNDI>DefaultJMSProvider</JMSProviderAdapterJNDI>     <ServerSessionPoolFactoryJNDI>StdJMSPool</ServerSessionPoolFactoryJNDI>     <MinimumSize>1</MinimumSize>     <MaximumSize>15</MaximumSize>     <KeepAliveMillis>30000</KeepAliveMillis>     <MaxMessages>1</MaxMessages>     <MDBConfig>         <ReconnectIntervalSec>10</ReconnectIntervalSec>         <DLQConfig>             <DestinationQueue>queue/DLQ</DestinationQueue>             <MaxTimesRedelivered>10</MaxTimesRedelivered>             <TimeToLive>0</TimeToLive>         </DLQConfig>     </MDBConfig> </proxy-factory-config> 



JBoss 4. 0(c) The Official Guide
JBoss 4.0 - The Official Guide
ISBN: B003D7JU58
EAN: N/A
Year: 2006
Pages: 137

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net