JaVa
   

Where to Perform Data Access

Now that we've considered some major data access issues, let's consider the key architectural decision of where to perform data access in a J2EE app. Let's survey the options for accessing data sources in J2EE. We'll look at the recommended options in more detail in later chapters.

Data Access in the EJB Tier

Most tutorials on J2EE recommend performing data access from EJBs. In a distributed J2EE app this is sound advice; in this case, code in the distributed web containers should depend only on the architectural tier directly beneath them (the remote EJBs), and not communicate independently with data sources. However, in collocated apps there is a less compelling case of performing data access from EJB. The advantages of performing data access from EJBs are:

The disadvantages are all the drawbacks of EJB (such as complexity) we've previously discussed, plus the serious consideration that data access code is likely to be hard to test, as it depends on an EJB container. Let's look at the options for data access in the EJB tier.

Entity EJBs

An entity bean is a standard J2EE component intended to support access to persistent data. An entity bean layer formalizes the good design practice of decoupling business logic from persistence logic. It is (at least theoretically) independent of the underlying data source. Whatever data source we use, a layer of entity beans objectifies it. In this model, entity beans will expose local interfaces, while the business objects will normally be session beans. However, any objects collocated in the same JVM can work with the entity beans through their local interfaces. Entity beans are a very basic O/R mapping solution. While they are guaranteed to be available by the EJB specification, they neglect most of the O/R mapping challenges we listed earlier. Object inheritance is forbidden. Data can only come from a single table. Entity beans don't allow us to access aggregate functions in the database without writing custom code, effectively subverting the abstraction they exist to provide. However, EJB 2.0 CMP does support object relationships (EJB 1.1 did not).

Important 

Entity beans in EJB 1.1 have limited functionality, and inferior performance, compared with entity beans written with the EJB 2.0 CMP contract As the CMP 2.0 contract differs from the CMP 1.0 contract, CMP entities require code changes to migrate from EJB 1.1 to EJB 2.0. When using an EJB container that does not support EJB 2.0, don't use entity beans.

Although given the special blessing of the EJB specification for data access, entity beans are perhaps the most controversial technology in J2EE. We'll discuss the pros and cons of using entity beans in more detail in the next chapter, but the following disadvantages rule out their use to solve many J2EE data access problems (some of these disadvantages apply to any simple O/R mapping):

The essential contradiction in using entity beans for data access is arguably that EJBs - due to the complexity of accessing them and their relatively heavyweight nature - are best considered as components, rather than ordinary objects. Data access usually requires much finer granularity than EJBs can efficiently deliver.

Important 

Entity beans can be effective in some J2EE architectures, but they're not the ideal abstraction between business logic and physical data store. If session beans access entity beans directly, session beans risk becoming tied to a particular schema. It's also hard to replace the entity bean layer with another approach if performance proves to be a problem.

Session EJBs and Helper Classes

Even if we choose to use EJB and implement business logic in session EJBs, we're not forced to use entity beans for data access. Session EJBs are business logic components. This means that they shouldn't deal with the details of data access. However, this leaves the option of using session beans to control data access, and using the DAO pattern to abstract the details of that access. This is a very flexible approach. Unlike using entity beans, which commits us to one approach, we retain control of how persistence is handled. DAOs can use any persistence API, such as JDO, JDBC, a proprietary mapping framework, or even entity beans. This flexibility (and the reduced overhead compared with the entity bean infrastructure) often leads to better performance than using entity beans. The only difference between using the DAO pattern from session beans and from other types of business object is the availability of declarative transaction management. Often the same DAOs will work inside or outside an EJB container.

Note 

This approach is sometimes referred to as Session Managed Persistence (SMP), in contrast to entity bean CMP and BMP. I don't much like this term, as it implies that the persistence code is actually contained in session beans - a poor implementation choice. Also, the DAO approach isn't tied to the use of EJB.

Data Access in the Middle Tier without Using EJB

As we've seen, J2EE web apps can have a distinct middle tier of business objects without using EJB (EJBs are the only choice for the middle tier in distributed apps with remote clients). This means that we can have middle tier business objects running inside a J2EE web container, but which are not web-specific (in fact they can also support remote access via web services). Such objects have access to programmatic global transaction management with JTA, and connection pooling (J2EE web containers, like EJB servers, provide connection pools, accessible to user code with JNDI lookup. This means that we don't need to use an EJB container to access enterprise data). Such business objects can use any data access strategy available to J2EE apps. Typically, they will use an O/R mapping framework, such as JDO or TopLink, or a resource-specific API, such as JDBC. They lack the option of declarative transaction management, but this approach offers good performance (as it avoids the overhead of EJB) and is easy to test. Typically, data access objects used in the web container depends only on the ability to access aJDBC datasource viaJNDI or an O/R mapping framework. Such requirements can easily be met by test harnesses, unlike EJB container services. Such data access without EJB is a good option for collocated apps when:

In a collocated app, there's no need to perform all data access in the same place. For example, it's legitimate to perform transactional data access from EJBs (to leverage CMT) and non-transactional data access from objects in the web container (because it's simpler and faster). We'll adopt this mixed approach in the sample app.

Data Access in the Web Tier

In contrast, data access in the web tier (the logical architectural layer concerned with presenting a web interface) is a poor design choice. Business objects running in the web container should be distinct from web tier components, will depend on the Servlet API.

Servlets and Web-Specific Classes

There is no justification for performing data access from web-specific classes. There's no reason that data access objects should be tied to the Servlet API. This will prevent their use in an EJB container if required. UI code should also be shielded from data source implementation issues: changing a table or column name in an RDBMS, for example, should never break a web interface. Data access from web-specific classes is unnecessary, as there should be a layer of business objects available to them.

Data Access from JSP Pages

However, there is still one worse option for performing data access. The least attractive data access option in J2EE systems is data access from JSP pages. It tends to lead to problems with error handling and loss of the distinction between business logic, data access and presentation. Yet it is surprisingly widespread, so we can't ignore it. In the early days of JSP, JSP "Model 1" systems were common. Many developers attempted to replace servlets altogether with JSP pages, partly for the enhanced authoring convenience. JSP pages often contained data access code, along with much of the rest of the app. The results were appalling. Today there's wide awareness of the value of MVC concepts in Java web apps (we'll discuss this issue in detail in s 12 and 13). However, with the introduction of custom tags in JSP 1.1, welcome though they were in other ways, data access from JSP pages has once more raised its ugly head. JDBC access from custom tags is superficially appealing, because it's efficient and convenient. Consider the following JSP fragment from the JSP Standard Tag Library 1.0 specification, which transfers an amount from one account to another using two SQL updates. We'll discuss the JSP STL Expression Language in . The ${} syntax is used to access variables already defined on the page:

 <sql:transaction dataSource="${dataSource}">
 <sql:update>
 UPDATE account
 SET Balance = Balance - ?
 WHERE accountNo = ?
 <sql:param value="${transferAmount}"/>
 <sql:param value="${accountFrom} "/>
 </sql:update>
 <sql:update>
 UPDATE account
 SET Balance = Balance + ?
 WHERE accountNo = ?
 <sql:param value="${transferAmount)"/>
 <sql:param value="${accountTo}" />
 </sql:update>
 </sql:transaction>


Now let's consider some of the design principles such a JSP violates and the problems that it is likely to produce:

If there is any place for data access from JSP pages using tag libraries, it is in trivial systems or prototypes (the authors of the JSP standard tag library share this view).

Important 

Never perform data access from JSP pages, even when it is given the apparent respectability of a packaged tag library. JSP pages are view components.

JaVa
   
Comments