Entity CMP EJB Example in Glassfish - No Annotations

Aim
The aim of this EJB tutorial is to create a simple CMP (Container Managed Persistence) Entity Enterprise Java Bean or EJB, deploy it to a Glassfish server and then call it's remote interface via a java client. We will be building this bean from the ground up with an ejb-jar.xml and persistence.xml and without the use of Annotations( @Remote etc). Once you learn the basic you can take the short-cuts. Leave any questions or problems as comments and I will endeavour to answer them.

Assumptions
This article assumes that you have Galssfish 2 installed and a domain configured. Please see Installing and Setting up Glassfish 2 for more details. For purposes of this example the glassfish domain is running on port 8082. This also assumes that you have a database up and running with a JNDI database pool configured. For this example we are using a MySQL database with a pool configured in one of the previous tutorials -JNDI Database bool with MySQL. The project directory is EJBEntityCMPExample.

Versions used in this example
Sofware/ComponentImage
Windows XP SP2N/A
Glassfish 2glassfish-installer-v2.1-b60e-windows.jar
JDK 1.5.0N/A
Links to these files can be found here

Although this is a quick 'helloworld' tutorial we will not sacrifice neatness for speed - so all the source files, class files etc will be kept in separate directories and as clean as possible. You will thank me for this later.

Create this webapp directory structure in your working directory- similar to something you would get from eclipse. The structure used in this example is given below. EJBEntityCMPExample will be referred to as your project or working directory. Create this structure.

EJBEntityCMPExample
_|_bean_src
_|__|_EntityBeanExample.java
_|__|_EntityBeanHomeExampleI.java
_|__|_EntityBeanExampleI.java
_|_bean_bin
_|__|_META-INF
_|__|__|_ejb-jar.xml
_|__|__|_sun-ejb-jar.xml
_|__|__|_persistence.xml
_|_client_src
_|__|_EntityBeanClient.java
_|_client_bin


The Glassfish app server is installed in the D:\downloads\glassfish directory for this tutorial.

JNDI-JBDC pool
  1. This tutorial assumes that you already have the 'jdbc/MySQLPool' jndi dtabase pool configured and you have the table required. The table below is the entitybeanexample table. the id field is a primary key. Make sure you can access this table through the jdbc/jndi entry. See JNDI Database bool with MySQL if you wan't to learn how to do this. Our entity bean will map to this table.
    id (INT)name (CHAR)
    1arabica
    2robusta
  2. `
  3. For completeness I have added an axcertp from the dump of the 'entitybeanexample' table below. You can forget about the additional columns. All you need is the id and name.
     1. CREATE TABLE `entitybeanexample` (
     2.   `id` int(11) NOT NULL DEFAULT '0',
     3.   `name` char(32) DEFAULT NULL,
     4.   `description` char(32) DEFAULT NULL,
     5.   `stocklevel` int(11) DEFAULT NULL,
     6.   PRIMARY KEY (`id`)
     7. ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
     8. SET character_set_client = @saved_cs_client;
     9. 
    10. --
    11. -- Dumping data for table `entitybeanexample`
    12. --
    13. 
    14. LOCK TABLES `entitybeanexample` WRITE;
    15. /*!40000 ALTER TABLE `entitybeanexample` DISABLE KEYS */;
    16. INSERT INTO `entitybeanexample` VALUES (1,'arabica',NULL,0),(2,'robusta',NULL,0),(3,'liberica',NULL,0),(4,'bonnieri',NULL,0),(5,'ganja',NULL,NULL);
    17. /*!40000 ALTER TABLE `entitybeanexample` ENABLE KEYS */;
    18. UNLOCK TABLES;
    Hide line numbers

Write and compile the Bean files
  1. Write the remote interface and save it under bean_src as EntityBeanExampleI.java.
     1. package ejb.entitybeanexample;
     2. 
     3. import java.rmi.*;
     4. import javax.ejb.*;
     5. 
     6. public interface EntityBeanExampleI extends EJBObject{
     7.     
     8.     public Integer getId() throws RemoteException;
     9.     public void  setId(Integer id) throws RemoteException;
    10. 
    11.     public String getName() throws RemoteException;
    12.     public void  setName(String name) throws RemoteException;
    13. }
    Hide line numbers
  2. `
  3. Write the home interface and save it under bean_src as EntityBeanHomeExampleI.java.
     1. package ejb.entitybeanexample;
     2. 
     3. import java.util.Collection;
     4. import java.rmi.*;
     5. import javax.ejb.*;
     6. 
     7. public interface EntityBeanHomeExampleI extends EJBHome{
     8.     public EntityBeanExampleI create(Integer id, String name) throws CreateException, RemoteException;
     9.     public EntityBeanExampleI findByPrimaryKey(Integer id) throws FinderException, RemoteException;
    10.     public Collection findByNameLike(String s) throws FinderException, RemoteException;;
    11. }
    Hide line numbers
  4. `
  5. Complete the bean implementation and save it under bean_src as EntityBeanExample.java.
     1. package ejb.entitybeanexample;
     2.   
     3. import javax.ejb.*;
     4. import java.io.Serializable;
     5. import java.util.*;
     6. import java.rmi.*;
     7.   
     8. public abstract class EntityBeanExample implements EntityBean {
     9. 
    10.     public abstract Integer getId();
    11.     public abstract void  setId(Integer id);
    12.     
    13.     public abstract String getName();
    14.     public abstract void  setName(String name);
    15. 
    16.     public void ejbLoad() {}
    17.     public void ejbStore() {}
    18.     public void ejbActivate() {}
    19.     public void ejbPassivate() {}
    20.     public void setEntityContext(EntityContext ctx) {}
    21.     public void unsetEntityContext() {}
    22.     public void ejbRemove() throws RemoveException {}
    23.     
    24.     public void ejbPostCreate(Integer id, String name) throws CreateException {}
    25.     
    26.        public Integer ejbCreate(Integer id, String name) throws CreateException {
    27.            setId(id);
    28.            setName(name);
    29.         return null;
    30.     }
    31. }
    Hide line numbers
  6. `
  7. Compile the code and install the classes into the bean_bin using the cmd below.

    ..workspace\EJBEntityCMPExample\bean_src>javac -extdirs D:\downloads\glassfish\lib -d ..\bean_bin *.java
  8. `
  9. Create the deployment descriptor ejb-jar.xml. Save this under the bean_bin/META-INF directory. Note that the abstract name of the table is called 'beanstore.'
     1. <?xml version="1.0" encoding="UTF-8"?>
     2. <ejb-jar>
     3.     <display-name>Simple Entity Bean</display-name>
     4.     <enterprise-beans>
     5.         <entity>
     6.             <description>Simple CMP Entity bean example</description>
     7.             <ejb-name>EntityBeanExample</ejb-name>
     8.             <home>ejb.entitybeanexample.EntityBeanHomeExampleI</home>
     9.             <remote>ejb.entitybeanexample.EntityBeanExampleI</remote>
    10.             <ejb-class>ejb.entitybeanexample.EntityBeanExample</ejb-class>
    11.             <persistence-type>Container</persistence-type>
    12.             <prim-key-class>java.lang.Integer</prim-key-class>
    13.             <reentrant>false</reentrant>
    14.             <cmp-version>2.x</cmp-version>
    15.             <abstract-schema-name>beanstore</abstract-schema-name>
    16.             <cmp-field>
    17.                 <field-name>id</field-name>
    18.             </cmp-field>
    19.             <cmp-field>
    20.                 <field-name>name</field-name>
    21.             </cmp-field>       
    22.             <primkey-field>id</primkey-field>
    23.             <query>
    24.                 <query-method>
    25.                     <method-name>findByNameLike</method-name>
    26.                     <method-params>
    27.                         <method-param>java.lang.String</method-param>
    28.                     </method-params>
    29.                 </query-method>
    30.                 <ejb-ql>select object(e) from beanstore e where e.name like ?1</ejb-ql>
    31.             </query>
    32.           </entity>
    33.     </enterprise-beans>  
    34. </ejb-jar>
    Hide line numbers
  10. `
  11. Create the sun-ejb-jar.xml file and save this under the bean_bin\WEB-INF folder too. Note the jndi/jdbc name we're using for the database connection.
     1. <?xml version="1.0" encoding="UTF-8"?>
     2. <sun-ejb-jar>
     3. <enterprise-beans>
     4.     <ejb>
     5.         <ejb-name>EntityBeanExample</ejb-name>
     6.         <jndi-name>ejb/entitybeanexample</jndi-name>
     7.     </ejb>
     8.     <cmp-resource>
     9.         <jndi-name>jdbc/MySQLPool</jndi-name>
    10.     </cmp-resource>
    11. </enterprise-beans>
    12. </sun-ejb-jar>
    Hide line numbers
  12. `
  13. Now the final persistence.xml file. This goes in the META-INF directory also. Note that are using oracle's toplink to provide the persistence mechanism.
     1. <?xml version="1.0" encoding="UTF-8"?>
     2. <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
     3.     <persistence-unit name="hello-world" transaction-type="JTA">
     4.         <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
     5.         <jta-data-source>jdbc/MySQLPool</jta-data-source>
     6.         <class>ejb.entitybeanexample.EntityBeanExample</class>
     7.         <exclude-unlisted-classes>true</exclude-unlisted-classes>
     8.     </persistence-unit>
     9. </persistence>
    Hide line numbers
  14. `
  15. Now cd into the bean_bin directory and jar up the files in preparation for deployment

    ..workspace\EJBEntityCMPExample\bean_bin>jar -cvf entitybeanexample.jar *

Deploy the EJB in Glassfish
We are going to take a short cut and deploy the bean_bin directory instead of jar-ring it up and deploying as a .war or .jar file.
  1. Login to the Glassfish admin console. Please see Installing and Setting up Glassfish 2
  2. `
  3. Under Applications->EJB Modules select deploy. Under "Location" select "Packaged file to be uploaded to the server." Now navigate to your working directory (EJBEntityCMPExampleWorld), go to the bean_bin directory and select the 'entitybeanexample.jar' you created earlier. If there is a problem look at the server.log in the log directory in your Glassfish domain.
  4. `
  5. To make sure go to the "bin" diretory under your glassfish installation and run asadmin with list-jndi-entries.

    D:\downloads\glassfish\bin>asadmin list-jndi-entries --context ejb

    Jndi Entries for server within ejb context:
    mgmt: com.sun.enterprise.naming.TransientContext
    entitybeanexample: javax.naming.Reference
    Command list-jndi-entries executed successfully.

Write and compile the Client
  1. Write client and save it under the client_src direcotry as EntityBeanClient.java.
     1. import java.util.*;
     2. import java.io.*;
     3. import javax.naming.*;
     4. 
     5. import ejb.entitybeanexample.EntityBeanHomeExampleI;
     6. import ejb.entitybeanexample.EntityBeanExampleI;
     7. 
     8. public class EntityBeanClient {
     9. 
    10.     public static void main(String[] args) throws Exception{
    11.         (new EntityBeanClient()).Go();
    12.     }
    13.     
    14.     public void Go() throws Exception {
    15.         Properties props = new Properties();
    16.         
    17.         props.put(Context.PROVIDER_URL,"iiop://127.0.0.1:3700");
    18.         props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
    19.         
    20.         InitialContext ctx = new InitialContext(props);
    21.         
    22.         EntityBeanHomeExampleI beanhome = (EntityBeanHomeExampleI) ctx.lookup("ejb/entitybeanexample");
    23.         
    24.         EntityBeanExampleI bean= beanhome.findByPrimaryKey(2);
    25.         System.out.println(bean.getName()+" "+bean.getId());
    26.         
    27.         bean = beanhome.create(new Integer(5), "ganja");
    28.         //bean.remove();
    29.         
    30.         Collection beans = beanhome.findByNameLike("arabica");
    31.         Iterator i = beans.iterator();
    32.         while(i.hasNext()){
    33.             bean=(EntityBeanExampleI)i.next();
    34.             System.out.println(bean.getId()+" "+bean.getName());
    35.         }
    36.         
    37.     }
    38. }
    Hide line numbers
  2. `
  3. open a promt to the "client_src" directory and Compile the code. Use the "-d" ooption to copy the class to the client_bin directory.
    ..workspace\EJBEntityCMPExample\client_src>javac -extdirs D:\downloads\glassfish\lib
    -d ..\client_bin -cp ..\bean_bin EntityBeanClient.java

Running the client
  1. Open a command into the client_bin directory and run the application.
    ..workspace\EJBEntityCMPExample\client_bin>java -Djava.ext.dirs=D:\downloads\glassfish\lib -cp ..\bean_bin;. EntityBeanClient
  2. `
  3. You should see the result in the console. Also if you noticed we created a bean/record and then deleted it in the client. You may wish to comment out some of this, recompile and run again to see what's happening in the database.

Back to the tutorial trail | Home

3 comments:

Josh said...

Dude! This is totally awsome. The finer points get lost when you use tools such as netbeans etc. But then again it's because of this kind of complexity that EJBs have never really picked up and so we have annotations. Maybe EJBs will be reborn but I doubt it.

Ayodeji Filegbe said...

Nice Tutorial. Please i can't seem to run the application as it always tell me there is a problem with the lookup. Any help would be appreciated.
Thanks.

Naviya Nair said...

Very interesting and good Explanation
ASP NET Training
ASP NET Training
ASP NET Online Training
C-Sharp Training
Dot Net Training in Chennai
Online .Net Training


MVC Training
WCF Training
Web-API Training
LINQ Training
Entity Framework
Training

Dot Net Interview Questions