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

Migrating CMP entity beans to the EJB 3 JPA is the most complex and involved migration task we’ll discuss. It requires careful planning and a thorough understanding of your application.

You now know that there are significant differences between CMP entity beans and EJB 3 entities. CMP entity beans are coarse-grained data objects, whereas EJB 3 entities are lightweight domain objects that represent finegrained data. EJB 3 entities are regular Java classes and lack some features that CMP 2 entity beans provide, such as remoteness, declarative security, and transactions. We agree with the point of view that imposing those features was a bad idea in the first place. However, you’ll have to implement workarounds if you used those features. If you avoided them by using best practices and design patterns, then you are probably in good shape and your overall migration process will be smoother than it would be otherwise.

EJB 2 provided the ability to access an entity bean remotely by using remote interfaces, but design experts recommended against this. As you’ll recall from topic 12, we recommend you use a session facade as a shield to front entity beans, and use DTOs to transfer data between clients and the server. If you’ve followed these guidelines, it will simplify your migration efforts. Another benefit of using the DAO design pattern is that it may enable you to migrate the persistence tier easily without much impact on the business logic tier.


Signpost up ahead: dead end for BMP entity beans

EJB 2 supported entity beans with bean-managed persistence (BMP), where the code was developed using an API such as JDBC for persisting bean instances. BMP was quite popular initially because CMP implementations from most application servers were not stable. It was also useful when applications required nonrelational data.

However, there are some inherent issues with BMP, such as N + 1 problems. Unfortunately, there is no clear migration path for BMP entity beans to EJB 3. This translates into what seems like a dead end for BMP entity beans. As EJB 3 requires support for EJB 2, BMP entity beans will be supported in EJB 3 containers.

If you’re using BMP entity beans with a relational database, we recommend you consider migrating these to use the EJB 3 JPA. Otherwise, you may have a huge support issue lurking in your code base!

Redesign your domain model

You should seriously consider redesigning your domain model when migrating your CMP applications to EJB 3. CMP entity beans lacked support for OO features such as inheritance and polymorphism. Entity beans were mere representations of fragments of your database schema. Thus, in the OO purist’s lingua franca, your domain model was probably anemic; let’s see what we can do about that!

During your migration to EJB 3 JPA, you probably want to consider refactoring your entities to take advantage of the object-oriented features supported by the EJB 3 JPA. For example, assume that when ActionBazaar was built using CMP 2 it had an entity bean named UserBean that was a representation of the USERS table. Listing 14.1 shows the source code for this UserBean entity bean class.

Listing 14.1 User CMP entity bean using EJB 2

Listing 14.1 User CMP entity bean using EJB 2Listing 14.1 User CMP entity bean using EJB 2

While migrating the application, we looked at the ActionBazaar system and found that there could be different kind of users, such as Bidder, Seller, or Admin. Therefore, rather than migrating the entity bean to EJB 3, we used inheritance and a single-table-per-entity hierarchy, as shown in listing 14.2. Figure 14.4 shows the results of the entity refactoring.

Listing 14.2 Remodeled User entity with inheritance

Listing 14.2 Remodeled User entity with inheritance

While migrating EJB 2 entity beans to EJB 3, it is likely you'll want to refactor to take advantage of features like OO inheritance support. In our example, the UserBean entity bean can be refactored into a User POJO entity superclass and Bidder, Seller, and so forth entity POJO subclasses.

Figure 14.4 While migrating EJB 2 entity beans to EJB 3, it is likely you’ll want to refactor to take advantage of features like OO inheritance support. In our example, the UserBean entity bean can be refactored into a User POJO entity superclass and Bidder, Seller, and so forth entity POJO subclasses.

Note that remodeling the entities did not require any changes in the database because we used a single-table-per-entity strategy, and we used the existing USER_TYPE column as the discriminator.

You should carefully plan and execute such a refactoring; it requires more work and testing of your applications than just migrating your CMP entity beans to entity classes as is. But the payoff in maintenance costs can be more than worth that extra work if done correctly.

In the next few sections, we’ll focus on strategies that allow you to migrate entity beans to a JPA entity without doing any redesign.

Using DTOs as entities

The DTO is a commonly used design pattern. The specific benefit with respect to entity beans is that it allows the transfer of data back and forth between remote clients and entity beans in EJB 2. There are two types of DTOs: fine grained and coarse grained. The fine-grained DTO often has a one-to-one mapping between an entity bean and a DTO. The coarse-grained DTO represents data from multiple entity beans and is also known as the View object. In reality, a fine-grained DTO looks like a real domain object, just without any behavior; only the state of the object is represented.

Topic 9 explained that this use of a DTO is no longer required because entities themselves are POJOs that can be transferred between clients and servers. If you used the DTO design pattern and are looking to migrate your entity beans to EJB 3 without spending any effort on remodeling, then you should consider making each DTO a candidate for an EJB 3 entity class.

Assume that ActionBazaar used the DTO design pattern. Listing 14.3 shows a sample of a fine-grained DTO named UserDTO that maps to a UserBean entity bean.

Listing 14.3 A DTO for the UserBean CMP

Listing 14.3 A DTO for the UserBean CMP

Reviewing UserDTO in listing 14.3, it looks more like an entity. It’s a POJO; it has a constructor ©, fields O, and properties Q required for the persistent attributes defined. It even has a relationship defined to another DTO C that you can use as a basis for relationships between entities. It’s worth considering making this class an entity rather than migrating the abstract entity bean class in listing 14.1 to an entity. You can make the DTO an entity by simply annotating it as an entity with the @Entity annotation, and defining the O/R mapping from your vendor-specific

You have to make sure that you have defined all persistence fields in the entity class by cross-checking the persistence fields defined in the deployment descriptor with your entity bean. You’ll also need to migrate the ORM metadata from the vendor-specific deployment descriptor, to either mapping annotations in the entity class or to a mapping file. After you migrate the finder methods and select methods to named queries, you’re almost done!

The last step is to recall that your entity beans may have some business logic in the business methods. You have to migrate any business methods from the entity bean to the entity class, or to a session bean facade, as we describe next.

Entity bean classes and interfaces

If your applications have not used DTOs, then we’re afraid you’re in for a lot of monotonous work as you migrate your entity beans to entities. We hope it’s evident from listing 14.1 that since the entity bean class and all methods are abstract, you’ll have to convert the bean class to a concrete class with a constructor and define persistence fields as well as the obligatory getter/setter methods. The first step in migration will be similar to creating a DTO for your entity bean and annotating it with @Entity.

Persistence fields are actually defined in the EJB deployment descriptor. Migrating all the fields to your bean class and creating the appropriate fields and getter/setter methods in the entity class is required since we’re relying on dependency injection to help us out at runtime. You should be able to find some development tools and utilities to help automate these mechanical steps.

Converting interfaces

EJB 2 entity beans required two interfaces: a component (remote or local) interface and a home interface. EJB 3 entities don’t require any framework interfaces,deployment descriptor to either metadata annotations or orm.xml. Following is the UserDTO (renamed to User) converted to an entity with a few JPA annotations:

tmp6350_thumb

so you can entirely eliminate the interfaces from your entities if you like, or convert your component interface to a business interface for the entity.

Optionally, you can use your component interface as the basis for migrating to an entity. Listing 14.4 shows the local interface for the UserBean entity bean. A quick glance informs us that it will be easy to migrate this interface to an EJB 3 entity. The interface has all get/set methods for the persistence fields O and the relationships ©.

Listing 14.4 Local interface for the UserBean CMP

Listing 14.4 Local interface for the UserBean CMP

If you haven’t used a DTO, we recommend you start with the local interface as the basis for creating your entity class.

The home interface in the entity bean serves as the factory method to create, remove, and query bean instances. You can remove the home interface and migrate your finder methods to named queries, as we discuss later in the section. The create and remove methods are replaced with EntityManager operations. Optionally, you can migrate the home interface to be used as a session fagade that exposes all factory methods such as create and remove to minimize the impact on client applications. We’ll discuss this in section 14.4.4.

Identifying the primary key

Like the persistence fields, the primary key for CMP 2 is defined in the deployment descriptor. For example, the primary key for the UserBean entity bean is defined in the deployment descriptor as follows:

tmp6352_thumb

You identify the primary key of the entity class in EJB 3 using the @Id annotation:

tmp6353_thumb

CMP 2 did not support the automatic generation of primary key values; this required the use of workarounds such as the Sequence Generator pattern, or vendor-specific extensions to either database sequence or table sequence generators. If you happened to use such features, then you must migrate them to one of the primary key-generation strategies that we discussed in topic 8.

Creating O/R mapping

The ORM metadata such as table and column mapping for EJB 2 entity beans is defined in the vendor-specific deployment descriptor. Move those mappings to entity classes by using the @Table and @Column annotations, as discussed in topic 8. Optionally, you can move them to an OR mapping file, as discussed in topic 11.

Lifecycle methods

EJB 2 required you to implement a lot of lifecycle methods—a lot. These methods are template methods and are rarely used. It’s possible that you may have implemented some business logic in these methods. You can migrate the business logic for the lifecycle methods to the entity listener callback methods discussed in topic 9. Table 14.5 summarizes the methods that you can migrate from EJB 2 lifecycle methods to entity callback methods in EJB 3.

Table 14.5 EJB 2 required implementations of many lifecycle methods. EJB 3 allows you to define lifecycle callback methods. This table lists the corresponding methods for EJB 3 JPA that you can use to migrate an entity bean’s

EJB 2 Lifecycle Method

Migrated EJB 3 JPA Entity

tmp6-354

Constructors in the entity class.

tmp6-355

A method annotated with @PostPersist.

tmp6-356

A method annotated with @PreRemove.

tmp6-357

EntityContext is not supported in EJB3 JPA. Candidate for removal.

tmp6-358

A method annotated with @PostLoad as per the application requirement.

tmp6-359

Candidate for removal.

tmp6-360

A method annotated with either @PrePersist or @PreUpdate depending on the application requirement.

If you’re like us, you welcome the move away from all these required lifecycle methods. It’s long overdue!

Finding an alternative to EntityContext

The EJB 2 entity bean provided environment information with the javax.ejb. EntityContext object. EJB 3 entities are no longer components and therefore do not have contexts of their own. This means there is no EntityContext equivalent in EJB 3. You have to migrate the use of EntityContext to one of the appropriate alternatives. One of the most commonly used methods in the EntityContext is the getPrimaryKey method. You can create a business method to expose the primary key of the entity to the caller. As outlined in table 14.3, the setEntityContext and unSetEntityContext methods are now candidates for removal because they are no longer supported.

Business methods

It’s quite possible that you may have business methods in your entity classes that are using JNDI to find other entity beans. Perhaps you are using the ejbSelect method of another entity bean (e.g., ItemBean) in a business method of UserBean. You could migrate this code to the entity class by using a named query of the entity class. This would require grabbing an instance of the EntityManager using JNDI. However, we recommend against the approach of using JNDI code within your entity classes because it will limit its usability to relying on the container. This boils down to a scenario where you cannot test or use it outside the container. We suggest that you take this opportunity to migrate such code to the service layer (i.e., the session fagade).

Next post:

Previous post: