Monday, August 14, 2006

Developing a Spring-enabled Session bean

In one of my blog entries last month I showed how you could access an EJB 3.0 Session bean from Spring 2.0 beans. One of the readers wanted to know whether it is possible to use Spring with EJB 3.0. Interestingly Spring documentation does not say anything about EJB 3.0 beans support with Spring 2.0. I managed to get this to working Spring 2.0 RC2 and in this article; I will show how you can develop a Spring-enabled EJB 3.0 Session bean.

Spring-enabled EJB 3.0 Session bean.

Spring provides abstract classes such as org.springframework.ejb.support.AbstractStatelessSessionBean and org.springframework.ejb.support.AbstractStatefulSessionBean that you can use to build a Spring-enabled EJB 3.0 session bean. You have to extend the abstract session bean class and implement the onEjbcreate method where you can retrieve the required bean instance from the bean factory as in the following example:

@Stateless
public class EmployeeFacadeBean extends
AbstractStatelessSessionBean implements EmployeeFacade
{

EmployeeServiceBean empService;

protected void onEjbCreate()
{

empService = (EmployeeServiceBean)
getBeanFactory().getBean("empService");

}

public Employee addEmployee(String empName, double sal) {

return empService.addEmployee(empName,sal);
}

..
}

Note that our stateless session bean EmployeeFacadeBean extends AbstractStatelessSessionBean. Note that we have implemented the onEjbCreate method that retrieves instance of EmployeeServiceBean from the bean factory.

The EJB deployment descriptor

The application context is passed to the Session Bean by using an environment variable named ejb/BeanFactoryPath in the deployment descriptor (ejb-jar.xml) as follows:

<session>
<ejb-name>EmployeeFacadeBean</ejb-name>
<env-entry>
<env-entry-name>ejb/BeanFactoryPath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/howto-service.xml</env-entry-value>
</env-entry>
</session>

Note that the howto-service.xml contains the bean factory configuration that we see next. The howto-service.xml is packaged in the ejb-jar module.

Wiring all together with Spring configuration


The howto-service.xml contains the Spring configuration.
The
EmployeeServiceBean uses EmployeeDAO that is injected using setter injection:

<beans>

<bean id="empService" class="oracle.ejb30.EmployeeServiceBean">
<property name="employeeDAO">
<ref bean="employeeDAO">
</ref>
</property>
..
</bean>




Remember that the Spring enabled EJB 3.0 Session bean (EmployeeFacadeBean) invokes the EmployeeService bean from the bean factory

empService = (EmployeeServiceBean) getBeanFactory().getBean("empService");


Client Code:

Let us assume that a servlet accesses the Spring-enabled EJB as follows:

public class InsertServlet extends HttpServlet
{
@EJB
private EmployeeFacade ef;

..

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String name = "";
Double sal = new Double(0);

name = request.getParameter("empName");
sal = Double.valueOf(request.getParameter("Sal"));
try
{
Employee emp = ef.addEmployee(name,sal);
System.out.println("Successfully persisted an employee");
request.setAttribute("emp",emp);
this.getServletContext().getRequestDispatcher("/jsp/success.jsp").forward(request, response);
}
catch(Exception e)

}



If you look at the above code you will see that the Servlet uses dependency injection using @EJB (Java EE) to get an instance of Spring-enabled EJB and then invoke its method.


Conclusion


After you package your application, you should be able to deploy and run the application that uses a Spring-enabled EJB 3.0 session bean. Note that I tested this with Oracle Application Server 10g and I expect it to work in other application servers that support EJB 3.0. In a follow-up blog, I will discuss how you can use Spring’s JpaTemplate with a container-managed EntityManager within a Java EE container.

6 comments:

Anonymous said...

Hi,

I tried this on the JBOSS server,4.0.4-GA version and the ejbCreate does not seem to be invoked.

Does there exist any example which works on JBoss showing this?

Anonymous said...

Hi!
I have the same problem when I try a similar testproject on JBoss 5Beta2.
I can call a method in the facade but the spring bean is null and the onEjbCreate method is never invoked.

Jorge said...

Hi, with ejb3 you have to use callback annotations. Example:

@PostConstruct
public void ejb3Create() {
setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());
setBeanFactoryLocatorKey(PRIMARY_CONTEXT_ID);

try {
super.ejbCreate();
} catch (CreateException e) {
....

}

Amol A Aranke said...

Hello,

Can you please share the code, as few things are not clear from code snippets

Nilesh Makani said...
This comment has been removed by the author.
Enterprises taking Java application development seriously- But why? said...

Very Nice Information about java development guide java more info Enterprises taking Java application development seriously- But why?