Chris Richardson - enterprise POJOs

My book

Calendar

««Aug 2008»»
SMTWTFS
      12
3456789
10111213141516
17181920212223
24252627282930
31

My Top Tags

                                                                               

My RSS Feeds








 

I run a consulting and training company that helps organizations build better software faster.

We provide a variety of services including:

  • Development - we can build your application for you
  • Deployment - we can find a hosting partner or deploy your application on Amazon EC2
  • Training classes for Spring, Hibernate and Acegi Security
  • Jumpstarts to get your project off to the right start
  • Reviews to improve your architecture, code and development process

For more information contact me.

 

My bookmarks

Mailing List

Returning to the EJB cult - developing with EJB 3 Part2

posted Wednesday, 11 May 2005

In the previous installment I described the issues that I encountered persisting an existing POJO domain model with EJB 3. EJB 3.0 is definitely an improvement over EJB2 but the current O/R mapping is extremely limited when compared to Hibernate or JDO. As a result I was less happy than someone migrating to EJB 3 from EJB 2.

The next step in the EJB 3.0 migration process is to port the domain model classes that find, create and delete persistent objects. In this domain model the classes that manipulate persistence objects are the repositories, which are DAO-like classes that represent collections of persistent objects. There are three repositories:

  • PendingOrderRepository - defines methods for creating and finding pending orders
  • RestaurantRepository - defines methods for finding restaurants
  • OrderRepository - defines method for creating orders

These classes are mostly simple wrappers around the persistence framework APIs. The JDO versions use the Spring JdoTemplate class and the Hibernate versions use the HibernateTemplate class. In this blog I am going to describe the EJB 3 implementations of the PendingOrderRepository and the RestaurantRepository.

Implementing the PendingOrderRepository

The PendingOrderRepository defines two methods: createPendingOrder(), which creates a PendingOrder, and findPendingOrder(), which finds a PendingOrder:

public interface PendingOrderRepository {

PendingOrder createPendingOrder();

PendingOrder findPendingOrder(String pendingOrderId);

}

Spring does not yet support EJB 3 EntityManagerTemplate so the repositories must call the EntityManager directly. Fortunately, the PendingOrderRepository is pretty simple so its EJB 3 implementation is straightforward. The createPendingOrder() method calls EntityManager.persist() and the findPendingOrder() method calls EntityManager.find():

public class EJB3PendingOrderRepository implements
PendingOrderRepository {

private EntityManager entityManager;

public EJB3PendingOrderRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}

public PendingOrder createPendingOrder() {
PendingOrder po = new PendingOrder();
entityManager.persist(po);
return po;
}

public PendingOrder findPendingOrder(String pendingOrderId) {
return (PendingOrder) entityManager.find(
PendingOrder.class, new Integer(pendingOrderId));
}

}

Since its so simple there is not much else to say. Let's look at the RestaurantRepository, which is a little more complicated.

Implementing the RestaurantRepository

The RestaurantRepository defines two methods: findRestaurant(), which simply finds the restaurant with specified id, and findAvailableRestaurants(), which finds the restaurants that serve the specified delivery and delivery time:

public interface RestaurantRepository {

public List findAvailableRestaurants(
Address deliveryAddress,
Date deliveryTime);

public Restaurant findRestaurant(String restaurantId);

}

The findRestaurant() method calls Entity.find() to load the specified restaurant and the findAvailableRestaurants() method executes a named query passing as parameters the delivery address's zip code, and the delivery time's day of week, hour and minute:

public class EJB3RestaurantRepository implements
RestaurantRepository {

private EntityManager entityManager;

public EJB3RestaurantRepository() {

}

public EJB3RestaurantRepository(
EntityManager entityManager) {
this.entityManager = entityManager;

}

public Restaurant findRestaurant(
String restaurantId) {
return entityManager.find(Restaurant.class,
new Integer(restaurantId));
}

public List findAvailableRestaurants(
Address deliveryAddress, Date deliveryTime) {
Query query = entityManager
.createNamedQuery("Restaurant.findAvailableRestaurants");
Calendar c = Calendar.getInstance();
c.setTime(deliveryTime);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
String zipCode = deliveryAddress.getZip();

query.setParameter("dayOfWeek", new Integer(
dayOfWeek));
query.setParameter("hour", new Integer(hour));
query.setParameter("minute", new Integer(
minute));
query.setParameter("zipCode", new Integer(
zipCode));
return query.getResultList();

}

The findRestaurants() method uses a Calendar to extract the components of the delivery time and passes them as named query parameters. It executes the following named query, which is defined as annotation of the Restaurant class:

@Entity (access=AccessType.FIELD)
@NamedQuery(
name="Restaurant.findAvailableRestaurants",
queryString="SELECT OBJECT(restaurant) FROM Restaurant as restaurant, IN(restaurant.serviceArea) as zip, IN(restaurant.timeRanges) as tr WHERE zip.zipCode = :zipCode AND tr.dayOfWeek = :dayOfWeek AND ( (tr.openHour < :hour OR (tr.openHour = :hour AND tr.openMinute <= :minute)) AND (tr.closeHour > :hour OR (tr.closeHour = :hour AND tr.closeMinute > :minute) ))"
)
@Table(name="FTGO_RESTAURANT")
public class Restaurant implements Serializable {
...

This query finds restaurants whose serviceArea contains the specified zip and that have a timeRange for the specified delivery time.

Summary

As you can see, implementing the repositories was extremely straightforward. It is quite nice when things are this easy. In the next installment I will describe the design of the session facade that encapsulates the business logic. I will also explain how to use EJB dependency injection to supply its dependencies including the repositories described above.

 

 

 

tags:            

links: digg this    del.icio.us    technorati    reddit