How-To : Using EJB 3.0 and Java Persistence API with Spring in OC4J

Date: 7/06/06
Author: Debu Panda

Introduction

This example application demonstrates Oracle's support for Spring with EJB 3.0 Session beans, container-managed entity manager with Spring's JpaTemplate. This sample uses a Spring-enabled EJB 3.0 Session bean (EmployeeFacade EJB) that uses a Spring bean( EmployeeService bean). The Spring bean uses a Data Access Object ( EmployeeDAO) that uses Spring's JpaTemplate to manipulate entities. The persistence unit is managed by the EJB container by using a container-managed entity manager and passing it to Spring using setter injection. The application uses declarative transaction with EJB 3.0. For simplicity and to demonstrate the dependency injection support in the web container we have used a Servlet ( InsertServlet) as a controller and it uses dependency injection to inject an instance of EmployeeFacade.

Entity example using EJB 3.0 JPA

 

The entity class is a plain java class that is annotated with @Entity to mark it as an entity.

@Entity
@Table(name = "EMPLOYEES")
public class Employee implements java.io.Serializable
{
  private Long empNo;
  private String name;
  private double sal;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="EMPNO")
  public Long getEmpNo()
  {
    return empNo;
  }

..

}

The entity is configured in a persistence unit named howto as defined the persistence.xml. Note that the persistence unit uses a datasource with jndi location jdbc/OracleDS .

                          <persistence-unit name="howto">                           
<jta-data-source>jdbc/OracleDS</jta-data-source>
<properties>
<property name = "toplink.ddl-generation"
value = "drop-and-create-tables"/>
<property name = "toplink.ddl-generation.output-mode" value = "database"/>
</properties>
</persistence-unit>
</persistence>


Spring bean using JpaTemplate


The JpaTemplate in Spring 2.0 nicely abstracts dealing with EJB 3.0 JPA EntityManager API.

 

Following is the code for the DAO that uses JpaTemplate to manipulate entities:

 

                          public class EmployeeSpringDAO extends JpaDaoSupport implements EmployeeDAO {          public Employee addEmployee(String empName, double sal) {       Employee employee = new Employee();       employee.setEname(empName);       employee.setSal(sal);         this.getJpaTemplate().persist(employee);       return employee;     }          public Employee findEmployee(Long employeeId) {       return  (Employee) getJpaTemplate().find(Employee.class,employeeId);      }        } 
                      

The Spring Bean (EmployeeServiceBean) uses the EmployeeDAO . It uses setter injection to get an instance of EmployeeDAO. The following is the code for the EmployeeServiceBean:

                          public class EmployeeServiceBean implements EmployeeService  { protected EmployeeDAO employeeDAO ;                                       public void setEmployeeDAO(EmployeeDAO employeeDAO) {      this.employeeDAO = employeeDAO;   }     public Employee addEmployee(String empName, Double sal){        return (Employee) this.employeeDAO.addEmployee(empName, sal);       }      public Employee findEmployeeByEmpNo(Long empNo) {        return (Employee) this.employeeDAO.findEmployee(empNo);     }  }  
                      

Spring-enabled EJB 3.0 Session bean


The EmployeeFacadeBean extends Spring's AbstractStatelessSessionBean and retrieves the EmployeeServiceBean from the bean factory.

 

Following is the code for the EJB 3.0 Session bean:  

                          @PersistenceContext(name="howto/EntityManager",unitName="howto") @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);       }    public Employee findEmployeeByEmpNo(Long empNo){       return empService.findEmployeeByEmpNo(empNo); }  } 
                      

Note that The Session bean references a PersistenceContext that is used by the Spring bean. The session bean implements onEjbCreate method that retrieves EmployeeServiceBean instance.

 

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.

Wiring all together with Spring configuration

The howto-service.xml contains the Spring configuration. Note that the DAO uses a container-managed entity manager and is retrieved from the ENC using the JndiObjectFactoryBean as follows:

<bean id="entityManager" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/howto/EntityManager</value>
</property>
<property name="resourceRef">
<value>true</value>
</property>
</bean>

An instance of container-managed entity manager is injected to the EmployeeDAO. Note that the EmployeeSpringDAO refers to enityManager bean that we defined earlier as follows:

<bean id="employeeDAO" class="oracle.ejb30.EmployeeSpringDAO"
autowire="byType">
<property name="entityManager" ref="entityManager"/>
</bean>

 

The EmployeeService bean uses EmployeeDAO that is injected using setter injection:

<bean id="empService" class="oracle.ejb30.EmployeeServiceBean">
<property name="employeeDAO">
<ref bean="employeeDAO"/>
</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"); 
                      

If you want your Spring beans to appear in the Application MBean browser you have the following configuration to register your beans:

<bean id="howToMbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="defaultDomain" value="SpringHowTo" />
</bean>

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=empService" value-ref="empService" />
<entry key="bean:name=employeeDAO" value-ref="employeeDAO" />

</map>
</property>
<property name="server" ref="howToMbeanServer" />
</bean>

 

Prerequisites

What you need to know

For further information on EJB 3.0, see the following documents on OTN:

Software Requirements

This demonstration requires that the following software components are installed and configured correctly:

Notations

  • %ORACLE_HOME% - The directory where you installed the Oracle Application Server 10g 10.1.3 .1
  • %SPRING_HOME% - The directory where Spring Framework version 2.0 is installed
  • %JAVA_HOME% - The directory where your JDK is installed
  • %HOWTO_HOME% - The directory where this demo is unzipped

Building the Application

The configuration files are located in the %HOWTO_HOME%/etc directory, including deployment descriptor files such as application.xml.

Running the Application

To run the sample application on a standalone instance of Oracle Application Server 10g 10.1.3.1, follow these steps:

1. Examine the Sample File Directories

  • build - temporary directory created during the build
  • log - temporary directory holding build/deploy logs
  • etc - all necessary files to package the application
  • lib - holds the application archives that could be deployed
  • doc - the How-to document and Javadoc's
    • how-to-ejb30-jpa-spring.html - this How-to page
  • src - the source of the demo
    • ejb - contains the sample entity, Spring bean and DAO
    • web- contains application

2. Configure the Environment

Ensure the following environment variables are defined:

  • %ORACLE_HOME% - The directory where you installed OC4J.
  • %SPRING_HOME% - The directory where you installed Spring 2.0
  • %JAVA_HOME% - The directory where you installed the J2SE 5.0
  • %PATH% - includes %ORACLE_HOME% /ant/bin

Configure Data Source

This example requires the default DataSource (with jndi-location as jdbc/OracleDS)to be configured to connect to the database where you want to persist the entity. The persistence unit is configured to use automatic table creation feature of Oracle TopLink Essentials. For details see http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-extensions.html.

For OC4J, you must configure a datasource in the %ORACLE_HOME%/j2ee/home/config/data-sources.xml file and point it at the schema.

An example configuration. You can use Application Server Control to create or modify an existing DataSource.

<connection-pool name="ScottConnectionPool">
  <connection-factory factory-class="oracle.jdbc.pool.OracleDataSource"
   user="scott"
   password="tiger"
   url="jdbc:oracle:thin:@localhost:1521:ORCL" >
  </connection-factory>
</connection-pool>

<managed-data-source name="OracleManagedDS"
 connection-pool-name="ScottConnectionPool"
 jndi-name="jdbc/OracleDS"
/> 

 

You can create the JDBC resources by using ANT tasks. Make sure you change the database configurations (db.host, db.sid, db.port, db.user, db.password) in ant-oracle.properties file.

Ensure $ORACLE_HOME/ant/bin is included in your PATH environment variable and then use the following command:

>ant configure-ds

3. Start the Server

Start OC4J stand alone using the following command after you make the above changes.

>%ORACLE_HOME%/bin/oc4j -start

If you are using an OracleAS managed install, start using the following command after you make the above changes.

> %ORACLE_HOME%/opmn/bin/opmnctl startall

4. Generate, Compile, and Deploy the Application

Ant 1.6.2 is shipped with OC4J and you have to set your PATH environment variable to $ORACLE_HOME/ant/bin. On some operating systems, Ant does not currently support the use of environment variables. If this is the case for your operating system, please modify the ant-oracle.xml file located in the %HOWTO_HOME% directory.

Edit ant-oracle.properties (in the demo directory) and ensure the following properties are set to the correct values, as indicated below for OC4J standalone:

  • oc4j.host: host where OC4J is running (default localhost)
  • oc4j.admin.port: RMI port number (default 23791)
  • oc4j.admin.user: admin user name (default oc4jadmin)
  • oc4j.admin.password: admin user password (default welcome)
  • oc4j.binding.module: website name where deployed web modules are bound (default http-web-site)

If you are using OracleAS managed install then you have appropriately change the following properties beside changing oc4j.admin.user and oc4j.admin.password for your managed OC4J instance in OracleAS install.

  • opmn.host: the hostname/IP where OracleAS is running (default localhost)
  • opmn.port: OPMN request port (default 6003) for the OracleAS install
  • oc4j.instance: admin user name (default oc4jadmin)

You have to uncomment appropriate deployer.uri in the ant-oracle.properties based on your environment i.e. a single instance OC4J or a clustered OC4J instance/group managed by OPMN.

To build the application, type the following command from the %HOWTO_HOME% directory:

>ant

You should now have the newly created ejb3spring.ear in your %HOWTO_HOME%/lib directory.

This command will attempt to deploy the application archive if the build is successful. It will first test whether OC4J is running before attempting the deployment operation.

Note that you can also deploy the application separately . Ensure the %ORACLE_HOME% environment variable is defined, and from the %HOWTO_HOME% directory, type the command:

>ant deploy

5. Run the Application

Run the sample by providing invoking the following URL from your favorite browser:

http://localhost:8888/ejb3spring

In this page, enter employee no, Name and Salary and then click on Add Employee button.

The InsertServlet will be invoked that will try to persist the employee. The InsertServlet invokes addEmployee method EmployeeFacade. The EmployeeFacade bean uses the EmployeeServiceBean (Spring managed Bean) that in turns uses Spring JpaTemplate to persist the entity instance.

You will be redirected to a success page if your record was inserted successfully. You can also check the database table to ensure the record was created.

Summary

In this document, you should have learned how to:

  • Develop a simple Spring enabled EJB 3.0 Session Bean
  • Use the container-managed EntityManager with Spring JpaTemplate
  • Deploy an execute a sample application using Spring-enabled EJB 3.0 Session bean, JPA Integration with Spring on Oracle Application Server 10g 10.1.3.1

 

Left Curve
Popular Downloads
Right Curve
Untitled Document