Ask a question
Tuesday, 15 September 2009 09:32

J2EE Design Patterns: The Business Tier

Rate this item
(1 vote)
The Business Tier

Business tiers are about complexity, memory, and scale. Business tiers are complex because they implement the rules the business must follow. The rules themselves can be simple ("mark each item shipped as removed from inventory," "when shipping to Massachusetts, add a 5% sales tax") but the interconnected system of rules can rapidly become more than any one person can easily handle. Memory, in the long-term recollection sense rather than the hardware sense, is important because businesses need to record every activity they participate in. Humans aren't well equipped to do this reliably, at least without tools and time. Finally, business tiers are about scale. Even if process and record-keeping activities are simple enough to be done by hand, repeating them several thousand times over the course of a day is costly, error-prone, and inflexible.[1]

In the business tier, more than anywhere else, you have to keep an eye out for the unexpected. Creating domain models and business logic that meet the growth requirements of the environment presents a challenge to system architects. Even when the initial application requirements may not seem to impose much in terms of complexity, memory, and scale, change is inevitable. Business tiers require a substantial investment, so once created, they tend to be used and extended over the long haul. In fact, we rarely see successful enterprise applications enter an end-of-life stage. They're much more likely to be incorporated as a component of something else. Fifteen years from now there will be a vendor making a lot of money selling adapters to incorporate your old J2EE applications into whatever happens to be the new dominant environment. You'll often do the same thing yourself, integrating existing legacy systems into new J2EE frameworks.
A poorly implemented business tier imposes limitations on a system that fancy user interfaces can't overcome. On the other hand, a difficult user interface, or a middle tier that is slow or difficult to extend, prevents effective use of even the best-designed business and domain logic. A full J2EE application is an integrated whole, however compartmentalized it may be, that makes each tier more or less equally important. The art is in the interfaces that create the smoothly functioning whole. The business logic and domain model are the starting point that everything else grows out of.
  
6.1 The Business Tier
There are several ways to slice up a J2EE application. It's quite common to hear the phrases domain logic, business logic, business object, business tier, and other variants tossed around with wild abandon, resulting in more than a little confusion. What is the business tier? Is the application server part of the business tier, or does it enable the business tier? What about the database? The tables in the database? The servlet container?
All business tiers, as we use the term, have two functions in common. Business tiers:
  • Provide a structured model for application data.
  • Provide procedures for performing business-related activities.
Most also share the following characteristics. Business tiers:
  • Are shared by multiple clients.
  • Provide a framework for transactions, ensuring that the information in the domain model remains in a valid state.
  • Provide a persistence mechanism for application data.
Most enterprise applications ultimately serve multiple clients, whether different types of clients (servlet applications versus Swing GUIs) or multiple instances of the same type (10,000 Swing GUIs, or an array of web servers). Most applications will use some transaction functionality at least once, but transaction implementations can be done via JTA, EJB, JDBC, or raw objects, depending on the needs and desires of the designer. Persistence is commonly associated with the transaction logic, often via JDBC and a database. Chapter 10 is devoted to transactions and concurrency management, so we'll skip lightly over it here.
The persistence mechanism, although we've listed it under the "most" heading, is essentially universal. Of course, the method by which different applications implement the persistence mechanism varies tremendously, from serialized objects to Enterprise JavaBeans, to database tables and JDBC. The business tier itself might be housed in a complex application server or as a humble application in a standalone JRE (or, quite frequently, in the same JRE as the presentation tier).
6.1.1 Business Tier Components
The standard J2EE application model defines a Server Side Business Logic layer, implemented via EJBs or other objects, which optionally accesses Enterprise Information Systems. We don't find that view quite as helpful, because it doesn't address what we actually put into the system: just how we'd implement it.
For the purposes of this chapter and those that follow, we subdivide the business tier into three parts: the visible business tier, the resource layer, and the enterprise layer. The visible business tier is what's exposed to the presentation tier, while the resource and enterprise layers provide the services that allow the visible portion of the business tier to do its job.
Although the business tier can be subdivided, it isn't the same kind of subdivision that we get with the tiers themselves. The coupling between the various components that make up the business tier generally has to be quite tight: you can't create a new set of domain objects and expect all the business logic to work properly. However, with proper compartmentalization, you retain some flexibility. In most applications, the business logic isn't tightly coupled to a particular database, and as a result we can potentially change the underlying database without having to rewrite the business process code.
Figure 6-1 shows a view of the business tier. Not every business tier will look like this, of course. Components higher on the chart access components that are lower on the chart, either directly or through intermediaries. Process logic, for instance, accesses domain objects and the enterprise layer.
6.1.1.1 Business tier components

Domain objects
represent the "nouns" of the application. They're the concrete things that map to real or virtual concepts within the application. Objects (or database tables) represent customers, orders, stock items, user accounts, outstanding invoices, clinical measurements, or anything else that could substitute for one of the blanks in "a ___ is related to a ___."

The business logic reflects the business process. A business process is the set of steps required to fulfill one of the system's use cases, and can be thought of as a "verb" or a system activity. Business processes don't have a life of their own except in the project management sense: once the process is complete, a record may be kept for analysis, but an instance of the process itself only exists while it works towards a particular goal. For example, when an order is shipped, the order process is complete. (The domain object containing the record of the order, however, is permanent.)

Put together, domain objects and business logic are sometimes known as the domain model. They represent the "domain" of an application, including both the physical entities and the processes.
Figure 6-1 subdivides the business logic layer into domain objects and process logic (the business processes). The process logic manipulates the domain objects. In some cases, the process logic is the only part of the application visible to any of the lower tiers. For example, a J2EE application might embed process logic in EJB session beans, or via a web services interface. The session beans or web service backend are responsible for interacting with the domain objects. This is good practice, but it doesn't make sense for every aspect of every possible application.

Both domain objects and business logic are subject to business rules. A business rule might state that a particular order is associated with one and only one customer, or that employees may only report to managers and not to programmers. The business rules for the domain apply regardless of the application. For example, an orders system and an inventory system that deal with the same domain (stock management) could theoretically use the same domain model. The business rules embedded in the model should apply equally to either application. These rules don't show up on the diagram in Figure 6-1, but instead constrain the actions of the various pieces of the business logic layer.
6.1.1.2 Supporting players

The resource layer in a J2EE application is typically a database, but it can include any persistent storage mechanisms, both locally (on disk) or remotely (in messaging, transaction management, and other support systems). Chapter 8 is devoted to the patterns that apply to the resource layer. The resource layer should be largely invisible to the presentation tier, which interacts only with the business logic objects.

Finally, the enterprise layer consists of connections to other systems, whether they're legacy systems, J2EE systems, or web services. Business processes often involve handoffs to external systems. Sometimes these exchanges are handled quickly in near real time (such as a credit card authorization for an online merchant) and sometimes asynchronously (such as a request to approve a mortgage application). Chapter 11 addresses intersystem integration in detail.

Literature on software architecture often mentions business services. In a well-designed application that is properly divided into components that have fully defined interfaces between them, a business service is simply another phrase for a business tier component.
Business Tier Services

A service is a software component that performs an action on behalf of another component. A typical action might involve retrieving a piece of information for a client, or performing a specific operation for that client, often on a remote resource.

Directories are probably the most common software service, and are a good illustration of a service because they provide access to both information and resources. A corporate LDAP directory is an example of a directory that accesses information. Normally, the directory maintains all sorts of information about employees, including simple items like names and phone numbers, as well as more complex relationships, such as whom individual employees work for. A UDDI directory, on the other hand, returns resources: rather than providing information directly, it points an application towards a web service that can help.

When a Java application accesses an LDAP directory, it doesn't manipulate an object representation of that directory. Instead, it issues a request for specific information through the generic Java Naming and Directory Interface (JNDI). The request must explicitly state exactly what information is required (either by providing a specific name or a set of criteria); in response to the request, JNDI returns an object containing the requested information. If the application needs to update the directory, and has permission to do so, it can pass the object back, again specifying exactly how the directory should store it.

In each case, the service interface acts as the medium of exchange. Other business services, including web services, work the same way, fielding requests for information or actions and returning responses.
The most important thing to remember is that web services in particular are not inherently stateful. Each service call contains all the information required to complete a request, whether the service call is requesting the name of an object, asking that an equation be solved, or providing a business transaction to post. Of course, stateful remote components do exist: they're just called distributed objects.

6.2 Domain Objects

The patterns in this chapter focus on important aspects of business tier development. We start with the Domain Object Model, which is at the heart of most large J2EE applications. The Domain Object Model defines an object-oriented representation of the underlying data of an application. The benefits of this approach should be familiar by now: the tiers integrating with the business tier become simpler and are decoupled from the implementation of the business tier, allowing changes to the resource layer level implementation without affecting the UI components. Business processes can be included in the domain object model via methods attached to the entity objects in the model or to specialized objects.
We'll also look at the Composite Entity pattern, which provides a guideline for building domain objects in an efficient way. The goal is to balance flexibility and efficiency by creating object representations that can be used in the most efficient way.

6.2.1 Domain Object Model

The domain model is the portion of the business tier that defines the actual data and processes managed and implemented by the system. The process for creating an effective domain model varies depending on the project, the information available, and the future requirements of the system.

The Domain Object Model pattern is central to most J2EE applications. The pattern is fundamentally simple: create a Java object model that represents the concepts in the underlying domain. This may seem obvious, and you may even question whether it should be considered a pattern at all. It's certainly intrinsic to EJB. On the other hand, it's possible to build applications with J2EE technology that don't use a formalized domain model at all, and it's possible to build a domain object model without using EJB.

Many web applications get along fine without a domain object model. They keep their domain model entirely in the database component, never building an object representation. In this case, the model is relational rather than object-oriented: two-dimensional tables full of data, linked to other tables via a set of shared keys. The application updates the model by executing SQL statements directly from servlets, and produces HTML pages the same way. In some cases, business process information is also held in the database, in the form of stored procedures, or it is embedded in the servlet tier.

In contrast, a domain object model represents the application's entities (which would otherwise be found in database tables) and processes (which would otherwise be scattered throughout the application). The ultimate repository may still be a relational database, and the objects that make up the model are responsible for persisting themselves to the database in an appropriate way. The presentation tier can access the Java objects instead of manipulating the database directly. In building a domain object model, we translate the business model into object terms.

Figure 6-2
shows a simple domain object model for a system that issues government IDs. We'll leave the potential civil liberties issues inherent in this system aside, and focus on the domain modeling issues instead. We have three classes, one for the federal government, one for the state governments, and one for citizens. The federal government can be associated with multiple state governments, which can have multiple citizens. We also have four classes that perform business activities. The Passport Issue class uses the federal government and the citizen classes to issue a passport. The State License Issue class is abstract, and is extended by two other classes that issue particular kinds of state ID cards.

6.2 Domain Objects

The patterns in this chapter focus on important aspects of business tier development. We start with the Domain Object Model, which is at the heart of most large J2EE applications. The Domain Object Model defines an object-oriented representation of the underlying data of an application. The benefits of this approach should be familiar by now: the tiers integrating with the business tier become simpler and are decoupled from the implementation of the business tier, allowing changes to the resource layer level implementation without affecting the UI components. Business processes can be included in the domain object model via methods attached to the entity objects in the model or to specialized objects.
We'll also look at the Composite Entity pattern, which provides a guideline for building domain objects in an efficient way. The goal is to balance flexibility and efficiency by creating object representations that can be used in the most efficient way.

6.2.1 Domain Object Model

The domain model is the portion of the business tier that defines the actual data and processes managed and implemented by the system. The process for creating an effective domain model varies depending on the project, the information available, and the future requirements of the system.

The Domain Object Model pattern is central to most J2EE applications. The pattern is fundamentally simple: create a Java object model that represents the concepts in the underlying domain. This may seem obvious, and you may even question whether it should be considered a pattern at all. It's certainly intrinsic to EJB. On the other hand, it's possible to build applications with J2EE technology that don't use a formalized domain model at all, and it's possible to build a domain object model without using EJB.

Many web applications get along fine without a domain object model. They keep their domain model entirely in the database component, never building an object representation. In this case, the model is relational rather than object-oriented: two-dimensional tables full of data, linked to other tables via a set of shared keys. The application updates the model by executing SQL statements directly from servlets, and produces HTML pages the same way. In some cases, business process information is also held in the database, in the form of stored procedures, or it is embedded in the servlet tier.

In contrast, a domain object model represents the application's entities (which would otherwise be found in database tables) and processes (which would otherwise be scattered throughout the application). The ultimate repository may still be a relational database, and the objects that make up the model are responsible for persisting themselves to the database in an appropriate way. The presentation tier can access the Java objects instead of manipulating the database directly. In building a domain object model, we translate the business model into object terms.

Figure 6-2
shows a simple domain object model for a system that issues government IDs. We'll leave the potential civil liberties issues inherent in this system aside, and focus on the domain modeling issues instead. We have three classes, one for the federal government, one for the state governments, and one for citizens. The federal government can be associated with multiple state governments, which can have multiple citizens. We also have four classes that perform business activities. The Passport Issue class uses the federal government and the citizen classes to issue a passport. The State License Issue class is abstract, and is extended by two other classes that issue particular kinds of state ID cards.
Figure 6-2. Domain Object Model for government IDs
This is a simple example, but it's amazing how many development projects get going without nailing these relationships down as much as possible at the start.
Next, we'll take a look at how we might get to this model.[2]

Of course, there are whole schools of thoughts that oppose "Big Design Up Front." But it's always safer to figure out the fundamentals in advance.

6.2.2 Building an Object Model

The analysis process for building an object model depends on the project, resources available, and processes within a particular organization. We find the following general approach to be both prevalent and useful.
Building an object model for the domain requires a solid understanding of the business foundations underlying the system. Often, developers aren't in a position to supply this information on their own, particularly when they're coming in as consultants or independent contractors. The information has to come from the business users. This process isn't always simple, since the users may be busy, unavailable, or in the case of a company developing a new product, nonexistent. Even when they can be tracked down, they don't always know what they want.[3]

Nothing in this chapter should, however, be taken as an excuse for engineers to run off and develop software without input from the end user community or some reasonable proxy thereof.
6.2.2.1 Define the vision

The place to start is the business requirements for the software. Whole books have been written on the subject of gathering requirements effectively and presenting them as usable specifications. See, for example, Software Requirements by Karl Wiegers (Microsoft Press) and Writing Effective Use Cases by Alistair Cockburn (Addison-Wesley).

We find it helpful to start by creating a vision statement for the domain model. This statement, which can be exceedingly brief, should describe a high-level vision for the domain model, including its purpose and scope. An example might read: "An inventory, customer, and sales management system for use by all of the web-based applications and internal systems at XYZ Corporation." More than a paragraph is probably overkill. The vision statement should address current requirements and potential future needs, but it should take care not to overload the project with speculative features. Vision statements help to boost morale, too. Developers, like most corporate citizens, like to know that they're working on something that's been thought out in advance. A vision statement also helps keep change requests under control, since potential alterations can be evaluated in the context of the product vision.

Let's build towards the domain object model introduced in Figure 6-2. We're going about it a bit backward, since we've already shown you the model, but stick with us here. In our case, the vision statement might be, "The system will manage and issue official forms of identification for every citizen in the United States. It will support the major forms of identification issued by the federal and state governments."
6.2.2.2 Gather the user cases

The next step is to identify the use cases for the application or applications that will follow the domain model. In some situations, these use cases will be in the style introduced in Chapter 2. In other cases, you may need to work backward from a requirements specification. Working from requirements specifications can often be harder than working from pure use cases: the author of the specification may have unknowingly made some design decisions as he spelled out exactly what the system should do. Watch out for these implicit assumptions.

Our example National ID system might have several use cases, including "Issue Passport," "Verify Citizenship," and "Issue State License" (generalized from "Issue State ID" and "Issue Driver's License"). There are several actors involved, as well: the State Department, the local DMV, and citizens of the state and the country. The State Citizen actor generalizes to a Citizen, and the two use cases for issuing state IDs generalize to a parent use case for issuing state level licenses. Figure 6-3 shows a simple use case diagram for this application. Each use case, as we discussed in Chapter 2, needs to be specified with more than a name. For example, the Issue Passport use case might include the following steps:
1.      Verify applicant's identity.
2.      Verify applicant's citizenship.
3.      Take and scan photograph.
4.      Enter passport data into system.
5.      Issue passport.
The Driver's License use case is similar, but involves verification that the applicant has passed her driving test, has a clean driving record, and is a citizen of the state in which she is applying for a license.
6.2.2.3 Find object candidates

The next step is to identify object candidates for each use case. In our example, we need to identify citizens for each use case, and we need to store information about who has been issued a particular ID; a Citizen object is an obvious choice. The State Department and the DMV could have their own objects, but we don't need access to any other aspects of the State Department or the DMV. We do need to know which states citizens are citizens of, so we have a State class, and a Federal class to hold the states.

Citizenship is constrained via a business rule within the domain model: a citizen is a citizen of any polity in whose object they are contained. So, all citizens are federal citizens, and each citizen is also a citizen of exactly one state. This is also an example of a domain boundary for the system: it only applies to the United States, or other countries that assign citizens to two hierarchical categories for purposes of licensing. Countries that devolve these responsibilities to, say, a city within a state would need to modify the model.

We define these relationships in the class diagram by making the associations between Federal, State, and Citizenship objects composite associations, rather than simple associations. Using this approach builds the business rule directly into the domain model, and also means that we've made a trade-off: supporting multiple citizenship or state citizens who are not federal citizens would be difficult in the future.

We now have the three domain objects in the system: the federal government, the state governments, and the individual citizens. These are our "nouns." We also define four classes, one of which is abstract, to represent the use cases we're implementing. In this case, we've kept things relatively simple and built a class to handle each activity. The two state-level activities share a superclass that contains methods common to both: for instance, a method to verify state citizenship.
We're now more or less done: the resulting class hierarchy is the one we introduced in Figure 6-2. In designing all of these classes, we've tried to keep one of the fundamental principles of object-oriented programming clearly in sight: the separation of responsibilities. Each class should be responsible for as little as possible, and should only be responsible for activities that bear on it directly.

For example, the Citizen class in the example above includes methods to retrieve the licenses and IDs created by the other classes, but doesn't include mechanisms for issuing passports and drivers' licenses. While these activities affect individual citizens, carrying them out is not the citizen's responsibility. However, the Citizen class might include a method, such as verifyResidence( ), which could be used in the license issue process.
Domain Models and Iterative Development

One of the great things about Java is that it makes iterative development a lot easier than some earlier technologies. By delivering fast-paced releases that prioritize key functionality, developers can get a system out faster and incorporate user feedback and testing in more places during the development cycle. Java, and object-oriented languages in general, make it easier to build frameworks and fill in specific functionality as you go.

This approach raises some questions about domain model development, though. If, for example, the use cases that support customer account management won't be added to a system until the third or fourth iteration, should the components of the domain model that will be required by these use cases (and only these use cases) be incorporated into the initial design, or can they be incorporated later? To a certain extent, you can do both. Isolating individual tiers reduces the affect of changes made to the domain model later on: the presentation tier can remain ignorant of even substantial changes in the underlying database schema.

In general, we think it makes sense to consider all of the use cases when designing a domain model, even if you won't be implementing the user interfaces, presentation tiers, or business logic right away. Entity models, however well compartmentalized and designed, are always something of a pain in the neck to modify.

One technique that makes life easier is to put off finalizing the difficult-to-change aspects of the domain model, which are usually related to the persistence layer. Every aspect of the system is a use case, after all, even if it's not a "functional" use case. If persistence to a database table structure is a requirement, it can be postponed until later in the process, when the object model has had a chance to settle down. For development in the interim, you can serialize the object hierarchy to disk or use some of the approaches we'll discuss in Chapter 8. This method involves a bit more coding, but it can shorten the overall development cycle, since the domain model will be based more on feedback and less on sitting in a conference room trying to figure everything out with no practical data.

Designing domain models for the future involves a tricky balance of doing work now for a potential payoff later. A helpful approach when making any domain modeling decision is to consider what opportunities you might be closing off by
adopting a particular approach.
6.2.2.4 Implementing a domain object model in J2EE

Traditionally, domain object models in J2EE are based on EJBs. However, just because EJBs exist doesn't mean that you need to use them. EJBs have two major advantages over Plain Old Java Objects (POJOs). First, they can be accessed remotely: the EJB server can be located on one system while the client is located on another. In design parlance, this means they are remoteable. Second, EJBs are transactional: a set of operations performed on one or more EJBs can be made contingent on the success of all the operations. We'll discuss transactions in much more depth in Chapter 10.

For enterprise applications with a Swing GUI interface, the ability to access objects hosted remotely is often vital: without this ability, the client will have to maintain its own connection with the resource tier, and changes to the business tier implementation will involve updating every single deployed client, creating an access control and scalability nightmare.

EJBs often make sense when you need a coarse-grained entity model, remote access, and integral transaction support. Typical situations in which EJBs are appropriate include applications that are geared toward frequent and complex transactions, applications in which the domain model will be accessed by a number of systems at once, either via clustered web servers or a large number of Swing GUI clients, and applications that spread transactions across multiple services (databases, messaging servers, etc.). For more on when to use and not use EJBs, see the "Everything Is an EJB" antipattern in Chapter 12.

Plain Old Java Objects can be a little more work to code, but they are easier to deploy, since they don't require an EJB container. Because they don't provide a remote interface, they can be more efficient than EJBs when distributed capabilities aren't required. For the same reason, regular objects lend themselves to a more finely grained object model than EJBs do, since each regular object maps to a single object instance (EJBs require four or more). In many web applications, the same server can run the POJO model and the servlet container, keeping everything in the same JVM.

The tradeoff is that you need to support transactions on your own, rather than delegating to the EJB container (we'll look at strategies for dealing with this in Chapter 10). POJO models can also be difficult to cluster effectively, although the greater efficiency of this approach for many applications can reduce the need for clusters in the first place, at least for scalability purposes. Most modern databases, running on appropriate hardware, easily keep up with the load imposed by a high volume site, assuming the data model was designed properly. Since a POJO object model lives in the same JVM as the web tier, it's easy to cluster several web servers and point them to the same database, provided you have the right concurrency design.

The other nice thing about a POJO object model is that you're not stuck with it. If it turns out that you need an EJB interface after all, it's relatively easy to wrap BMP Entity and Session Beans around your existing objects and move them into an EJB server.

Some applications don't need to expose the entire data model (as found in the database) as Java objects. We'll look at strategies for interacting directly with relational databases in the next chapter.

6.2.3 Composite Entity/Entity Façade Pattern

One common mistake is mapping each table in the underlying database to a class, and each row in that table to an object instance. It's easy to fall into this trap when developing Enterprise JavaBeans using Container Managed Persistence, but it can happen just as readily with non-EJB technologies like Java Data Objects, O/R mapping tools, or coding from scratch. A good data model can actually make this temptation worse.

In the EJB world, a profusion of entity beans has severe performance consequences. Each bean requires not one but several objects to support it, and the server must do more to maintain the integrity of each bean and manage resources effectively. Since clients need to access a large number of distinct entity beans in order to accomplish any given task, communication overhead causes performance degradation proportional to the number of objects involved (see the Round-Tripping anti-pattern in Chapter 12).

These issues can be ameliorated using the Composite Entity pattern, which is also known as the Entity Façade pattern.[4] We'll see a few more façade patterns over the next couple of chapters, all based on the GoF Façade pattern. The Façade pattern provides a simple interface to a complex system: one object fronting for several objects or several database tables.

This pattern is referred to as Entity Façade in Oracle's BC4J application framework.

Composite entities are simply coarse-grained domain objects. When implementing a system using EJB, rather than mapping one bean class to each table and one bean instance to each row, a Composite Entity will collect information from multiple tables and multiple rows into a single entity bean. The entire domain model may still be represented, but not as a direct mapping to the underlying persistence structure.

Composite entities aren't the exclusive province of Enterprise JavaBeans. Any object representation of a domain model entity can use this approach to make itself more efficient and easier to use. Clients accessing composite entity objects have an easier time manipulating the domain model, since they have to manage fewer EJB instances at once. This is particularly the case when the database design has already been defined and can't be changed, either due to legacy system considerations or conflicting requirements.

On the implementation side, using a composite entity allows you to improve performance in at least two ways. First, the smaller number of entity beans reduces the amount of network activity required between the client and the server, as well as between the various beans within the server. With fewer objects in memory, a given quantity of computing resources can handle that many more connections. Second, mapping multiple tables to a single bean allows you to take advantage of the capabilities of the underlying database to merge information at the SQL level rather than the object level.
6.2.3.1 A composite entity schema

Let's look at a simple composite entity schema, which we'll use in the next few chapters. The example is the core of a data structure for managing patient visits at a small hospital. We will track patients, patient addresses, patient visits, notes recorded at each visit, staff members involved in a visit, and notes on the procedures that were performed.

There's no central table in this example. Instead, the tables queried depend on the needs of the application. The database structure is normalized: any time an entity within the database, such as a patient, visit, address, or staff member is referenced in more than one place, it is pulled out into a new table with a separate primary key (we'll talk more about primary keys in Chapter 8). Similarly, data with uncertain cardinality[5] is also pulled into separate tables, with a reference back to the primary key of its logical parent. For example, a patient may have multiple addresses: Home, Office, Billing, Insurance, and so forth. Rather than add fields to the Patient table for each of these, we create a new table, PATIENT_ADDRESS, linked to the Patient table via a primary key. This allows us to add all the addresses we want. We do the same thing with visit notes, which are stored in the VISIT_NOTES table and linked to the VISIT table and the
STAFF table (since there can be multiple visit notes per visit, and each visit note could be created by a different staff member, such as a radiologist or nurse). Figure 6-4 shows an illustration.

The simplest way of mapping this schema to an EJB object structure is to create a new EJB entity bean type for each table. This process allows us to easily use Container Managed Persistence, and allows simple remote updates to each type of data. On the other hand, it results in a profusion of entity beans. A healthy patient probably averages one or two visits a year, and sick patients will generally visit much more often. So the average number of yearly visits may be closer to four or five. Each visit might have 10 or more visit notes associated with it, depending on what procedures were performed. That means each patient could produce 40 or 50 new entities a year. These add up fast, since a single hospital might serve 10,000 or more patients (most of them just pop in for 20 minutes a year). Of course, a well designed EJB container will manage to avoid keeping most of this material in memory at all times, but it's still an awful lot of objects. That's the problem at the macro scale.

The An-Entity-Bean-for-Everything approach also causes problems at the micro scale. Remember that each time you access a remote EJB, you incur a network performance penalty that can be measured in milliseconds. A web page that requires accessing 40 different EJBs will take much longer to generate than one that requires 4, with a corresponding impact on your budget for application servers.

Figure 6-5
shows the hospital visit object model using a set of composite entities. There are still two classes of entity bean: the Patient bean and the HospitalVisit bean. The HospitalVisit bean contains objects representing the visit date, the attending physician, and all of the procedures performed during the visit. The Patient entity bean contains an Address object, and has a one-to-many relationship with a set of HospitalVisit entity beans.

When the EJB container instantiates the HospitalVisit bean, the bean loads all of the associated visit notes, as well as the staff information for both the attending physician and for each visit note. This process may take two or three queries, but it can be optimized for performance. For example, the visit note information and visit note staff information can be retrieved with one SQL statement. Here's a simple approach to building out the objects (we'll see much more of this in Chapter 8).
// Assume visit_id variable containing the visit primary key
 
Connection con = getConnection( );
Statement stmt = con.createStatement( );
ResultSet rs = stmt.executeQuery("select VISIT_DATE, FNAME, LNAME from " +
        "VISIT, STAFF WHERE VISIT.VISIT_ID = "+visit_id+" AND STAFF_NO = SEEN_BY");
 
if(rs.next( )) {
        // ... Read visit information
}
 
rs.close( );
 
rs = stmt.executeQuery("select NOTE_DATE, NOTE, FNAME, LNAME from " +
        "VISIT_NOTES, STAFF where VISIT_ID = " +visit_id+" AND STAFF_NO = NOTE_BY");
 
while(rs.next( )) {
        // load visit notes
}
// etc.
We leave the Patient and HospitalVisit objects as entity beans because they might need to be associated with a variety of other objects (such as bills or HMOs). We also need something that external components can access. The individual procedures and addresses, on the other hand, are not necessary outside the context of the entity beans that control them.

The StaffMember class is shown twice on the diagram to indicate that a particular instance of the object isn't shared between visits and notes. Like the VisitNote and Address objects, a StaffMember object is created at need by the parent object.

In EJB applications, composite entities are more difficult to implement using Container Managed Persistence, although it's certainly possible. For easier portability, it often makes more sense to use Bean Managed Persistence. In the next chapter, we'll look at some database-related patterns that make it easier to build both BMP and POJO entity objects, and in Chapter 9 we'll see some patterns designed to further reduce network traffic and to improve the separation of the entity model and the business logic.
 
Last modified on Wednesday, 23 September 2009 21:18
Vicky

Vicky

E-mail: This e-mail address is being protected from spambots. You need JavaScript enabled to view it
More in this category: Doing Portal Administration »