Migrating CMP 2 entity beans to the EJB 3 JPA Part 2

Finder and select methods

If you’ve used CMP entity beans in EJB 2, you know that finder and select methods are defined in the home interface for the entity bean as shown here:

tmp6361_thumb_thumb

The finder methods and select methods in the bean class can be converted to named queries in the User entity class like so:

tmp6362_thumb_thumb

tmp6363_thumb_thumb


Notice the two custom finders. The query for the finder methods (findAll and findByFirstName) are defined in the ejb-jar.xml using EJBQL as defined here:

tmp6364_thumb_thumb

While migrating the finder methods to named queries, we have changed the name of the named queries to unique names (findUserById from findById), because named queries are scoped for the persistence units. This is unlike finder methods that can be invoked only on an entity bean instance. You will notice that we have used the simplified syntax of a JPQL query. Optionally, you can migrate your query to an ad hoc or dynamic query in your session facade, but we recommend against that due to the performance reasons we discussed in topic 13.

Container-managed relationships

In EJB 2.1, relationships are defined in deployment descriptors. Listing 14.5 shows the descriptor elements that define a unidirectional, one-to-one relationship between the User and ContactDetail entity beans, and a one-to-many relationship between the User and Bid entity beans.

Listing 14.5 Container-managed relationship defined in the deployment descriptor I

Listing 14.5 Container-managed relationship defined in the deployment descriptor Itmp6366_thumb[2]

The relationships need to be migrated to the entity class using the appropriate association annotations such as @OneToOne or @OneToMany. Note that we have used Java Generics and changed the association field to a Set from Collection type and such change will require appropriate changes in the client code. The simplified code looks like this:

tmp6367_thumb[2]tmp6368_thumb[2]

In EJB 2, entity beans supported the concept of container-managed relationships. The container was automatically updating the reverse side of relationships when one side was updated. When migrating your relationships to EJB 3, you have to be aware that you are now responsible for managing both sides of your relationships. For example, if you had the following method in the User entity to update a relationship:

As you can see, there’s not a lot of code involved, but the burden of keeping things bidirectional falls squarely on your shoulders now.

Transactions and security settings

CMP entity beans provided the ability to specify transactions and security settings for bean methods. In practice, these were rarely used in favor of the more popular session fagade approach. EJB 3 entities don’t provide such facilities, which means that you need to move security and transaction settings to your session fagades.

Client applications

In EJB 3, we use the EntityManager API to perform entity operations such as persisting, finding, and removing entities. In EJB 2 the home interface acted as a factory interface to provide methods to create, remove, and find entity bean instances. Clients used these methods to persist, remove, and query bean instances. In the new EJB 3 world, client applications should be modified to use the EntityManager API.

Let’s say we have an EJB 2 newUser method in the BazaarAdminBean that is a session fagade used to create an instance of a User entity bean as follows:

tmp6369_thumb[2]

you’d have to change this code to add the back pointer (i.e., set the relationship from Bid to User) as follows:

tmp6370_thumb[2]

tmp6371_thumb[2]

Our example code uses a DTO named UserDTO. After migration, the client code (where User is an entity) will look much simpler:

tmp6372_thumb[2]

Similarly, you can migrate other operations, such as removal, or queries to use the EntityManager API. You have to remove the client code to handle exceptions such as CreateException and FinderException that were previously required to be handled in CMP entity beans but are no longer imposed.

Translating entity home to a session fagade

It’s fairly effortless to migrate the home interface to a session facade by moving all factory methods such as create, remove, and find to this facade. We first create a UserLocalHome interface:

tmp6373_thumb[2]

This interface is exactly the same as before except it does not extend EJBLocal-Home. The session bean implements the UserLocalHome interface and implements all factory methods using the EntityManager API as follows:

tmp6374_thumb[2]tmp6375_thumb[2]

This code throws the EJB 2-specific exceptions that may be expected by clients. You can use this session bean facade to mimic the home interface, thereby reducing the number of changes required on the client side.

This concludes our discussion on migrating applications using CMP entity beans to the EJB 3 JPA. As we told you at the start of this section, migrating your CMP beans to JPA is the most involved of the tasks you’re likely to undertake when upgrading to EJB 3. Revising your domain model, using DTOs and session facades, and the required API changes will all help you achieve your migration goal. Your EJB 2 applications may already use DTOs and session facades, in which case much of this is familiar to you. Either way, we’ve provided a roadmap that will lead you down the migration trail.

At this point, we know exactly what you’re thinking—OK, what you’re probably thinking. What about all that JDBC code? You guys got any tips for converting it to JPA? It just so happens we do, and if you mosey on over to the next section you can see what these tips are.

Next post:

Previous post: