Professional Documents
Culture Documents
org.springframework.ejb.support
org.springframework.ejb.access
These classes generally form the Facade for the clients. It means
that the core logic for doing an operation will be implementated as
a POJO (Plain Old Java Object) and the Enterprise Beans merely
serve as a facade and delegate the control to POJOs. One of the
major disadvantages that the developers would have felt while
using the Enterprise Bean running in a EJB Container is that it will
be harder for them to perform unit testing. With the use of Spring’s
approach, unit testing becomes much simplier since the
implementation classes are POJO.
A super-class for all Enterprise Beans is : the
AbstractEnterpriseBean that contains a method for loading beans
from the Application context that use the
ContextJndiBeanFactoryLocator and it is going to create a
BeanFactory object by collecting the location from one or more
classpath address as specified by the default environment variable,
Consider the following default Bean Factory locating strategy,
<session>
<env-entry>
<env-entry-name>ejb/BeanFactoryPath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>applicationContext.xml</env-entry-value>
</env-entry>
...
</session>
We can see from the above code snippet that the default
environment variable corresponds to the default bean factory
locator key and in our case it happens to be 'ejb/BeanFactoryPath'.
This always can be overridden programmatically by calling the
method as follows,
String beanFactoryLocatorKey =
"applicationSpecificBeanFactoryLocator";
bean.setBeanFactoryLocatorKey(beanFactoryLocatorKey);
The default BeanFactory Locator is
the ContextJndiBeanFactoryLocator and this can also be overridden
programmatically by calling the following method,
<bean id="sajjadBean">
<property name="jndiName">
<value>ejb/myBeanService</value>
</property>
<property name="businessInterface">
<value>MyComponentService</value>
</property>
</bean>
There are two properties for configuring a local stateless session bean
using Proxy mechanism. The first property 'jndiName' is the Jndi name of the
bean which can be used by the Jndi Bean Factory object to perform lookup
operation. The second property 'businessInterface' defines the business
interface for which the implementation will be generated by the Spring
container and delegation will be made to the actual implementation.
Similarly, for accessing the Remote Stateless Session Bean, the
class SimpleRemoteStatelessSessionProxyFactoryBean has to be used
instead of LocalStatelessSessionProxyFactoryBean. The
properties 'jndiName' and 'businessInterface' will still be applicable.
There is no direct support in Spring for accessing the Stateful Session Beans
using Proxy mechanisms. However, a convenient way is provided in the form
of JndiObjectFactoryBean.
Let us consider the following configuration,
<bean id="myServiceHome">
<property name="jndiName">
<value>ejb/myService</value>
</property>
</bean>
In the above Xml snippet, we have configured an instance of a EJB
Home interfacewith the help of JndiObjectFactoryBean. In a
traditional EJB Applicaition, we have to manually do a JNDI lookup
using the InitialContext to get a reference to the EJB Home object.
But in Spring, the lookup operation is made easy merely by putting
some configuration information,
We would have to use the following approach to get a reference to
the Stateful Session Bean,
package javabeat.net.articles.spring.ejb.integration.stateless;
package javabeat.net.articles.spring.ejb.integration.stateless;
}
The above class provides a simple implementation for the business
interface HelloService. The implementation merely returns the
string “Hello”. Note that a real implementation may contain much
sophisticated logic by maintaining transaction, accessing the
database, etc.. It is evident that the above business
interface follows the POJO standard which means that it will be
easier to perform Unit Testing in isolation by providing Mock
Implementation.
package javabeat.net.articles.spring.ejb.integration.stateless;
import javax.ejb.EJBLocalObject;
public interface HelloServiceLocal extends HelloService,
EJBLocalObject{
}
Let us define a Local interface by extending the EJBLocalObject.
Note that this interface also extends our business
interface HelloService. This is the client-facing interface meaning
that the client will invoke all the business operation through this
interface.
package javabeat.net.articles.spring.ejb.integration.stateless;
import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;
}
The above Home interface contains a create() method that returns
a HelloServiceLocal object.
package javabeat.net.articles.spring.ejb.integration.stateless;
import javax.ejb.CreateException;
import org.springframework.beans.factory.BeanFactory;
import
org.springframework.ejb.support.AbstractStatelessSessionBean;
<beans>
<bean id="helloService"
/>
</beans>
The preceding HelloEjbComponent instantiates an implementation
of HelloService through the identifier “helloService”. This identifier
should match the one that is defined in the configuration file.
<ejb-jar>
...
<session>
<ejb-name>HelloServiceEjb</ejb-name>
<local-home>
javabeat.net.articles.spring.ejb.integration.stateless.HelloServiceHo
me
</local-home>
<local>
javabeat.net.articles.spring.ejb.integration.stateless.HelloServiceLoc
al
</local>
<ejb-class>
javabeat.net.articles.spring.ejb.integration.stateless.HelloServiceEjb
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<env-entry>
<env-entry-name>ejb/BeanFactoryPath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>spring-stateless-ejb</env-entry-value>
</env-entry>
</session>
...
</ejb-jar>
The above deployment descriptor is similar to a traditional
deployment descriptor. One thing to note is the environmental
entries, that contains a key called 'ejb/BeanFactoryPath' which
contains the path to the configuration file. As mentioned in the
preceding section, the default Bean Factory Locator key
is 'ejb/BeanFactoryPath' and this can always be overridden by
specifying the property beanFactoryLocatorKey.
<beans>
<bean id="echoService">
<property name="jndiName">
<value>java:comp/env/helloService</value>
</property>
<property name="businessInterface">
<value>javabeat.net.articles.spring.ejb.integration.stateless.HelloSe
rvice</value>
</property>
</bean>
</beans>
The client accessing an Enterprise Bean can be a standalone
Remote client, or a Servlet or even can be another Enterprise Bean.
In all these cases, the client must be aware of the factors like
locating the Bean when given a Jndi name and to get a appropriate
reference to the business interface.
In the above configuration file, the property 'jndiName' is used to
locate the Enterprise Bean object. The business interface
is HelloService which means a proxy object
for HelloService interface will be returned simply because we have
configured the bean to use LocalStatelessSessionProxyFactoryBean.
4) Conclusion
A major drawback in developing a J2EE Application that makes use
of Enterprise Java Beans for doing a business operation is the un-
necessary complications available for the clients like looking up the
Home object, creating the reference etc.., and it is impossible to do
Unit testing for the Enterprise Bean as these beans always reside
within the Container. However with Spring’s way of accessing
Enterprise Beans this has been simplified.