So it’s here at last! No more fussing with xml deployment descriptors (unless you really really need to) and some powerful hibernate persistence under the hood for your Entity beans.
I am already using ejb3 in a couple of active projects (mainly web services in axis that communicate with stateless process beans) and I must say… it’s painless! The application server is a JBoss 4.04GA with EJB3. The first thing I had to do was to satisfy the right dependencies and I did that with ant during compilation and deployment and in Eclipse by creating a user library pointing to the necessary EJB3 stuff on Jboss.
Here is an extract from the build file reguarding the necessary jars:
<path id=”classpath”>
<fileset dir=”${jboss.dev.home}/server/default/lib”>
<include name=”*.jar”/>
</fileset>
<fileset dir=”${jboss.dev.home}/server/default/deploy/ejb3.deployer”>
<include name=”*.jar”/>
</fileset>
<fileset
dir=”${jboss.dev.home}/server/default/deploy/jboss-aop-jdk50.deployer”>
<include name=”*.jar”/>
</fileset>
<fileset dir=”${jboss.dev.home}/lib”>
<include name=”*.jar”/>
</fileset>
<fileset dir=”${basedir}/lib”>
<include name=”*.jar”/>
</fileset>
<pathelement location=”${build.classes.dir}”/>
</path>
<property name=”build.classpath” refid=”classpath”/>
So that’s it … now just start coding! A stateless ejb3 is as simple as could be… it’s actually just a plain old java object with a specific annotation that is @Stateless (of course you MUST use JDK5 or more recent in order to use EJB3) and then implement your local and remote interface:
import it.abbeynet.ejb3.example.dao.Contact;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* An very simple example of a stateless ejb3 persisting data
* with a DAO object.
* @author fabio.russo@abbeynet.it
*/
@Stateless
public class AddressBook implements AddressBookLocal, AddressBookRemote
{
@PersistenceContext(unitName=”abbeynet”) private EntityManager manager;
public void insertContact(Contact contact)
{
manager.persist(contact);
}
public Contact findContact(int pKey)
{
return manager.find(Contact.class, pKey);
}
}
A few interesting things are that
the @Stateless tag is in the package javax.ejb and
we have a @PersistenceContext that returns an EntityManager (remember hibernate?!)
we use a very simple DAO object which is nothing more than another POJO
But let’s take one step at a time…
So first of all we have our Stateless bean that implements two interfaces (local and remote) … let’s see these:
[Local]
import it.abbeynet.ejb3.example.dao.Contact;
import javax.ejb.Local;
/**
* A simple local interface example.
* @author fabio.russo@abbeynet.it
*/
@Local
public interface AddressBookLocal
{
public void insertContact(Contact contact);
public Contact findContact(int pKey);
}
[Remote]
import it.abbeynet.ejb3.example.dao.Contact;
import javax.ejb.Remote;
/**
* A simple remote interface example.
* @author fabio.russo@abbeynet.it
*/
@Remote
public interface AddressBookRemote
{
public void insertContact(Contact contact);
public Contact findContact(int pKey);
}
Now we add a Data Access Object class. This is also a POJO, actually more of a JavaBean. The interesting thing is that it has got specific annotations.
package it.abbeynet.ejb3.example.dao;
/**
* A DAO Contact Entity Example.
* @author fabio.russo@abbeynet.it
*/
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Id;
@Entity
@Table(name=”CONTACTS”)
public class Contact implements java.io.Serializable
{
private int id;
private String name;
private String surname;
private String phone;
@Id
@Column(name=”ID”)
public int getId()
{
return id;
}
public void setId(int pk)
{
id = pk;
}
@Column(name=”NAME”)
public String getName()
{
return name;
}
public void setName(String str)
{
name = str;
}
@Column(name=”SURNAME”)
public String getSurname()
{
return surname;
}
public void setSurname(String str)
{
surname = str;
}
@Column(name=”PHONE”)
public String getPhone()
{
return phone;
}
public void setPhone(String str)
{
phone = str;
}
}
As you can see we have a couple of new annotations:
@Entity – States this object is an Entity bean
@Table - describes the actual db table
@Column – describes the actual db column
@Id – identifies the Primary Key on the table
Note that we will also use a descriptor for hibernate called persistence.xml that must be placed in the META-INF directory. The content of such a persistence descriptor can be very basic for simple use:
<?xml version=”1.0″ encoding=”UTF-8″?>
<persistence>
<persistence-unit name=”abbeynet”>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name=”hibernate.hbm2ddl.auto” value=”create”/>
</properties>
</persistence-unit>
</persistence>
To end now, all we need is to deploy the jar file on jboss and have a client call the AddressBook interface we need. An example of an ejb3 client could look like this:
package it.abbeynet.ejb3.example.client;
import it.abbeynet.ejb3.example.AddressBookRemote;
import it.abbeynet.ejb3.example.dao.Contact;
import java.rmi.RMISecurityManager;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
/**
* A simple ejb3 client.
* @author fabio.russo@abbeynet.it
*/
public class AddressBookClient
{
public static void main(String[] args)
{
try
{
// getInitialContext();
// you will need a local jndi.properties to do this
// without specifying more options.
Context jndiContext = new InitialContext();
// Calls the remote interface
AddressBookRemote ref =
(AddressBookRemote)jndiContext.lookup(“AddressBook/remote”);
// This is standard: BeanName/remote or BeanName/local
// this eases up jndi lookups
//Create a new contact
Contact fabio = new Contact();
fabio.setId(1);
fabio.setName(“Fabio”);
fabio.setSurname(“Russo”);
fabio.setPhone(“11919191″);
//Let us insert the created contact
ref.insertContact(fabio);
// retrieve the contact
Contact fromdb = ref.findContact(1);
// and see if it is correct
System.out.println(“Name: ” + fromdb.getName() + ” Surname: ”
+ fromdb.getSurname() + ” Phone: ” + fromdb.getPhone());
}
catch (NamingException e)
{
// Here we can simply use a Log4J logger.
// A log4j.properties local file should do.
Logger log = Logger.getLogger(“client-log.log”);
log.error(“An error has occured!”, e);
e.printStackTrace();
}
}
}
So that should be really it. As you can see EJB3 is really a piece of cake if compared to previous J2EE versions of enterprise beans.