Using Spring's EJB implementation support classes - Java-Springs

EJB 2.x base classes

Spring provides convenience classes to help you implement EJBs.These are designed to encourage the good practice of putting business logic behind EJBs in POJOs, leaving EJBs responsible for transaction demarcation and (optionally) remoting.

To implement a Stateless or Stateful session bean, or a Message Driven bean, you need only derive your implementation class from Abstract State less Session Bean, Abstract State ful Session Bean, and Abstract Message Driven Bean / Abstract Jms Message Driven Bean, respectively.

Consider an example Stateless Session bean which actually delegates the
implementation to a plain java service object. We have the business interface:

public interface MyComponent {
public void myMethod(...);
...
}

We also have the plain Java implementation object:

public class MyComponentImpl implements MyComponent {
public String myMethod(...) {
...
}
...
}

And finally the Stateless Session Bean itself:

public class MyFacadeEJB extends AbstractStatelessSessionBean
implements MyFacadeLocal {
private 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 myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}

The Spring EJB support base classes will by default create and load a Spring IoC container as part of their lifecycle, which is then available to the EJB (for example, as used in the code above to obtain the POJO service object). The loading is done via a strategy object which is a subclass of Bean Factory Locator. The actual implementation of Bean Factory Locator used by default is Context Jndi Bean Factory Locator, which creates the Application Context from a resource locations specified as a JNDI environment variable (in the case of the EJB classes, at java: comp/env/ejb/Bean Factory Path). If there is a need to change the Bean Factory/ Application Context loading strategy, the default Bean Factory Locator implementation used may be overridden by calling the set Bean Factory Locator() method, either in setSessionContext(), or in the actual constructor of the EJB.Please see the Javadocs for more details.

As described in the Javadocs, Stateful Session beans expecting to be passivated and reactivated as part of their lifecycle, and which use a non-serializable container instance (which is the normal case) will have to manually call unload Bean Factory() and loadBeanFactory() from ejb Passivate() and ejbActivate(), respectively, to unload and reload the Bean Factory on passivation and activation, since it can not be saved by the EJB container.

The default behavior of the Context Jndi Bean Factory Locator class is to load an ApplicationContext for use by an EJB, and is adequate for some situations. However, it is problematic when the Application Context is loading a number of beans, or the initialization of those beans is time consuming or memory intensive (such as a Hibernate Session Factory initialization, for example), since every EJB will have their own copy. In this case, the user may want to override the default Context Jndi Bean Factory Locator usage and use another BeanFactoryLocator variant, such as the Context Singleton Bean Factory Locator which can load and use a shared container to be used by multiple EJBs or other clients. Doing this is relatively simple, by adding code similar to this to the EJB:

/**
* 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);
}

You would then need to create a bean definition file named bean Ref Context. xml. This file defines all bean factories (usually in the form of application contexts) that may be used in the EJB.In many cases, this file will only contain a single bean definition such as this (where business Application Context.xml contains the bean definitions for all business service POJOs):

<beans>
<bean id="businessBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="businessApplicationContext.xml" />
</bean>
</beans>

In the above example, the Services Constants.PRIMARY_CONTEXT_ID constant would be defined as follows: public static final String Services Constants.PRIMARY_CONTEXT_ID = "business Bean Factory";

Please see the respective Javadocs for the Bean Factory Locator and Context Singleton Bean Factory Locator classes for more information on their usage.

EJB 3 injection interceptor

For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient interceptor that resolves Spring 2.5's @Autowired annotation in the EJB component class: org.spring frame work. ejb. interceptor. Spring Bean Auto wiring Interceptor. This interceptor can be applied through an @Interceptors annotation in the EJB component class, or through an interceptor-binding XML element in the EJB deployment descriptor.

@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
@Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}

Spring Bean Auto wiring Interceptor by default obtains target beans from a Context Singleton Bean Factory Locator, with the context defined in a bean definition file named bean Ref Context.xml. By default, a single context definition is expected, which is obtained by type rather than by name. However, if you need to choose between multiple context definitions, a specific locator key is required. The locator key (i.e. the name of the context definition in bean Ref Context. xml) can be explicitly specified either through overriding the get Bean Factory Locator Key method in a custom Spring Bean Auto wiring Interceptor subclass.

Alternatively, consider overriding Spring Bean Auto wiring Interceptor's get Bean Factory method, e.g. obtaining a shared Application Context from a custom holder class.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Java-Springs Topics