- The JBoss Microcontainer and Why It Matters
- An Example EJB3 Project on JBoss5
- Running the Client
- Running the Code
- Conclusion
An Example EJB3 Project on JBoss5
The example program is a simple EJB3 stateless session bean. When we’re through with the code, you’ll have seen some of the following:
- Persistence coding with JPA
- The components of EJB3
- The concept of an entity bean
- Stateless session beans
- Running a client program
The application is very simple indeed. I model a greeting card entity that has a message and a color. Both of these attributes can be modified from the client program. The finished greeting card entity is stored in the default JBoss5 database. Before you can run the example code, you’ll have to download the code zip file and extract it into a folder such as the following:
C:\ejbcode
Next, set up the environment variables as described earlier. Run any Ant targets from the folder containing the Ant script file: build.xml. Let’s now have a look at the Java code.
The Domain Model
Listing 1 illustrates the domain entity that models our greeting card. Notice the use of annotations, such as @Entity and @Table. You might remember these if you read my recent article about JPA and Hibernate.
Listing 1 The Domain Entity for a Greeting Card
@Entity @Table(name="GREETING_CARD") public class GreetingCard implements java.io.Serializable { private int id; private String greeting; private int colour; @Id @Column(name="ID") public int getId() { return id; } public void setId(int pk) { id = pk; } @Column(name="NAME") public String getGreeting() { return greeting; } public void setGreeting(String str) { greeting = str; } @Column(name="COLOUR") public int getColour() { return colour; } public void setColour(int colour) { this.colour = colour; } }
One of the first things that struck me about EJB3 code is its brevity. Listing 1 models a business entity. How do you choose such entities? A good rule of thumb is to model the entities described as nouns in your business domain. So, our code will be using instances of the entity in Listing 1—reading and writing them to the database. Let’s now look at the EJB interface—this is the so-called business contract.
The EJB Interface
The interface is the business contract and is illustrated in Listing 2.
Listing 2 The Business Interface
import javax.ejb.Remote; import com.cardsrus.domain.GreetingCard; @Remote public interface CardShopRemote { public void createGreetingCard(GreetingCard greetingCard); public GreetingCard findGreetingCard(int pKey); public void removeGreetingCard(GreetingCard greetingCard); public void mergeGreetingCard(GreetingCard greetingCard); public void flushGreetingCard(); }
The use of the @Remote annotation indicates that the implementation of this interface is accessible to clients outside the EJB3 container. Don’t think of this interface as being any more complex than a normal Java interface; it just has a set of methods that can be implemented by a bean class. Let’s now look at such an implementation—our first bean.
The Bean Class
Listing 3 illustrates the stateless bean class. This class implements the interface we saw in Listing 2.
Listing 3 The bean Class
@Stateless public class CardShopBean implements CardShopRemote { @PersistenceContext(unitName="cardshop") private EntityManager manager; public void createGreetingCard(GreetingCard greetingCard) { manager.persist(greetingCard); } public GreetingCard findGreetingCard(int pKey) { return manager.find(GreetingCard.class, pKey); } public void removeGreetingCard(GreetingCard greetingCard) { manager.remove(greetingCard); } public void flushGreetingCard() { manager.flush(); } public void mergeGreetingCard(GreetingCard greetingCard) { manager.merge(greetingCard); } }
The most noteworthy thing in Listing 3 is the use of the EntityManager class. This is required to gain access to the database services. The next building block is the client program.
The Client
Listing 4 illustrates the client class that brings it all together.
Listing 4 The client Class and Main Program
public class Client { public static void main(String [] args) { try { Context jndiContext = getInitialContext(); Object ref = jndiContext.lookup("CardShopBean/remote"); CardShopRemote dao = (CardShopRemote)ref; GreetingCard oldGreetingCard = dao.findGreetingCard(1); if (oldGreetingCard != null) { dao.mergeGreetingCard(oldGreetingCard); dao.removeGreetingCard(oldGreetingCard); dao.flushGreetingCard(); } GreetingCard greetingCard_1 = new GreetingCard(); greetingCard_1.setId(1); greetingCard_1.setGreeting("Seasons Greetings from Terry Dactyll"); greetingCard_1.setColour(1); dao.createGreetingCard(greetingCard_1); GreetingCard greetingCard_2 = dao.findGreetingCard(1); System.out.println( "Greeting card name:"+greetingCard_2.getGreeting()); System.out.println( "Greeting card colour: " + greetingCard_2.getColour()); } catch (javax.naming.NamingException ne) { ne.printStackTrace(); } } public static Context getInitialContext() throws javax.naming.NamingException { return new javax.naming.InitialContext(); }
The program is divided into four main sections:
- Resource lookup
- Deleting old greeting cards
- Creating a new greeting card
- Retrieving the new greeting card
Again, notice the simplicity of the code. In spite of the compact size and simplicity, the code in Listing 4 is doing some pretty sophisticated stuff: JNDI lookups, database access, entity creation, entity modification, etc. However, the code conceals much of the complexity because it effectively “outsources” the mechanics to the EJB3 container.
The last major code element is the persistence unit. Let’s look at this now.
The Persistence Unit
The last major building block you need is what’s called the persistence unit. Just think of this as the database that the Java code uses. This is the location into which instances of the domain entities are written and retrieved. You might have heard of an acronym called CRUD? This is Create, Read, Update, and Delete, and represents the typical set of database operations you execute on your data. You create new entity instances. You read these instances from the database. You modify or update existing entities. Finally, when you no longer need a given entity, you delete it. Well, the client code in Listing 4 illustrates the CRUD operations, and the persistence unit (see Listing 5) describes the data source against which these operations take place.
Listing 5 The Persistence Unit XML File
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="cardshop"> <jta-data-source>java:/DefaultDS</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> </properties> </persistence-unit> </persistence>
The persistence unit in Listing 5 is pretty much the simplest possible: It uses the default JBoss5 database and re-creates the schema on each run of the program. All the building blocks are now in place. We just need an Ant script to compile, deploy, and run the program.
To compile and deploy the EJB to JBoss5, make sure the application server is running and execute the standard Ant command from the code download folder:
C:\ejbcode>ant
This will compile and deploy the EJB in the JBoss5 deployment folder. Let’s have a quick look at the Ant build script.
The Ant Build Script
As is normal for any Ant script, the file is made up of a set of targets. Each target has a specific purpose, such as compilation, deployment, cleanup, execution, etc. Listing 6 illustrates what is perhaps the most interesting target: Deployment.
Listing 6 The Deployment Target
<target name="ejbjar" depends="compile"> <jar jarfile="build/cardsrus.jar"> <fileset dir="${build.classes.dir}"> <include name="com/cardsrus/domain/*.class"/> <include name="com/cardsrus/cardshop/*.class"/> </fileset> <fileset dir="${src.resources}/"> <include name="META-INF/persistence.xml"/> </fileset> </jar> <copy file="build/cardsrus.jar" todir="${jboss.home}/server/default/deploy"/> </target>
In Listing 6, the EJB JAR file is created and copied to the server deployment folder. That’s all that’s required to get your code running under JBoss5. If all is well, the deployed EJB JAR is picked up by JBoss and registered. This should result in a flurry of JBoss messages culminating in those illustrated in Listing 7.
Listing 7 Successful Deployment of the EJB
12:32:20,203 INFO [SessionSpecContainer] Starting jboss.j2ee:jar=cardsrus.jar,name=CardShopBean,service=EJB3 12:32:20,437 INFO [EJBContainer] STARTED EJB: com.cardsrus.cardshop.CardShopBean ejbName: CardShopBean 12:32:20,890 INFO [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI: CardShopBean/remote - EJB3.x Default Remote Business Interface CardShopBean/remote-com.cardsrus.cardshop.CardShopRemote - EJB3.x Remote Business Interface
At this point, you’re ready to run the client.