EJB 3 Getting Started

EJB 2 had three areas of complexities

Three primary techniques in EJB 3 eliminate the above complexities

Java SE 5.0 added metadata annotations and this is easily the most important change in EJB 3, annotations simplify the EJB programming model and remove the need for detailed deployment descriptors and act as a delivery mechanism for dependency injection. They allow you to attach additional information (attributes) to a Java class, interface, method or variable. Annotations can be used by development environments like Eclipse, the Java compiler, persistence providers like Hibernate or a runtime environment like the Java EE container.

Annotation example

import mypackage.Sport;

@Sport("football");
public class DatadiskEJB implements Interests

XML deployment descriptor to override above annotation <Interests>
  <Interest>
    <SportClass>DatadiskEJB</SportClass>
    <Sport>soccer</Sport>
  </Interest>
</Interests>

The @Sport is the annotation, which is a special kind of interface and must be imported hence the import syntax. Annotations humble beginnings is the grandparent of JavaDoc tags, which itself was the XDoclet tool. XDoclet acted as a source code preprocessor that allowed you to process custom Java Doc tags and do whatever you needed to do with the tagged source code or even the EJB 2 deployment descriptors.

One note about annotations is that you should still use deployment descriptors if things change regularly, otherwise you will have to change the source code, XML deployment descriptors override any annotation settings where appropriate and you can mix and match were necessary (see above for overriding example).

A deployment descriptor is a simple XML file that contains application configuration information, they are kinda of hard to read and to understand, hence why the less we deal with them the better, EJB 3 makes deployment descriptors completely optional.

There are a number of common metadata annotations

Annotation Usage Components that use them
javax.annotation.Resource Dependency injection of resources such as Data-Source, JMS objects, etc EJB, web, application client
javax.ejb.EJB Dependency injection of session beans EJB, web, application client
javax.jws.WebServiceRef Dependency injection of web services EJB, web, application client
javax.persistence.PersistenceContext Dependency injection of container-managed EntityManager EJB, web
javax.persistence.PersistenceUnit Dependency injection of EntityManagerFactory EJB, web
javax.annotation.PostConstruct Lifecycle method EJB, web
javax.annotation.PreDestroy Lifecycle method EJB, web
javax.annotation.security.RunAs Security EJB, web
javax.annotation.security.RolesAllowed Security EJB
javax.annotation.security.PermitAll Security EJB
javax.annotation.security.DenyAll Security EJB
javax.annotation.DeclareRoles Security EJB, web

Dependency Injection

Almost every component uses another component or a resource to implement functionality, the main aim of Dependency Injection (DI) is make it as loosely coupled as possible, which means that one component should call another component or resource only through an interface and that components and resources should be glued together using configuration instead of code. In EJB 2 a JNDI lookup involved hard coding resource names into the bean, with DI the container reads the target bean configuration and figures out what beans and resources the target bean needs and injects them into the bean at runtime. DI allows you to declare component dependencies but lets the container deal with the complexities of service or resource instantiation, initialization, sequencing and supplies the service or resource references to the clients as required, @EJB will inject EJBs, @Resource will inject JMS resources, @PersistenceContext will inject container-managed EntityManager.

Test Application

The test application I will use is from the EJB 3 in Action book, which is based on the Hibernate in Action book called the CaveatEmptor application so they should take credit for it. However sometimes unless you know the application you do become confused so in some parts I will create a generic piece of code that that be related to any application a sort of noddy piece of code just to see what is happening without learning the application. The test application in Enterprise Java Beans 3.0 book is a bit much for a beginner but is certainly worth a look after you get you feet wet.

One point I will make is that if you want a full description on how the application works then I suggest you buy the book, my website will only provided references and not full code explanations, it kind of a cheat sheet version, I will also be merging a number of books into a single website so that I have a single point of reference.

The ActionBazzar is a simple eBay like application, you place items into the systems for users to bid on, the application will be developed using more advanced technologies as we learn them.

Like many e-businesses such as eBay, Amazon, you order a number of items and proceed to the checkout, you checkout your items and in a flash your order is complete from the users point of view, however in the background the order process is still continuing by checking credit card details, making sure the money has been obtained (you generally see this as processing from your account page), getting the items ready for delivery, all these processes are probably on different systems but all talking to one another, there will be a dependency between each other making that the order is processed correctly (obtain money before delivery, etc). Once all the processing has finished you generally receive an email stating your order has been completed.

Business logic and persistence components for the above set of actions can be implemented using EJB 3, the process can be visualized below within an EJB 3 architecture, but many other applications will use a very similar setup.

The above diagram represents a traditional four tier architecture, only two processes are triggered by the user, adding a bid to an item and ordering items won. The below is we are planning on using for each part of the application

Business Logic with Session Beans

Session beans should model business processes or actions, they control the business logic calling on other beans to get a task done. They come in two flavors

Stateless beans are used to perform actions or tasks that can be processed in one shot, such as placing a bid on an item in an auction. In this case all we need to do is place obtain a bid and persist it into a database, you could use something like below to achieve this

Interface (remember code to interfaces)

package example.buslogic;

import javax.ejb.Local;
import example.persistence.Bid;

@Local
public interface PlaceBid {
  Bid addBid(Bid bid);
}

stateless session example package example.buslogic;

import javax.ejb.stateless;
import example.persistence.Bid;

@Stateless
public class PlaceBidBean implements PlaceBid {
  ...
  public PlaceBidBean() {}

  // Agreeing with the interface contract
  public Bid addBid(Bid bid) {
    System.out.println("Adding bid, bidder ID = " + bid.getBidderID() +
                       ", item ID = " + bid.getItemID +
                       "bid amount = " + bid.getBidAmount() + ".");

    return save(bid);
  }
}

The above code is very much like a POJO with the exception of the @local and @stateless annotations

@Stateless this tells the container that this is a stateless session bean, this means the container automatically will provide such services to the bean automatically concurrent control, thread safety, pooling and transaction management. You can add other services like transparent security and interceptors.
@Local This tells the container that the session bean can be accessed via the local interface, which means that whatever accesses it will have to be running in the same JVM. The alternate is @remote which allows access to beans via the network using Remote Method Invocation (RMI). The last option you could have used is the @webservice annotation which allows non-java applications to access the bean.

To access the above bean you can use the below client code

simple client code package example.buslogic;

import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import example.persistence.Bid;

public class PlaceBidServlet extends HttpServlet {

  @EJB
  private PlaceBid placeBid;

  public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,                       IOException {

    int bidderID = Integer.parseInt(request.getParameter("bidder_id"));
    int itemID = Integer.parseInt(request.getParameter("item_id"));
    double bidAmount = Double.parseDouble(request.getParameter("bid_amount"));

    Bid bid = new Bid();
    bid.setBidder(bidderID);
    bid.setitemID(itemID);
    bid.setBidAmount(bidAmount);

    placeBid.addBid(bid);
    ...
  }
  ...
}

Again everything looks like a normal POJO except for the @EJB annotation, throughout this EJB 3 topic I will be discussing more advanced features of the annotations already discussed

@EJB The @EJB annotation works in any component that is registered with the Java EE container (servlet, JSF). When the container see this annotation, it looks up the PlaceBid EJB behind the scenes and sets the placeBid variable to be retrieved EJB reference, if necessary the container will lookup the EJB remotely over RMI. The container will instantiate the placeBid variable with the EJB named PlaceBid before the variable is available for use.
Old EJB 2 way of doing the samething Object ejbHome = new InitialContext().lookup("java:comp/env/PlaceBid");
PlaceBidHome placeBidHome = (PlaceBidHome) PortableRemoteObject.narrow(ejbHome, PlaceBidHome.class);
PlaceBid placeBid = placeBidHome.create();

As you can see for the above example EJB 3 has come a long way to making things easier, the whole EJB 2 statement has been reduce to one line of code, thus reducing redundant code across your application, less error-prone.

The one thing to remember is that there is absolutely no need for the stateless bean to guarantee that the value of any of its variables will be the same across any two invocations, this is what statelessness means.

Stateful beans guarantee that a client can except to set the internal state of a bean and count on the state being maintained between any number of method calls. The container makes this happen by doing two important things, firstly the container ensures that a client can reach a bean dedicated to it across more than one method call, secondly the container ensures that the bean instance variable values are maintained for the duration of a session without you having to write any session maintenance code, this technology stops you having to fiddle around with HTTP session, browser cookies or hidden HTML form variables to try and accomplish the same thing.

Using the ActionBazzar application the ordering process would be a good example to use a stateful session bean, since it is broken into four steps

  1. Adding items to the order
  2. Specifying shipping information (shipping method, shipping address, insurance, etc)
  3. Adding billing information
  4. Confirmation of the order (confirm order is correct, total costs)

With a stateful bean the data the user enters at each step can be cached into bean variables until the ordering workflow completes, when the user confirms the order.

Interface

package example.buslogic;

import javax.ejb.Remote;

@Remote
public interface PlaceOrder {
  void setBidderId(Long bidderID);
  void addItem(long itemId);
  void setShippingInfo(ShiipingInfo shippingInfo);
  Long confirmOrder();
}

Stateful bean example

package example.buslogic;

import javax.ejb.*;
import java.util.ArrayList;
import java.util.List;

@Stateful
public class PublicOrderBean implements PlaceOrder {

  private Long bidderID;
  private Long<Long> items;
  private ShippingInfo shippingInfo;
  private BillingInfo billingInfo;

  public PlaceOrderBean() {
    items = new ArrayList<Long>();
  }

  public void setBidderID(Long bidderID) {
    this.bidderID = bidderID;
  }

  public void addItem(Long itemID) {
    items.add(itemID);
  }

  public void setShippingInfo(ShippingInfo shippingInfo) {
    this.shippingInfo = shippingInfo;
  }

  public void setBillingInfo(BillingInfo billingInfo) {
    this.billingInfo = billingInfo;
  }

  @Remove
  public Long confirmOrder() {
    Order order = new Order();
    order.setBidderId(bidderID);
    order.setItems(items);
    order.setShippingInfo(shippingInfo);
    order.setBillingInfo(billingInfo);

    saveOrder(order);
    billOrder(order);

    return order.getOrderId();
  }
  ...
}

As you can see in the above code, there is not much difference between a stateless and a stateful session bean, and the code still remains simple, however there are few new annotations to discuss

@Stateful This annotation tells the container to use the same session bean, this will be a dedicated bean for the clients session, they are not pooled beans unlike stateless beans. There is a optimization technique called passivation which will be discussed later that helps in reducing memory consumption.
@Remote This annotation enables remote-client access
@Remove This annotation marks the end of the workflow by the stateful bean, it tells the container that it no longer requires to maintain the beans session, this helps the container to clear up resources ASAP, otherwise it would wait until the session timed out, before clearing up the session bean. This annotation is optional but critical from a server performance standpoint.

A client program to access the above would look like the following, although I have not provided the full code, you can download it at Manning Publications web site under the EJB 3 in action book.

client code package example.buslogic;

import javax.ejb.EJB;

public class PlaceOrderTestClient {
  
  // This will pull in all the resources we need
  @EJB

  private static PlaceOrder placeOrder;

  public static void main(String[] args) throws Exception {

    System.out.println("Exercising PlaceOrder EJB... ");
    placeOrder.setBidderId(new Long(100));
    placeOrder.addItem(new Long(200));
    placeOrder.addItem(new Long(201));
    placeOrder.setShippingInfo(new ShippingInfo("1 home sweet home", "MyCity", "MyCounty"));
    placeOrder.setBillingInfo("123456789", "VISA", "0123"));

    Long orderId = placeOrder.confirmOrder();
    System.out.println("Order confirmation number: " + orderId);
  }
}

Note that the code above is again very simple (POJO centric) and could even be part of a JUnit test script. You can run the client code in an Application Client Container (ACC) which will inject the remote EJB into the standalone client code. An Application Client Container (ACC) is a mini Java EE container that can be run from the commandline, its a souped-up JVM with some Java EE added. You can run any Java SE client such as a Swing application inside the ACC as if you were running in a regular JVM. The client container can look up and inject EJBs on remote servers, communicate with remote EJBs using RMI, provide authentication and authorization, etc.

Any Java class with a main method can be run inside the ACC, including JAR files as long as the Manifest file contains a Main-Class entry, the JAR can contain a jndi.properties file and an application-client.xml file that contains the environment for connecting to a remote EJB container.

GlassFish example appclient -client test_program.jar

Message-Driven Beans (MDB)

Messaging has numerous uses including system integration, asynchronous processing, and distributed system communication. Java EE messaging makes messaging robust by adding a reliable middleman between sender and receiver, this middleman is called a messaging destination, powered by message-oriented middleware (MOM) servers like IBM MQSeries, or Progress Software SonicMQ. Java EE standardizes messaging through a well-known API, called the Java Messaging Service (JMS), upon which MDBs are heavily dependent.

I will go into great detail about JMS and MDBs in a later topic but here simple example code a MDB using JMS

MDB producer example package example.buslogic;

...
import javax.annotation.Resource;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.jms.*;
...

@Stateful
public class PlaceOrderBean implements PlaceOrder {

  @Resource(name="jms/QueueConnectionFactory")
    private ConnectionFactory connectionFactory;


  @Resource(name="jms/OrderBillingQueue")
    private Destination billingQueue;

  ...

  @Remove
  public Long onfirmOrder() {
    Order order = new Order();
    order.setBidderId(bidderId);
    order.setItems(items);
    order.setShippingInfo(shippingInfo);
    order.setBillingInfo(billingInfo);

    saveOrder(order);
    billOrder(order);

    return order.getOrderId();
  }
  ...
  private void billOrder(Order order) {
    try {
        Connection connection = connectionFactory.createConnection();
        Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer session.createProducer(billingQueue);
        ObjectMessage message = session.CreateObjectMessage();

        message.setObject(order);
        producer.send(message);
        producer.close();
        session.close();
        connection.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
  }
}

Notice the @Resource annotation which is a more general purpose injection, it can be used to inject anything the container knows about, it uses the name parameter which specifies what resource are bound to the EJBs environment naming context and injects them into the code.

I will be going into more depth on JMS in a later topic but for the time being here is the MDBs code that will process the message, again it only highlights what you need to know now.

MDB consumer example

package example.buslogic;

import javax.ejb.MessageDriven;
import javax.ejb.ActivationConfigProperty;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import example.persistence.Order;
import example.persistence.OrderStatus;

@MessageDriven(
   activationConfig = {
      @ActivationConfigProperty(
         propertyName="destinationName",
         propertyValue="jms/OrderBillingQueue")
   }
)

public class OrderBillingMDB implements MessageListener {

  ...
  public void onMessage(Message message) {
    try {
        ObjectMessage objectMessage = (ObjectMessage) message;
        Order order = (Order) objectMessage.getObject();

        try {
            bill(order);
            notifyBillingSuccess(order);
            order.setStatus(OrderStatus.COMPLETE);
        } catch (BillingException be) {
            notfiyBillingFailure(be, order);
            order.setStatus(OrderStatus.BILLING_FAILED);
        } finally {
            update(order);
        }
     } catch (Exception e) {
          e.printStackTrace();
     }
  }
}

The @MessageDriven annotation makes the container transparently provide messaging and other EJB services into a POJO, the properties inside the annotation tell the container what JMS destination the MDB wants to receive messages from. The container in the background starts listening for messages set to the destination specified by the activation configuration properties, as soon as a message arrives at the destination, the container forwards it to an instance of the MDB, remember like stateless beans they are pooled.

MDB implement the javax.jms.MessageListener interface, this well know interface is used to invoke an MDB. The onMessage method defined by the interface has a single javax.jms.Message parameter that the container uses to pass a received message to the MDB.

Persisting Data with JPA

The Java persistence API (JPA) is the persistence-tier solution for the Java EE platform, and it is vastly different from EJB 2. The JPA EntityManager interface defines the API for persistence while the JPA entities specify how application data is mapped to the database, I will have a complete topic on ORM-based persistence and provide a link when i have completed it.

I present some sample code so that you can get a feel on what is going on, i will have numerous other topics that will explain all in depth.

persistence example

package example.persistence;

import java.io.serializable;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GenerationType;
import javax.persistence.GeneratedValue;

@Entity
@Table(name="BIDS")
public class Bid implements Serializable {

  private Long bidID;
  private Long itemID;
  private Long BidderID;
  private Double bidAmount;
  private Date bidDate;

  @Id
  @GeneratedValue(strategy=GeneratedType.AUTO)
  @Column(name="BID_ID")

  public Long getBidID() {
    return bidID;
  }

  public void setBidID(Long BidID) {
    this.BidID = BidID;
  }

  @Column(name="ITEM_ID")
  public Long getItemID() {
    return itemID;
  }

  public void setItemID(Long itemID) {
    this.itemID = itemID;
  }

  @Column(name="BIDDER_ID")
  public Long getBidderID() {
    return BidderID;
  }

  public void setBidderID(Long BidderID) {
    this.BidderID = BidderID;
  }

  @Column(name="BIDDER_AMOUNT")
  public Long getBidAmount() {
    return bidAmount;
  }

  public void setBidAmount(Double bidAmount) {
    this.bidAmount = bidAmount;
  }

  @Column(name="BID_DATE")
  public Long getBidDate() {
    return bidDate;
  }

  public void setBidDate(Date bidDate) {
    this.bidDate = bidDate;
  }

There are a number of annotation used here

@Entity this annotation signals that this bean is a JPA entity
@Table tells the JPA that this entity is mapped to a specific table
@Id this tells the JPA that this property is the primary key for the entity
@GeneratedValue this tells the persistence provider that it should automatically generated the primary key when an entity is saved to the database. There are a number of options that you can use: table, sequence, identity key, etc.
@Column Tells the JPA which properties maps to which table columns.

So now that you have an entity bean how do you go about saving it to the database, you use the EntityManager to persist data, it does this by reading the ORM configuration and providing entity persistence services through an API-based interface. The EntityManager knows how to update entity stored in the database; delete data mapped to an entity instance from the database; read data from the database and store data to a database.

Again I present some sample code using a session bean so that you can get a feel on what is going on

persisting data package example.buslogic;

...
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;

...

@Stateless
public class PlaceBidBean implements PlaceBid {

  // Inject instance EntityManager
  @PersistanceContext(unitName="actionBazzar")
    private EntityManager entityManager;

  ...

  public Bid addBid(Bid bid) {
    System.out.println("Adding bid, bidder ID = " + bid.getBidderID() +
                                    ", Item ID = " + bid.getItemID() +
                                    ", Bid Amount = " + bid.getBidAmount() );

    return save(bid);
  }

  public Bid save(Bid bid) {
    // Persists enity intance
    entityManager.persist(bid);
    return bid;
  }
}

The EntityManager acts as an interpreter between the OO and relational worlds, the entitymanager reads the ORM mapping annotations like @Table and @Column on the entity and figures out how to save the entity into the database. The unitName parameter points to the persistence unit specific to this application, a persistence unit is a group of entities packaged together in an application module. In the background a normal SQL statement will be executed "INSERT INTO BIDS ......." to insert the record, this again has been created by using the annotations in the entity.