Exercise 10.1: Entity Callbacks

Exercise 10.1: Entity Callbacks

This exercise shows you a simple example of applying the entity callback annotations to an entity bean class. You will see the full life cycle of an entity bean as it is created, loaded, updated, and deleted. Of particular interest is when the Hibernate Entity Manager performs these callbacks. The example makes it clearer when Hibernate performs interactions with the database.

Start Up JBoss

If you already have JBoss running, there is no reason to restart it. Otherwise, start it up as instructed in Workbook 1.

Initialize the Database

The database tables will be created when Exercise 10.1 is deployed to JBoss. If you have problems running this example, shut down JBoss and run the clean.db Ant task.

Build and Deploy the Example Programs

Perform the following steps:

  1. Open a command prompt or shell terminal and change to the ex10_1 directory created by the extraction process.

  2. Set the JAVA_HOME and JBOSS_HOME environment variables to point to where your JDK and JBoss 4.0 are installed. Examples:


    C:\workbook\ex10_1> set JAVA_HOME=C:\jdk1.5.0
    C:\workbook\ex10_1> set JBOSS_HOME=C:\jboss-4.0.x


    $ export JAVA_HOME=/usr/local/jdk1.5.0
    $ export JBOSS_HOME=/usr/local/jboss-4.0

  3. Add ant to your execution path. Ant is the build utility.


    C:\workbook\ex10_1> set PATH=..\ant\bin;%PATH%


    $ export PATH=../ant/bin:$PATH

  4. Perform the build by typing ant.

As in earlier exercises in other chapters, titan.jar is rebuilt, copied to the JBoss deploy directory, and redeployed by the application server.

Examine the Customer Entity

This exercise interacts with the Customer entity you saw in previous chapters. The Customer class has been augmented with the full suite of entity callback annotations.

package com.titan.domain;

import javax.persistence.*;

import java.util.Date;

public class Customer implements java.io.Serializable
   private int id;
   private String lastName;
   private String firstName;

   public int getId( )
      return id;
   public void setId(int pk)
      id = pk;

   public String getLastName( ) { return lastName; }
   public void setLastName(String lastName) { this.lastName = lastName; }

   public String getFirstName( ) { return firstName; }
   public void setFirstName(String firstName) { this.firstName = firstName; }

   public void prePersist( )

   public void postPersist( )

   public void postLoad( )

   public void preUpdate( )

   public void postUpdate( )

   public void preRemove( )

   public void postRemove( )


Each callback annotation simply outputs a message to System.out.

Examine TravelAgentBean

travelAgentBean acts as a façade around the persistence unit that holds the Customer entity. It has simple operations that create, load, update, and remove a Customer instance. Let's take a look at it.

package com.titan.travelagent;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.titan.domain.Customer;

public class TravelAgentBean implements TravelAgentRemote
   @PersistenceContext(unitName="titan") private EntityManager manager;

   public int createCustomer(Customer cust)
      System.out.println("Calling createCustomer():" + cust.getFirstName( ));
      System.out.println("Calling manager.persist( )");
      System.out.println("Ending createCustomer.");
      return cust.getId( );

   public Customer findCustomer(int pKey)
      System.out.println("Calling findCustomer( )");
      System.out.println("manager.find( )");
      Customer cust = manager.find(Customer.class, pKey);
      System.out.println("Returning from findCustomer(): " + cust.getFirstName( ));
      return cust;

   public void doMerge(Customer cust)
      System.out.println("Calling doMerge( )");
      System.out.println("Returning from doMerge( )");

   public void doFlush(int pKey)
      System.out.println("Calling doFlush( )");
      System.out.println("manager.find( )");
      Customer cust = manager.find(Customer.class, pKey);
      System.out.println("cust.setName( )");
      System.out.println("calling manager.flush( )");
      manager.flush( );
      System.out.println("returning from doFlush( )");

   public void doRemove(int pKey)
      System.out.println("Calling doRemove( )");
      System.out.println("manager.find( )");
      Customer cust = manager.find(Customer.class, pKey);
      Systsem.out.println("calling manager.remove( )");
      System.out.println("returning from doRemove( )");


Each of the travelAgentBean's methods interacts with the entity bean in different situations so that you can see when the Customer class's callback methods are executed. EntityManager methods such as persist( ), find( ), merge( ), flush( ), and remove( ) are invoked so that you can see their effect on a Customer entity.

Examine the Client

The client's only role is to allocate a Customer instance and invoke each of the travelAgentBean's methods in sequence. It is not very interesting, so we won't go over it.

Run the Client

Run the Client application by invoking ant run.client at the command prompt. Remember to set your JBOSS_HOME and PATH environment variables. The client program has no interesting output. You will need to view the JBoss console window to see the output from the Customer's callback methods. After running the example, notice that the update from the merge( ) operation is queued until the transaction commits. The same is true of the remove( ) operation. This is the console output:

18:39:35,973 INFO  [EJB3Deployer] Deployed:
18:39:44,567 INFO  [STDOUT] --------------------------------------
18:39:44,567 INFO  [STDOUT] Calling createCustomer( ):Bill
18:39:44,567 INFO  [STDOUT] Calling manager.persist( )
18:39:44,770 INFO  [STDOUT] @PrePersist
18:39:44,817 INFO  [STDOUT] @PostPersist
18:39:44,817 INFO  [STDOUT] Ending createCustomer.
18:39:44,864 INFO  [STDOUT] --------------------------------------
18:39:44,864 INFO  [STDOUT] Calling findCustomer( )
18:39:44,864 INFO  [STDOUT] manager.find( )
18:39:44,895 INFO  [STDOUT] @PostLoad
18:39:44,895 INFO  [STDOUT] Returning from findCustomer( ): Bill
18:39:44,910 INFO  [STDOUT] --------------------------------------
18:39:44,910 INFO  [STDOUT] Calling doMerge( )
18:39:44,910 INFO  [STDOUT] @PostLoad
18:39:44,926 INFO  [STDOUT] Returning from doMerge( )
18:39:44,926 INFO  [STDOUT] @PreUpdate
18:39:44,926 INFO  [STDOUT] @PostUpdate
18:39:44,942 INFO  [STDOUT] --------------------------------------
18:39:44,942 INFO  [STDOUT] Calling doFlush( )
18:39:44,942 INFO  [STDOUT] manager.find( )
18:39:44,942 INFO  [STDOUT] @PostLoad
18:39:44,942 INFO  [STDOUT] cust.setName( )
18:39:44,942 INFO  [STDOUT] calling manager.flush( )
18:39:44,942 INFO  [STDOUT] @PreUpdate
18:39:44,957 INFO  [STDOUT] @PostUpdate
18:39:44,957 INFO  [STDOUT] returning from doFlush( )
18:39:44,957 INFO  [STDOUT] --------------------------------------
18:39:44,957 INFO  [STDOUT] Calling doRemove( )
18:39:44,957 INFO  [STDOUT] manager.find( )
18:39:44,973 INFO  [STDOUT] @PostLoad
18:39:44,973 INFO  [STDOUT] calling manager.remove( )
18:39:44,973 INFO  [STDOUT] @PreRemove
18:39:44,973 INFO  [STDOUT] returning from doRemove( )
18:39:44,989 INFO  [STDOUT] @PostRemove

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows