Thursday, June 16, 2011

Entity Bean - EJB 2.0









In this blog, we are going to learn how to write a simple entity bean and deploy it in Jboss server.


A brief idea









Entity beans are object oriented way of looking at data in a persistence store.
An Entity is a real, uniquely identifiable thing that exists somewhere outside of EJB, and the entity bean's job is simply to become an object oriented view of that real, persistent entity.

An instance of an entity bean represents a row in a table. Typically, each entity bean has an underlying table in database and each instance of the bean corresponds to a row in that table.
So entity bean maps a combination of data and associated functionality.  Entity EJBs are usually based on an underlying data store and will be created based on that data within it.

There are tow types of entity bean :
Entity bean with bean managed persistence (BMP) and entity bean with container managed persistence (CMP).
In this blog, we will be considering only CMP.

Just like session bean, entity bean is composed of following part :

·         The remote interface
·         The home interface
·         The entity bean
·         The deployment descriptor 

Remote Interface :  The remote interface of an entity bean enables a client to access the instance of an entity bean. An entity bean's remote interface must extend the javax.ejb.EJBLocalObject | javax.ejb.EJBObject  interface. In the remote interface, the entity bean developer defines methods that can be called by the bean's client.

 ItemLocal.java




package com.sarf.entity.bean;
import javax.ejb.EJBLocalObject;

public interface ItemLocal extends EJBLocalObject{
      public Integer getItemId();
      public void setItemId(Integer nItemId);
      public String getItemName();
      public void setItemName(String strItemName);
      public Integer getPrice();
      public void setPrice(Integer nPrice); 
}


Home Interface : The home interface performs life cycle operations: creating, finding, and removing the enterprise bean.The client uses the home object to do the following:
·         Create an entity object
·         Remove an entity object
·         Find an entity object
·         Obtain the javax.ejb.EJBMetaData interface for an entity bean
The client uses the home interface to ask for a reference to the component/remote interface. The home is the client's starting point for getting hold of a reference to a bean.


 ItemLocalHome.java



package com.sarf.entity.bean;
import java.util.Collection;
import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;
import javax.ejb.FinderException;

public interface ItemLocalHome extends EJBLocalHome{
      public ItemLocal create(String name,Integer salary) throws CreateException;
      public ItemLocal findByPrimaryKey(Integer key) throws FinderException;
      public Collection findAll() throws FinderException;
}



Entity Bean :An entity bean class must implement the javax.ejb.EntityBean interface. This interface defines methods that determine the life cycle of the bean as well as other callback methods that are called by the EJB container.


 
ItemBean.java



package com.sarf.entity.bean;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;

public abstract class ItemBean implements EntityBean{

      private static final long serialVersionUID = 1L;
      private EntityContext ctx;
     
      private Integer generatePrimaryKey(){
            return new Integer((new Object()).hashCode());
      }
     
      public abstract Integer getItemId();
      public abstract void setItemId(Integer nItemId);
      public abstract String getItemName();
      public abstract void setItemName(String strItemName);
      public abstract Integer getPrice();
      public abstract void setPrice(Integer nPrice);
     
      private void create(String strName, Integer nPrice) {
            setItemId(generatePrimaryKey());
            setItemName(strName);
            setPrice(nPrice);
          }
      public Integer ejbCreate(String strName, Integer nPrice)  
            throws RemoteException, CreateException {
            create(strName,nPrice);
            return null;
          }
     
      public void ejbPostCreate(String strName,Integer nPrice){}
      public void ejbRemove(){}
      public void ejbStore(){}
      public void ejbLoad(){}
      public void ejbActivate(){}
      public void ejbPassivate(){}
     
      public void setEntityContext(EntityContext ctx){
         this.ctx = ctx;
         }
      public void unsetEntityContext(){
         this.ctx = null;
         }
 }

Deployment Descriptor : Every EJB application must be accompanied by a deployment descriptor that should be saved into the META-INF directory of the project, in a file named ejb-jar.xml.


ejb-jar.xml



<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="2.1" 
        xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
            http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
   <display-name>Item EJB Jar</display-name>

   <enterprise-beans>
       <entity>
         <display-name>Item Entity Bean</display-name>
         <ejb-name>Item</ejb-name>
         <local-home>com.sarf.entity.bean.ItemLocalHome</local-home>
         <local>com.sarf.entity.bean.ItemLocal</local>
         <ejb-class>com.sarf.entity.bean.ItemBean</ejb-class>
           
         <persistence-type>Container</persistence-type>
         <prim-key-class>java.lang.Integer</prim-key-class>
         <reentrant>false</reentrant>
          
         <cmp-field><field-name>ItemId</field-name></cmp-field>
         <cmp-field><field-name>ItemName</field-name></cmp-field>
         <cmp-field><field-name>Price</field-name></cmp-field>
         <primkey-field>ItemId</primkey-field>
       </entity>
   </enterprise-beans>
   <assembly-descriptor>
      <container-transaction>
         <method>
            <ejb-name>Item</ejb-name>
            <method-name>*</method-name>
         </method>
         <trans-attribute>Required</trans-attribute>
      </container-transaction>
   </assembly-descriptor>
</ejb-jar>



jboss.xml



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" 
   "http://www.jboss.org/j2ee/dtd/jboss_5_0.dtd">
<jboss>
   <enterprise-beans>
     <entity>
       <ejb-name>Item</ejb-name>
       <local-jndi-name>bean.ItemBean</local-jndi-name>
     </entity>
   </enterprise-beans>
</jboss>   



application.xml



<application xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/application_5.xsd"  version="5">

 <description>EntityBean Example</description>
 <display-name>EntityBean Example</display-name>
 <module>
   <ejb>EntityBeanExample.jar</ejb>
 </module>
 <module>   
   <web>
     <web-uri>EntityBeanExample.war</web-uri>
     <context-root>/EntityBeanExample</context-root>
   </web>
 </module>   

</application>



CMP Customization : Jboss CMP descriptor is used to control the behavior of the Jboss CMP's engine.This can be done globally through the conf/standardjbosscmp-jdbc.xml descriptor found in the server configuration file set or per EJB JAR deployment via a META-INF/jbosscmp-jdbc.xml descriptor.
The Jboss CMP descriptor file contains database and relationship mapping information for the entity bean. It is also used to define database name and type-mapping.
For each entity defined in the ejb-jar.xml, the Jboss CMP descriptor contains one <entity> child element in <enterprise-beans> element.

 
jbosscmp-jdbc.xml



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jbosscmp-jdbc PUBLIC  
   "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN"
   "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd">

<jbosscmp-jdbc>
   <defaults>
      <datasource>java:/MySqlDS</datasource>
      <datasource-mapping>mySQL</datasource-mapping>
      <create-table>false</create-table>
      <remove-table>false</remove-table>
      <pk-constraint>true</pk-constraint>
      <preferred-relation-mapping>foreign-key</preferred-relation-mapping>
   </defaults>

   <enterprise-beans>
      <entity>
         <ejb-name>Item</ejb-name>
         <table-name>Item</table-name>

         <cmp-field>
            <field-name>ItemId</field-name>
            <column-name>ItemId</column-name>
            <not-null/>
         </cmp-field>
          <cmp-field>
            <field-name>ItemName</field-name>
            <not-null/>
         </cmp-field>
         <cmp-field>
            <field-name>Price</field-name>
            <not-null/>
         </cmp-field>
      </entity>
   </enterprise-beans>
</jbosscmp-jdbc>


Jboss JDBC Connectivity : The Jboss application server provides data source access for EJB persistence. By default, Jboss server is configured to use HypersonicDB. We need to manually configure the server to use other database.

To use Jboss with MySQL, we first need to put the MySQL driver classes into the CLASSPATH. Copy the MySQL jdbc driver jar file to /server/default/lib directory.

To use the MySQL data source, copy /docs/examples/jca/mysql-ds.xml to the /server/default/deploy directory.

We need to modify mysql-ds.xml file to configure our JDBC connectivity.

 
mysql-ds.xml



<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://localhost:3306/myDBName</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password>root</password>
    <exception-sorter-class-name> 
      org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
    </exception-sorter-class-name>
    <!-- corresponding type-mapping in the jbosscmp-jdbc.xml  -->
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>


I have written client code in JSP files. There are three jsp files written for three different type of purpose. addItem.jsp is written for adding a new item into database. findItem.jsp is used for finding an item by primary key. showAllItem.jsp is used to display all items from database.



addItem.jsp



<%@page import="com.sarf.entity.bean.ItemLocalHome"%>
<%@page import="com.sarf.entity.bean.ItemLocal"%>
<%@page import="javax.naming.InitialContext"%>

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>Add Employee</title>
 </head>
 <body>
  <%
      ItemLocalHome objHome = null;
      try{
            InitialContext ctx = new InitialContext();
            objHome = (ItemLocalHome) ctx.lookup("bean.ItemBean");
            objHome.create("Rx Grapes",342);
          }catch(Exception exc){}
  %>
  Item Added
  <hr>
 </body>
</html>




findItem.jsp



<%@page import="com.sarf.entity.bean.ItemLocal"%>
<%@page import="javax.naming.InitialContext"%>
<%@page import="com.sarf.entity.bean.ItemLocalHome"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>Find Items</title>
 </head>
 <body>
  <%
      ItemLocal item = null;
      ItemLocalHome objHome = null;
      try{
            InitialContext ctx = new InitialContext();
            objHome = (ItemLocalHome) ctx.lookup("bean.ItemBean");
            item = objHome.findByPrimaryKey(4326188);
            }catch(Exception exc)
            {
            }
  %>
  Item Id : <%= item.getItemId() %> <br />
  Item Name : <%= item.getItemName() %> <br />
  Price : <%=item.getPrice() %>
 </body>
</html>


 
showAllItem.jsp


<%@page import="com.sarf.entity.bean.ItemLocalHome"%>
<%@page import="com.sarf.entity.bean.ItemLocal"%>
<%@page import="java.util.Iterator"%>
<%@page import="java.util.Set"%>
<%@page import="java.util.ArrayList"%>

<%@page import="javax.naming.InitialContext"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>List Items</title>
 </head>
 <body>
 <%
   ItemLocal objLocal = null;
   ArrayList itemList = null;
   ItemLocalHome objHome = null;
   try{
       InitialContext ctx = new InitialContext();
       objHome = (ItemLocalHome) ctx.lookup("bean.ItemBean");
       itemList = (ArrayList) objHome.findAll();
    }catch(Exception exc)
   {}
 %>
 <table border="1">
  <tr>
   <td>Item Id</td>
   <td>Item name </td>
   <td>Price</td>
  </tr>
  <%
  ItemLocal item = null;
  Iterator itr = itemList.iterator();
  while(itr.hasNext())
  {
      item = (ItemLocal) itr.next();
      if(item != null){
  %>
  <tr>
   <td><%=item.getItemId()%></td>
   <td><%=item.getItemName()%></td>
   <td><%=item.getPrice()%></td>
  </tr>
  <%} }%>
 </table>
 </body>
</html>


Database
I am using MySQL database for managing the data. We should need to install MySQL database in to our system.
Then we have to create database and table. For this example, we need to create a database namely MyDBName and a table namely item.


Database can be created using the following query:
CREATE DATABASE `myDBName`;

Table can be created using the query given below:
CREATE TABLE `item` (                    
          `ItemId` INT(11) NOT NULL,            
          `ItemName` VARCHAR(512) DEFAULT NULL
          `Price` INT(11) DEFAULT NULL,         
          PRIMARY KEY  (`ItemId`)               
        );








We need to build the ear file using ANT as ear structure given below. we can reuse the build.xml written for session bean in the session bean post.
Then we need to deploy the ear file into Jboss Application server and start the server.

To access the example, use the following url :
http://localhost:8080/EntityBeanExample/jsp/showAllItem.jsp



An Enterprise Archive, or EAR, is a file format used by Java EE for packaging one or more modules into a single archive so that the deployment of the various modules onto an application server happens simultaneously and coherently. It also contains XML files called deployment descriptors which describe how to deploy the modules.  
For more detail : Click here

Ear file Structure