Domain modeling and the JPA (EJB 3)

Often the first step to developing an enterprise application is creating the domain model—that is, listing the entities in the domain and defining the relationships between them.

In this section we’ll first present a primer on domain modeling. Then we’ll explore the ActionBazaar problem domain and identify actors in a domain model, such as objects, relationships, and cardinality. We’ll provide a brief overview of how domain modeling is supported with the EJB 3 Java Persistence API and then build a simple domain object as a Java class.

Introducing domain models

Although you may have been warned that domain modeling is complex, the idea behind it is pretty simple. In effect, a domain model is a conceptual image of the problem your system is trying to solve. Literally, it is made up of the objects in the "system universe" and the relationships or associations between them. As you can guess, an object in a domain model need not be a physical object but just a concept used by your system. A relationship, on the other hand, is an imaginary link between objects that need to "know" about one another. The critical thing to remember is that the domain model describes the objects and how the objects might relate to one another, but not how a system acts on the objects.


We like to think of a domain model as a set of interlocking toy blocks. Each uniquely shaped block in the set is an object. The shape of each block determines how they fit with one another. Each such "fit" is a relationship. In the end, though, you put together the blocks into whatever configuration sparks your imagination. The master plan for putting together the final results forms the business rules of the application. The business rules are implemented by the session beans and MDBs we discussed in previous topics, while the persistence API implements the domain model that the business rules act on.

We won’t talk about domain modeling much further than what is needed for explaining the concepts we just introduced. However, we encourage you to explore the topic further by checking out the excellent books written on the subject of domain modeling, most notably Patterns of Enterprise Applications Architecture by Martin Fowler (Addison-Wesley, 2002). UML class diagrams are the most popular method of creating the initial domain model.Instead, we’ll use the simplest diagrams possible, which might have a shallow resemblance to UML.

The ActionBazaar problem domain

Modeling the entire ActionBazaar domain will introduce complexity that we don’t need in order to explain JPA. To avoid this unnecessary complexity, we are going to develop the core functionality of the ActionBazaar application that is directly related to buying and selling items on bid online.

NOTE Admittedly, this is a slightly unoriginal example. We considered using an example tangential to the central theme of ActionBazaar but decided against it and remained true to the ActionBazaar core concept.

As figure 7.1 shows, at the heart of it ActionBazaar centers on the following activities:

■ Sellers post an item on ActionBazaar.

■ Items are organized into searchable and navigable categories.

■ Bidders place bids on items.

■ The highest bidder wins.

NOTE If you are familiar with use cases and the list looks a lot like use cases, they really are.

In our artificially simplistic scenario, we can pick out the domain objects by scanning the list of activities and looking for nouns: seller, item, category, bidder, bid, and order. Our goal is to identify the domain objects or entities that we want to persist in the database. In the real world, finding domain objects usually involves hours of work and many iterations spent analyzing the business problem. We’ll make our initial diagram by randomly throwing together our objects into figure 7.2.

The core functionality of ActionBazaar. Sellers post items into searchable and navigable categories. Bidders bid on items and the highest bid wins.

Figure 7.1 The core functionality of ActionBazaar. Sellers post items into searchable and navigable categories. Bidders bid on items and the highest bid wins.

Entities are objects that can be persisted in the database. In the first step you identify entities—for example, entities in the ActionBazaar domain.

Figure 7.2 Entities are objects that can be persisted in the database. In the first step you identify entities—for example, entities in the ActionBazaar domain.

Putting in the links between objects that should know about each other (these are the infamously complex domain relationships) will complete our domain model. We encourage you to spend some time looking at figure 7.2 guessing how the objects might be related before peeking at the finished result in figure 7.3.

We won’t spell out every relationship in figure 7.3, since most are pretty intuitive even with the slightly cryptic arrows and numbers. We’ll explain what is going on with the arrows and numbers in just a bit when we talk about direction and multiplicity of relationships. For now, all you need to note is the text describing how objects are related to one another. For example, an item is sold by a seller, a seller may sell more than one item, the item is in one or more categories, each category may have a parent category, a bidder places a bid on an item, and so on. You should also note that although the domain model describes the possibilities for cobbling objects together, it does not actually describe the way in which the objects are manipulated. For instance, although you can see that an order consists of one or more items and is placed by a bidder, you are not told how or when these relationships are formed. But by applying a bit of common sense, it is easy to figure out that an item won through a winning bid is put into an order placed by the highest bidder. These relationships are probably formed by the business rules after the bidding is over and the winner checks out the item won.

The ActionBazaar domain model complete with entities and relationships. Entities are related to one another and the relationship can be one-to-one, one-to-many, many-to-one, or many-to-many. Relationships can be either uni- or bidirectional.

Figure 7.3 The ActionBazaar domain model complete with entities and relationships. Entities are related to one another and the relationship can be one-to-one, one-to-many, many-to-one, or many-to-many. Relationships can be either uni- or bidirectional.

We’ll clarify the concepts behind domain model objects, relationships, and multiplicity next before moving on to the JPA.

Domain model actors

Domain modeling theory identifies four domain model "actors": objects, relationships, the multiplicity of relationships, and the optionality of relationships. Let’s fill in the details that we have left out so far about all four actors.

Objects

From a Java developer perspective, domain objects are closely related to Java objects. Like Java objects, domain objects can have both behavior (methods in Java terms) and state (instance variables in Java). For example, the category domain object probably has the name, creation date, and modification date as attributes. Similarly, a category probably also has the behavior of being renamed and the modification date updated. There are likely hundreds of instances of category domain objects in the ActionBazaar, such as "Junkyard Cars for Teenagers," "Psychedelic Home Decor from the Sixties," "Cheesy Romantic Novels for the Bored," and so on.

Relationships

In Java terms, a relationship is manifested as one object having a reference to another. If the Bidder and Billinglnfo objects are related, there is probably a Billinglnfo instance variable in Bidder, a Bidder instance variable in Billing-Info, or both. Where the object reference resides determines the direction of the arrows in figure 7.3. If Bidder has a reference to Billinglnfo, the arrow should point from Bidder to Billinglnfo. Or suppose Item and Bid have references to each other; an Item has Bids on it and Bids are placed on Items. Signifying this fact,the arrow connecting Bid and Item points in both directions in figure 7.3. This is what is meant by a bidirectional relationship or association between Bid and Item as opposed to a unidirectional relationship or association between Seller and Billinglnfo. Typically, objects are nouns and relationships are verbs such as has, is part of, is member of, belongs to, and so on.

Rich vs. anemic domain models

As we mentioned, domain models are eventually persisted into the database. It might already be obvious that it is easy to make the domain model objects look exactly like database tables. As a matter of fact, this is exactly why data modeling is often synonymous to domain modeling and DBAs (or data analysts) are often the domain experts. In this mode of thinking, domain objects contain attributes (mapping to database table columns) but no behavior. This type of model is referred to as the anemic model.

A rich domain model, on the other hand, encapsulates both object attributes and behavior and utilizes objected-oriented design such as inheritance, polymorphism, and encapsulation.

An anemic domain model may not necessarily be a bad thing for some applications. For one thing, it is painless to map objects to the database. As a rule of thumb, the richer the domain model is, the harder it is to map it to the database, particularly while using inheritance.

Multiplicity, or cardinality

As you can probably infer from figure 7.3, not all relationships are one-to-one. That is, there may be more than one object on either side of a relationship. For example, a Category can have more than one Item. Multiplicity or cardinality refers to this multifaceted nature of relationships. The multiplicity of a relationship can be:

■ One-to-one—Each side of the relationship may have at most only one object. An Employee object can have only one ID card and an ID card can only be assigned to one employee.

■ One-to-many—A particular object instance may be related to multiple instances of another. For example, an Item can have more than one Bid. Note that, taken from the point of view of a Bid, the relationship is said to be many-to-one. For example, many Bids can be placed by a Bidder in figure 7.3.

■ Many-to-many—If both sides of the relationship can have more than one object, the relationship is many-to-many. For example, an Item can be in more than one Category and a Category can have multiple Items.

Ordinality, or optionality

Ordinality, or optionality, of a relationship determines whether an associated entity exists. For example, we have a bidirectional one-to-one association between User and Billinglnfo, and every user need not always have billing information, so the relationship is optional. However, Billinglnfo always belongs to a User and hence the optionality for the Billinglnfo-User association is false. Having established the basic concepts of domain modeling, we can now start discussing how the domain model is persisted using the EJB 3 Java Persistence API and actually begin implementing our domain model.

The EJB 3 Java Persistence API

In contrast to EJB 2 entity beans, the EJB 3 Java Persistence API (JPA) is a metadata-driven POJO technology. That is, to save data held in Java objects into a database, our objects are not required to implement an interface, extend a class, or fit into a framework pattern. In fact, persisted objects need not contain a single inline statement of JPA. All we have to do is code our domain model as plain Java objects and use annotations or the XML to give the persistence provider the following information:

■ What our domain objects are (for example, using the @Entity and @Embed-ded annotations)

■ How to uniquely identify a persisted domain object (for example, using the @ld annotation)

■ What the relations between objects are (for example, using the @OneToOne, @OneToMany, and @ManyToMany annotations)

■ How the domain object is mapped to database tables (for example, using various object-relational mapping annotations like @Table, @Column, or @JoinColumn)

As you can see, although O/R mapping using the JPA (or any other O/R frameworks like Hibernate) is a great improvement over entity beans or JDBC, automated persistence is still an inherently complex activity. The large number of persistence-related annotations and wide array of possible arrangements is a result of this fact. To make it all as digestible as possible, we’ll only cover the first three items in this

SQL-centric persistence: Spring JDBCTemplate and iBATIS

Like many of us, if you are comfortable with SQL and JDBC and like the control and flexibility offered by do-it-yourself, hands-on approaches, O/R in its full-blown, black magic, automated form may not be for you. As a matter of fact, O/R tools like Hibernate and the EJB 3 Java Persistence API (JPA) might seem like overkill, even despite the long-term benefits offered by a higher-level API.

If this is the case, you should give tools like Spring JDBCTemplate and iBATIS a very close look. Both of these tools do an excellent job abstracting out really low-level, verbose JDBC mechanics while keeping the SQL/database-centric feel of persistence intact.

However, you should give O/R frameworks and JPA a fair chance. You just might find that these options make your life a lot easier and OO-centric, freeing you to use your neuron cycles to solve business problems instead.

Topic, leaving the fourth (how the domain object is mapped to database tables) to topic 8. Moreover, we’ll stray from our pattern of presenting and then analyzing a complete example, since the wide breadth of the persistence API would not yield to the pattern nicely. Instead, we are going to explore the persistence API by visiting each step in our list using specific cases from the ActionBazaar example, analyzing features and intricacies along the way. Not straying from previous topics, however, we’ll still focus on using annotations, leaving the description of deployment descriptor equivalents for a brief discussion in topic 11.

Domain objects as Java classes

Let’s now get our feet wet by examining some code for JPA. We’ll pick a representatively complex domain object, Category, and see what it might look like in Java code. The Category class in listing 7.1 is a simple POJO class that is a domain object built using Java. This is a candidate for becoming an entity and being persisted to the database. As we mentioned earlier, the Category domain object may have the category name and modification date as attributes. In addition, there are a number of instance variables in the POJO class that express domain relationships instead of simple attributes of a category. The id attribute also does more than simply serving as a data holder for business logic and identifies an instance of the Category object. You’ll learn about identity in the next section.

Listing 7.1 Category domain object in Java

Listing 7.1 Category domain object in JavaListing 7.1 Category domain object in Java

The Category POJO Q has a number of protected instance fields G Q, each with corresponding setters and getters that conform to JavaBeans naming conventions Q. In case you are unfamiliar with them, JavaBeans rules state that all instance variables should be nonpublic and made accessible via methods that follow the getXX and setXX pattern used in listing 7.1, where XX is the name of the property (instance variable). Other than name and modificationDate, all the other properties have a specific role in domain modeling and persistence. The id field is used to store a unique number that identifies the category Q. The items property stores all the items stored under a category and represents a many-to-many relationship between items and categories. The parentCategory property represents a self-referential many-to-one relationship between parent and child categories. The subcategories property maintains a one-to-many relationship between a category and its subcategories.

The Category class as it stands in listing 7.1 is a perfectly acceptable Java implementation of a domain object. The problem is that the EJB 3 persistence provider has no way of distinguishing the fact that the Category class is a domain object instead ofjust another random Java object used for business logic, presentation, or some other purpose. Moreover, note that the properties representing relationships do not make direction or multiplicity clear. Lastly, the persistence provider also needs to be told about the special purpose of the id property. We’ll start solving some of these problems by using JPA annotations next, starting with identifying the Category class as a domain object.

Next post:

Previous post: