Sping as a container, with its affairs, ORM and JDBC access to these areas to support rich functionality, Spring really is the better choice.
[Keywords] J2EEJavaEJB container access
As a lightweight container, Spring is often considered a substitute for EJB.We also believe that, for many (not necessarily most) applications and use cases, as opposed to through the EJB container to achieve the same functionality in terms of, Sping as a container, with its affairs, ORM and JDBC access to these areas of richfunctional support, Spring really is the better choice.
However, special attention is to use the Spring EJB does not mean we can not be used, in fact, Spring greatly simplifies the EJB components from which to access and to achieve or implement only (EJB components) of their functional complexity.In addition, if accessed through the Spring EJB Component Services, then went to a local EJB, remote EJB, or POJO (simple Java objects) of these variants to switch transparently between the service implementation, without modifyingclient-side code.
This chapter, we take a look at how Spring helps us to access and implement EJB components.Particularly in access to stateless Session Bean (SLSBs) time, Spring is particularly useful, so we'll start the discussion.
Access to EJB 1.1. The concept to call a local or remote Stateless Session Bean on the way, usually the client JNDI lookup code must be obtained (local or remote) EJB Home object, then call the object's "create" method canget real (local or remote) EJB object.Before and after the call more than one method on the EJB component.
To avoid repeated low-level calls, many EJB applications use a service locator (Service Locator) and the business delegate (Bussiness Delegate) mode so than in the client code for JNDI lookup better everywhere, but their common implementationsobvious defects.For example:
Usually, if dependent on the Service Locator or Business Delegate singletons to use EJB, it is difficult to test the code.
In only the Service Locator pattern instead of using the business case commissioned by mode, the application code still needs to call the create method of EJB Home components, or introduced to deal with this exception.Lead to code still retains the coupling of EJB API and the complexity of the EJB programming model.
Implementing the Business Delegate pattern typically results in a lot of redundant code, because we have to write a lot of ways, and they did just call the EJB components with the same name.
Spring approach is to allow the creation and use of proxy objects, generally in the Spring ApplicationContext or BeanFactory configured inside, and business agents so similar, only a small amount of code.We no longer need to write another Service Locator, or an additional code for JNDI lookup, or handwritten Business Delegate method of redundancy, unless they can bring substantial benefits.
1.2. Accessing local state Session Bean (SLSB)
Suppose there is a web controller to use the local EJB component.We follow the practice of previous experience, so use the EJB's business method interface (Business Methods Interface) mode, so that the EJB component to extend the non-local interface EJB-specific business methods interface.Let us assume that this business methods interface is called MyComponent.
public interface MyComponent {... ...
} (Using the Business Methods Interface pattern is to ensure that a major cause of the local interface and bean implementation class synchronization between the method signature is automatic. Another reason is that it allows us to switch later on POJO (simple Java objects)service implementation easier, as long as this change is beneficial. Of course, we also need to implement the local Home interface, and provide a Bean implementation class, it implements the interface SessionBean and business methods interface MyComponent. Now, in order to control our Web tierand link the EJB implementation, the only thing we write Java code that is posted on the controller as a parameter MyComponent the setter method. so that you can save this reference to an instance of the controller variable.
private MyComponent myComponent;
public void setMyComponent (MyComponent myComponent) {
this.myComponent = myComponent;
}
Then we can any business method in the controller use this instance variable.Suppose we are from the Spring ApplicationContext or BeanFactory access to the controller object, we can configure in the same context, a LocalStatelessSessionProxyFactoryBean instance, will serve as the EJB component proxy object.The proxy object attributes configuration and control settings myComponent is to use a configuration item complete, as follows:
class = "org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
myComponent
com.mycom.MyComponent
These seemingly simple code behind a lot of complex processing, such as the silent work of the Spring AOP framework, we do not even have to know these concepts, the results can still enjoy it.Bean myComponent definition creates a proxy object of the EJB component, which implements the business method interface.The EJB Home object component of the local start when he was placed in the cache, we only need to perform a JNDI lookup.Every EJB component is called, the proxy object to call the local EJB component's create method, and call the EJB component's corresponding business methods.
The definition of the Bean myController, the controller class myController the value of the property is set to the above proxy object.
This approach greatly simplifies the EJB components to access the application code: Web layer (or other EJB client) code is no longer dependent on the use of EJB components.If we want to replace this EJB reference to a POJO, or a simulated test with the object or other component, we simply need to modify the definition of Bean myComponent only line of Java code, in addition, we no longer need to applyJNDI lookup in writing any program or other EJB-related code.
Evaluation and practical application experience has shown that the performance of the load in this way is very small (although using the reflection method to call the target EJB component's method), we usually use almost undetectable.Please remember that we do not want to frequently call the underlying EJB component method, but despite this, some performance cost is the basis for EJB application server framework related.
JNDI lookup on a little note.In Bean container, this class is usually best used as a single piece (no reason to make a prototype).However, if the Bean container pre-instantiates singleton (like XML ApplicationContext variants of the behavior), if the target EJB in the EJB container is loaded before loading bean container, we may encounter problems.Because the JNDI lookup in the class init method is executed and cached results, thus leading to the EJB can not be bound to the target location.The solution is not pre-instantiate this factory object, and allow it to be used when the first re-created in the XML container, which is through the attribute lazy-init to control.
Although most users of Spring will not interest, but those on the concrete application of AOP EJB to the user would like to see LocalSlsbInvokerInterceptor.
1.3. Access to remote stateless Session Bean (SLSB)
Basically, remote access and access to local EJB EJB little difference, except the former uses SimpleRemoteStatelessSessionProxyFactoryBean. Of course, whether or not to use Spring, the semantics of remote calls are the same, but for the use of scenarios and error handling, the call to another onedifferent virtual machines on the computer object in the method of their processing is different.
Spring does not use the way with clients compared to EJB, Spring's EJB client has an additional benefit.Usually if the client code is free to the local and remote EJB EJB switch back and forth between calls, there is a problem.This is because the remote interface methods must declare that it throws RemoteException, then the client code must deal with this exception, but the local interface methods do not.If you want change for the local EJB code to access a remote EJB, you need to modify the client code, to increase the handling RemoteException, otherwise you need to remove that exception handling.Using the Spring remote EJB proxy, we no longer need the interface and the EJB business methods declared in the code throws RemoteException, but a similar definition of remote interfaces, the only difference is that it throws the RemoteAccessException, and then submitted toto the proxy to dynamically treat the two interfaces.In other words, the client code that no longer need to explicitly RemoteException (checked) exception to deal with the actual operation of all exceptions thrown RemoteException will be captured and converted into an implicit (non-checked) the RemoteAccessException, it is the RuntimeExceptiona sub-class.This target server to connect the local EJB or remote EJB (or POJO) to switch freely between the client no longer need to worry about would not even aware of this switch.Of course, these are optional, we do not stop the business interface declared in the exception RemoteExceptions.
2. Using Spring implementation classes provided by Spring EJB component also provides some helper classes to facilitate the implementation of EJB components.They are designed to encourage good practice, such as on the business logic POJO in EJB layer to achieve after, only the transaction isolation, and remote call these responsibilities left to EJB.
To achieve a stateless or stateful Session Bean, or Message Driven Bean, our implementation can be inherited separately inherited AbstractStatelessSessionBean, AbstractStatefulSessionBean, and AbstractMessageDrivenBean / AbstractJmsMessageDrivenBean
Consider this example: We stateless Session Bean implementation services entrusted to the ordinary Java objects.Service interface is defined as follows:
public interface MyComponent {
public void myMethod (...);
...
}
This is a simple way to achieve the class of Java objects:
public class MyComponentImpl implements MyComponent {
public String myMethod (...) {
...
}
...
}
Finally, stateless Session Bean itself:
public class MyComponentEJB implements extends AbstractStatelessSessionBean
implements MyComponent {
MyComponent _myComp;
/ **
* Obtain our POJO service object from the BeanFactory / ApplicationContext
* @ See org.springframework.ejb.support.AbstractStatelessSessionBean # onEjbCreate ()
* /
protected void onEjbCreate () throws CreateException {
_myComp = (MyComponent) getBeanFactory (). getBean (
ServicesConstants.CONTEXT_MYCOMP_ID);
}
/ / For business method, delegate to POJO service impl.
public String myMethod (...) {
return _myComp.myMethod (...);
}
...
}
Spring EJB support provided by the base class by default create and load a BeanFactory (in this case, it is the ApplicationContext subclass) as part of their life cycle for EJB to use (like the above code asused to obtain the POJO service object).Loading is done via a strategy object, which is a subclass of BeanFactoryLocator.By default, the actual use of the BeanFactoryLocator the implementation class is ContextJndiBeanFactoryLocator, it is based on a JNDI environment variable to create an ApplicationContext object (EJB classes here, the path is java: comp / env / ejb / BeanFactoryPath).If you need to change the BeanFactory or ApplicationContext loading strategy, we can re-define the subclass of setSessionContext () method or the specific sub-class constructor EJB call setBeanFactoryLocator () method to change the default implementation class BeanFactoryLocator used.Details, refer to JavaDoc.
As described in JavaDoc, stateful Session Bean in its life cycle may be passivated and reactivated, if it is not serializable BeanFactory or ApplicationContext, EJB container because they will not be saved, so the need to manually ejbPassivate andThese two methods were ejbActivate call unloadBeanFactory () and loadBeanFactory, passive or active only when the unloaded or loaded.
In some cases, to load ApplicationContext to use EJB components, ContextJndiBeanFactoryLocator the default implementation is basically adequate, but, when the ApplicationContext is loading a number of bean, or the bean initialization time or memory required a lot of time (For example, the initialization of Hibernate SessionFactory), it is possible to go wrong, because each has its own copy of the EJB component.In this case, the user may want to override the default implementation ContextJndiBeanFactoryLocator and use the other variant BeanFactoryLocator, such ContextSingleton or BeanFactoryLocator, they can load and share a BeanFactory or ApplicationContext to the number of EJB components, or other clientpublic.This is quite simple, just give EJB is similar to the following code to add:
/ **
* Override default BeanFactoryLocator implementation
*
* @ See javax.ejb.SessionBean # setSessionContext (javax.ejb.SessionContext)
* /
public void setSessionContext (SessionContext sessionContext) {
super.setSessionContext (sessionContext);
setBeanFactoryLocator (ContextSingletonBeanFactoryLocator.getInstance ());
setBeanFactoryLocatorKey (ServicesConstants.PRIMARY_CONTEXT_ID);
}