Simplifying J2EE and EJB Development with BC4J

Steve Muench, BC4J Development Team
April 2002

Contents

        Introduction
                J2EE Design Patterns
                Putting the Design Patterns into Practice In Your Own Applications
        Hand-Coded vs. Framework-Based J2EE Approaches
                Simple Master/Detail JSP Page from the Pet Store Demo
                How You Might Approach Building a Framework Yourself
                Implementing the Same Pet Store Demo Page Using BC4J
        Streamlining EJB Development with BC4J
                Among Many EJB Architectures, One Stands Out For Performance
                Overview of the BC4J Data Access Objects Facilities
                Drilling Down Into the BC4J Data Access Objects
                What Kinds of EJB Session Beans Can You Build with BC4J?
                Haven't Embraced EJB Just Yet? Start By Deploying in Local Mode
                What Client Technologies Can You Couple with BC4J?
                How Does EJB 2.0 Change the Picture?
                Conclusion
        BC4J Design Pattern Catalog
        Frequently Asked Questions

Introduction

Over the last several years, developers have increasingly made the leap to standards-based, multi-tier application development. The majority of companies making this move are standardizing on the Java™ 2 Platform, Enterprise Edition (J2EE) so their developers can leverage facilities like:

These J2EE technologies and API's provide the enabling ingredients to build enterprise applications that deploy to any J2EE-compliant application server and use any SQL-compliant relational database. However, as any seasoned J2EE developer will tell you, there is a major difference in effort between creating a J2EE-compliant application, and delivering one that is modular, performant, and scalable.

This paper explains how Oracle's J2EE-compliant Business Components for Java (BC4J) framework considerably simplifies delivering solutions that exploit the full set of J2EE technologies above by providing an off-the-shelf implementation of the numerous additional design patterns you would normally have to code by hand to achieve this goal. In fact, many of Oracle's own applications development teams count on BC4J to deliver highly functional, well-performing J2EE applications in record time. A growing number of internal and external teams leverage BC4J for their J2EE development because as we'll see below, the amount of "application plumbing" code required for the typical J2EE application is a lot more than first meets the eye. Since Oracle has made a substantial and long-term investment in the J2EE platform, the BC4J framework and the Oracle9i JDeveloper development environment are key parts of Oracle's current and future Java strategy to improve productivity for developers targeting the J2EE platform.

J2EE Design Patterns

Since March of 1998 when EJB 1.0 first came on the scene, developers have learned a lot from their initial attempts to put J2EE technology into practice in real-world applications. These pioneers fed their experience back into the EJB development community as a set of best-practice coding techniques called the "J2EE Design Patterns". Many are listed and briefly described at Sun's J2EE Design Patterns web site. These guidelines begin where many EJB tutorials end, suggesting when and when not to apply what you've learned in the tutorials to achieve optimal results. In order to avoid the painful performance pitfalls that await the uninitiated, you and your team must study, understand, and apply these design patterns as you develop your own J2EE applications.

Fortunately, many of the techniques you need to learn are outlined in books like:

as well as in similar works by other authors. In addition to reading a good book or two on the subject, you can study the source code of Sun's Java Pet Store Demo for additional inspiration by observing how their developers put the design patterns into practice in this sample application.

Regardless of the kind of J2EE application your team is being asked to deliver, in the Pet Store Demo you'll find example code illustrating most of the common tasks all real-world applications have to perform, like:

In fact, a careful inventory of the Pet Store Demo source code reveals example implementations of many of the J2EE Design Patterns, like the:

  1. Data Access Objects Pattern

    which avoids unnecessary marshalling overhead by implementing dependent objects as lightweight, persistent classes instead of each as an Enterprise Bean,

  2. Model/View/Controller (MVC) Pattern

    where an "application object" exposes the data model of the application in a way that is cleanly separated from the layout code that presents the data,

  3. Session Façade Pattern

    which avoids inefficient remote client access of Entity Beans by wrapping them with a Session Bean,

  4. Value Object Pattern

    which avoids unnecessary network round-trips by creating one-off transport objects to group together a set of related attributes needed by a client program,

  5. Page-by-Page Iterator Pattern

    which avoids sending unnecessary data to the client by breaking a large collection into chunks for display, and the

  6. Fast-Lane Reader Pattern

    which avoids unnecessary overhead for read-only data by accessing JDBC API's directly.

As design patterns, these guidelines don't impose a particular implementation approach. There are many valid ways, ranging from simple, hand-coded solutions to ones leveraging more sophisticated, generic frameworks. Typically the difference between the approaches lies in the amount of work required of the individual developer. Understandably, as an example application built for learning purposes, the Pet Store Demo illustrates one possible approach to implementing the patterns in the context of a simple Web storefront application.

Putting the Design Patterns into Practice In Your Own Applications

Of course, reading books and studying sample code can only take your team a small part of the way to the goal line. When the time comes to begin writing your own J2EE applications, there are two basic approaches you can use to put the J2EE Design Patterns into practice:

  1. Implement the design patterns manually...

    writing and debugging the code for each occurrence of each pattern code by hand, or

  2. Apply a framework of helper-objects...

    that implement the design patterns for you in a generic way.

After examining the 200+ classes that comprise the fairly straightforward Java Pet Store application, it's easy to appreciate that implementing all of these best-practices design patterns entails writing a substantial amount of application plumbing code. Smart teams seek to minimize the amount of time spent writing and debugging this kind of code, preferring instead to dedicate their time to writing great business logic and user interfaces that differentiate their business from their competitors'. The framework-based approach described above is in line with Sun's own recommendations from their J2EE Blueprints book:

"Large scale development of object-oriented software requires frameworks. It is important to have a framework, so that every time the design requires two objects to interact, a developer does not have to come up with a whole new notion of how the interaction works out.” (J2EE Blueprints, Section 10.2.2.2)

A framework-based approach offers obvious productivity advantages, and scales better as the number of developers on the team begins to grow. Rather than teaching each developer how to hand-code all the patterns, each is trained instead in how to apply the framework objects to implement the solution. The typical decision you and your team have to make is whether to buy an off-the-shelf framework or build one yourselves.

Inevitably, teams that don't use an off-the-shelf offering end up gradually building their own team-specific framework over time as they realize more and more opportunities to generalize coding patterns into helper classes. This piecewise approach to cobbling together a team-specific framework has some downsides, however. It sacrifices the cohesiveness that is possible when the overall design of the framework is architected from the outset to provide a well-known set of collaborations like the J2EE design patterns require. Furthermore, building a framework yourself typically means dedicating and motivating a portion of your development resources to work full-time on generic application plumbing code to benefit the rest of the team. In practice, many teams that begin down this "roll your own" path quickly realize that the job requires a heroic effort and is a huge time sink, even with the best intentions and brightest staff.

Hand-Coded vs. Framework-Based J2EE Approaches

Since designing, authoring, debugging, documenting, delivering, and maintaining a J2EE design patterns framework takes a significant amount of time and effort, more and more teams are leveraging off-the-shelf J2EE frameworks like Oracle's Business Components for Java (BC4J) that implement the patterns for them so they don't have to. This approach gives them a decisive leg-up in getting their J2EE applications built, deployed, and enhanced more quickly.

However, if you have never used a framework-based approach to implementing the J2EE Design Patterns, it may not immediately be clear what type of development effort a framework can save you. To get a better feel for the coding effort the design patterns require, let's dissect a simple example from the Java Pet Store Demo and then illustrate how the same example would be implemented using a J2EE framework like BC4J.

Simple Master/Detail JSP Page from the Pet Store Demo

In the Pet Store Demo, a group of JSP pages provides the user interface allowing a user to carry out the task of browsing the store catalog. The  product.jsp page is a typical example of one page in this group. Since it displays master/detail business information, it is similar to many pages in your own web applications. The Pet Store demo examples in this whitepaper correspond to the 1.1.2 version of the demo.

After including the standard Pet Store banner at the top, the page displays the name of a product, like "Chihuahua", then lists the detail items for sale in the store corresponding to that product type. This results in a page whose dynamic content looks like what's shown in Figure 1.

Dynamic master/detail content from Pet Store Demo JSP page
Figure 1: Dynamic master/detail content from Pet Store Demo JSP page

A simplified version of the  product.jsp that produces these results is shown in Example 2. To clarify that the tag libraries in use here are not a built-in part of the J2EE platform, we've changed the  j2ee prefix used in the demo pages to use the more meaningful  petdemo prefix instead.

<%-- Product.jsp: Lists all items in the inventory for a particular product type.  --%>
<%--              Note! Renamed "j2ee" tag library prefix to "petdemo" for clarity --%>
<%@ taglib uri="/technology/WEB-INF/tlds/taglib.tld" prefix="petdemo" %>
<%@ page import="com.sun.j2ee.blueprints.shoppingcart.catalog.model.Product" %>
<jsp:useBean id="catalog" scope="application"
             class="com.sun.j2ee.blueprints.petstore.control.web.CatalogWebImpl"/>
<%
  Product product = catalog.getProduct(request.getParameter("product_id"));
%>
<petdemo:productItemList numItems="3" productId='<%=request.getParameter("product_id")%>'>
  <font size="5" color="green"><%= product.getName() %></font>
  <table border="0" bgcolor="#336666">
    <tr background="../images/bkg-topbar.gif">
      <th><font color="white" size="3">Item ID</font></th>
      <th><font color="white" size="3">Item Name</font></th>
      <th><font color="white" size="3">Item Price</font></th>
    </tr>
    <petdemo:items>
      <tr bgcolor="#eeebcc">
        <td><petdemo:productItemAttribute attribute="id"/></td>
        <td>
          <petdemo:productItemAttribute attribute="productAttribute"/>
          <petdemo:productItemAttribute attribute="name"/>
        </td>
        <td><petdemo:productItemAttribute attribute="listcost"/></td>
      </tr>
    </petdemo:items>
  </table>
</petdemo:productItemList>
Example 2: Source code for a simplified version of the Pet Store Demo's Product.jsp page

We can see from the  <jsp:useBean> tag that the  product.jsp page uses the  CatalogWebImpl bean. This class implements the application object in a Model/View/Controller pattern by centralizing access to the collections of data needed by the web tier to render pages for a specific application task. In this case, the task is browsing products, items, and categories from the store catalog. This class exposes the task-specific data model through methods like:

These methods allow the Web tier developer to access either a single data item or a collection depending on the situation. The  product.jsp page calls  getProduct() to retrieve an instance of a  Product value object corresponding to the ID passed in the HTTP parameter named  product_id. To display the name of the product in the page, we see the Java scriptlet  <%=product.getName()%> used later in the page, which calls the  getName() getter method.

To show the list of specific product items corresponding to the selected product, the page uses a custom tag library containing tags like:

Notice that to coordinate the master/detail relationship between Product information and Item detail information, the page author passes the  product_id parameter value from the master as the value of the  productId attribute on the  <petdemo:productItemList> tag, using a JSP scriptlet:

<petdemo:productItemList numItems="3" productId='<%=request.getParameter("product_id")%>'>

It's important to note that each of these tags is specific to the Pet Store Demo product item list and requires code similar to that found in the demo source code files  ProductItemListTag.java,  ItemsTag.java, and  ProductItemAttributeTag.java, respectively. These tags hide the data binding and formatting code from the JSP page developer. For example, the  ProductItemAttributeTag.java class contains code like that shown in Example 3 (comments added).

// handle the <petdemo:productItemAttribute attribute="XXXX"/> tag
if (attribute.equalsIgnoreCase("name")) {
  return (product.getName());
} else if (attribute.equalsIgnoreCase("productattribute")) {
  return (productItem.getAttribute());
  // ...etc...
} else if (attribute.equalsIgnoreCase("listcost")) {
  // FORMAT the value of the list cost as currency before returning
  return JSPUtil.formatCurrency(productItem.getListCost(), locale);
} else if (attribute.equalsIgnoreCase("description")) {
  return (product.getDescription());
  // ...etc...
Example 3: Data binding/formatting code from the <productItemAttribute>tag implementation

Under the covers, these tag implementation classes also use the  CatalogWebImpl application object to access the collections of  Item value objects needed to display the details on the page.

As recommended by the Data Access Objects pattern, the data access code is isolated into a separate class for ease of maintenance, so the  CatalogWebImpl class turns around and uses the  CatalogDAOImpl class that actually executes SQL queries using JDBC code to retrieve the data. Here the demo illustrates its implementation of the Fast-Lane Reader pattern, where the application object in the web tier consciously avoids using EJB Entity Beans to access store catalog data, going directly to JDBC instead.

Among other things, the code in the  CatalogDAOImpl class embeds the two SQL statements that will be executed to retrieve the data needed by the  product.jsp page. The  getProduct() method in  CatalogDAOImpl contains a line like

String qstr = "select productid, name, descn " +
              "from " +
              DatabaseNames.getTableName(DatabaseNames.PRODUCT_TABLE, locale) +
              " where " +
              "productid='" + productId + "'";

to retrieve a product by ID, while the  getItems() method contains this line:

String qstr = "select itemid, listprice, unitcost, " +
              "attr1, attr2, a.productid, name, descn " +
              "from " +
              DatabaseNames.getTableName(DatabaseNames.ITEM_TABLE, locale) +
              " a, " +
              DatabaseNames.getTableName(DatabaseNames.PRODUCT_TABLE, locale) +
              " b where " + "a.productid = '" + productId +
              "' and a.productid = b.productid "+ " order by name";

which joins informaton from the PRODUCT and ITEM tables needed to display the details. Significant additional code in  CatalogDAOImpl.java is also responsible for implementing behavior like:

  1. Obtaining a database connection
  2. Creating a JDBC Statement
  3. Executing the query
  4. Skipping over rows from previous pages (part of the Page-by-Page Iterator implementation)
  5. Constructing  Item value objects for the result set rows on the current page
  6. Cleaning up the JDBC resources
  7. Returning a list of these Items objects to the caller

The Pet Store demo comes with full source code, so open up these classes yourself and take a look. What might come as a surprise is that all of this code must be written to support each query executed by the application. Figure 4 highlights the amount of one-off application plumbing code that is required to display master/detail information on a simple JSP page using a hand-coded approach to the J2EE Design Patterns.

Code required to implement a master/detail page following J2EE Design Patterns
Figure 4: Code required to implement a master/detail page following J2EE Design Patterns

Specifically, the Pet Store Demo's approach to implementing the design patterns demonstrates that you have to implement:

  1. A task-specific MVC Application ObjectCatalogWebImpl) to cleanly separate the data model needed to implement the client display for your task (e.g. the set of JSP pages for the "Browse the Store Catalog" task)
  2. A Data Access Objects implementation class ( CatalogDAOImpl) to isolate the Fast-Lane Reader JDBC database access code, and to implement the Page-by-Page Iterator behavior by skipping over rows from previous pages while fetching data, and returning a page-sized list of rows for the current page.
  3. Two Value Object classes ( Product,  Item) to transfer the respective database query result rows for products and items queries,
  4. Custom JSP tags ( ProductItemListTag,  ProductItemAttributeTag) to implement data binding and formatting code in a layer that hides these coding details from the JSP page authors.

And all these steps (along with the code required behind them) were necessary just to get one product and a list of its detail items on the screen!

Perhaps the most disappointing news is that none of these classes is reusable when the time comes to display some other data like Customer information on a JSP page. You have to replicate the code for all the steps above for the customer information, and indeed for each different view of business information that needs to be surfaced to web client displays. Quite a workout!

It's worthwhile to point out that when developers hand-code a similar solution over and over, in the interest of time they are likely to cut corners. In fact, experience proves that one of the first aspects of code quality to suffer is the extra coding required to make optimal use of JDBC. Unfortunately, cutting corners in the database access layer of your application has direct and measurable negative impact on your application's performance and scalability. For example, the JDBC code in  CatalogDAOImpl.java in the Pet Store Demo, does not use JDBC bind variables, does not reuse prepared statements, does not exploit bulk record fetching, and does not implement any kind of data caching for frequently retrieved data, etc. Ideally, all of these additional application plumbing details to remember should be written once in generic code so all developers on the team can share their benefits.

How You Might Approach Building a Framework Yourself

As we saw in the quote from Sun's J2EE Blueprints book above, solving this kind of routine, recurring problem cries out for a framework to automate the interaction of the various objects involved. In fact, after implementing your tenth JSP page following the hand-coded pattern example above, you will undoubtedly begin to study the opportunities for automation yourself!

From experience, you notice that for every set of pages that you build related to a particular application task (e.g. displaying your store catalog), you find yourself typing in code that answers the same basic questions:

You also realize that each of your hand-coded value-objects follows similar coding pattern and could easily be made more generic. These opportunities to generalize your repetitive design-pattern implementation code are reflected in Figure 5.

A generic design pattern implementation could answer routine questions using metadata
Figure 5: A generic design pattern implementation could answer routine questions using metadata

Given enough time by your management to design, debug, and implement them, you realize that you could significantly simplify your life as a J2EE Design Patterns developer by writing yourself a few generic Java Bean components like:

Aspiring to achieve a good object-oriented design, the behavior of these generic helper components would live in base classes, like  QueryBeanImpl and  ApplicationObjectImpl. From then on, any time you need to build a new query or a new application object for a particular J2EE application you are building, you just derive a new subclass from the appropriate generic base class. Distinguished metadata like the SQL query statement, the names and types of the query results column values, or the names of the views in your application object data model could be stored for easy editing in an XML deployment descriptor for each derived component. As a bonus, by centralizing these common implementation aspects of your J2EE applications, you could then write a generic JSP Tag Library that handles all of your data binding needs, instead of having to code one for each new kind of data that needs to be presented.

To be sure, nothing you did while building your time-saving framework compromised your application's J2EE compliance. And, of course, your new, more clever approach still implements the same, familiar J2EE Design Patterns: heck, you designed it on purpose that way! All that's changed is that you're spending less time implementing design patterns plumbing code and more time implementing J2EE applications that make a difference to your company. In this ideal scenario, you find that your new J2EE framework is a gift that keeps on giving...

Back in the real world, it's unlikely that your management has budgeted time in the schedule for you to implement such a framework yourself. However, this fact does not necessarily doom you to a life of hand-coding design patterns. You're in luck, since you can leverage Oracle's off-the-shelf J2EE framework called Business Components for Java (BC4J). It already implements the J2EE design patterns framework described above, so you don't have to.

Implementing the Same Pet Store Demo Page Using BC4J

The BC4J framework comes with an implementation of the time-saving ingredients we described above:

Using the BC4J Wizards and Editors you can create subclasses of the generic framework components very easily. The tools manage the creation of editing of both your Java framework subclasses and their XML-based deployment descriptors. The only code you write is code specific to your own application's functionality.

Starting with an empty project in the Oracle 9i JDeveloper development environment, here are the steps required to implement the JSP page from the Pet Store Demo above:

  1. Specify a name for the java package to hold your components. Let's call it  pet.
  2. Use the View Object Wizard to create a view object called  Product with the SQL query:

    select productid, name, descn
      from product
    where productid = ?
  3. Use the View Object Wizard again to create a view object called  ProductItem with the SQL query:

    select itemid, listprice as listcost, unitcost,
           attr1 as product_attribute, a.productid, name, descn
      from item a, product b
    where a.productid = b.productid
    order by name
  4. Use the View Attribute Editor to set the format mask property for the  Listcost attribute to display as "Currency" with a mask of "$0000.00"
  5. Use the View Link Wizard to create a view link called  ItemsForProduct linking the master  Product view with the detail  ProductItem view based on appropriate key attributes specified declaratively
  6. Use the Application Module Wizard to create an application module called  CatalogWeb to be your MVC application object, and select the master/detail combination of the  Product view and the  ProductItem view to define the data model that the application object will support.
  7. Write a  product.jsp page using the in-place tag library assistance provided in the JDeveloper JSP editor to:

  8. Finally, add the one-line JSP snippet to the top of the page that sets the value of the JDBC bind variable in the  Product query equal to the value of the HTTP parameter named  product_id.

    product.getRowSet().setWhereClauseParam(0,request.getParameter("product_id"));

Then run the  product.jsp page directly from the IDE to see the fruit of your labor. It produces the same results as the Pet Store Demo example, with a whole lot less work on your part. The only line of code you had to write was the one line above to set a bind variable. Figure 6 illustrates the resulting set of components that you've created.

BC4J-powered approach: metadata-driven components that extend framework classes
Figure 6: BC4J-powered approach: metadata-driven components that extend framework classes

And the JSP page, for comparison, looks like Example 7.

<%-- Lists all items in the inventory for a particular product type. --%>
<%@ taglib  uri="/technology/webapp/DataTags.tld"  prefix="bc4j" %>
<bc4j:ApplicationModule id="catalog" configname="pet.CatalogWeb.Test"/>
<bc4j:DataSource id="product" appid="catalog" viewobject="Product"/>
<bc4j:DataSource id="item" appid="catalog" viewobject="ProductItem" rangesize="3"/>
<%
  product.getRowSet().setWhereClauseParam(0,request.getParameter("product_id"));
%>
<bc4j:RowsetIterate datasource="product">
  <font size="5" color="green"><bc4j:ShowValue dataitem="Name"/></font>
  <table border="0" bgcolor="#336666">
    <tr background="../images/bkg-topbar.gif">
      <th><font color="white" size="3">Item ID</font></th>
      <th><font color="white" size="3">Item Name</font></th>
      <th><font color="white" size="3">Item Price</font></th>
    </tr>
    <bc4j:RowsetIterate datasource="item">
      <tr bgcolor="#eeebcc">
        <td><bc4j:ShowValue dataitem="id"/></td>
        <td>
          <bc4j:ShowValue dataitem="ProductAttribute"/>
          <bc4j:ShowValue dataitem="Name"/>
        </td>
        <td><bc4j:RenderValue dataitem="Listcost"/></td>
      </tr>
    </bc4j:RowsetIterate>
  </bc4j:RowsetIterate>
</table>
<bc4j:ReleasePageResources/>
Example 7: BC4J-powered approach: generic tag library and just one line of code

For this particular set of catalog pages, the Pet Store Demo chose not to involve Enterprise Beans, opting instead for the JSP page to directly use the MVC application object, and indirectly the DAO implementation class, as local Java beans classes. However, other pages in the Pet Store demo do make use of session beans. Using the BC4J framework to power your J2EE application development, you can have it either way. You can decide at any time which of your application components should be deployed and used as a local Java beans as shown above, and which should be deployed as EJB Session Beans, supporting the Session Façade pattern. All that's needed is to use the Application Module Editor and select the desired deployment modes on the "Remote" tab as shown in Figure 8.

Easily deploy any application module as an EJB Session Bean
Figure 8: Easily deploy any application module as an EJB Session Bean

In the next section we'll describe in detail exactly how BC4J supports the EJB architecture and what options the BC4J developer has available for implementing performant EJB applications for multiple J2EE application servers, including Oracle9iAS and WebLogic.

Streamlining EJB Development with BC4J

As prescribed by the design patterns in the J2EE Blueprints and illustrated by the healthy mix of J2EE technologies on display the Java Pet Store Demo, Enterprise JavaBeans are one of the many tools in the J2EE developer's toolbox. Following this spirit, BC4J implements a complete set of J2EE application-building facilities that target EJB 1.1 and EJB 2.0 application servers using a carefully-architected blend of J2EE technologies. The architecture, capabilities, and performance of the BC4J framework have been validated by over two years of extensive, daily use within Oracle's own Applications Development division on projects using JSP, Servlet, Swing, and pure XML user interfaces.

Out of many different possible architectures for building EJB applications, first we'll study the factors that motivate the architecture that BC4J targets.

Among Many EJB Architectures, One Stands Out For Performance

It's natural that after completing an EJB training course, many first-time J2EE developers see Enterprise JavaBeans as the principal tool in their J2EE toolbox. This innocent initial instinct compels them to create enterprise beans for every component in their application:

However, as these developers load-test their application, they generally discover the system fails to scale due to inherent remoting overhead that Enterprise Beans require. Section 5.5 of the J2EE Blueprints book confirms this, and recommends a simpler, more pragmatic strategy:

"Since enterprise beans are remote objects that consume a significant amount of system resources and network bandwidth, it is not appropriate to model all business objects as enterprise beans. Only the Business objects that need to be accessed directly by a client need to be enterprise beans; other objects can be modeled as data access objects.” (Section 5.5, J2EE Blueprints)

The J2EE design pattern called "Session Façade" further refines this recommendation by clarifying that applications should be designed so that only Session Beans are remotely accessible. Rather than providing fine-grained, remote access to individual business entities to the client, Session Façade suggests creating an EJB Session Bean to wrap access to appropriate views of business information in a task-specific service interface. As shown in Figure 9, Value Object classes shuttle copies of the appropriate subset of business data between the Session Bean and the client program.

Session Bean Facade encapsulates access to persistent business entities
Figure 9: Session Bean Facade encapsulates access to persistent business entities

Since the recommended Session Façade architecture effectively encapsulates the technology used to represent your persistent business entities, the J2EE platform (the EJB specification in particular) affords several different options for implementing this layer of your application. Under the control of your Session Bean Façade, there are two top-level strategies. You can implement your persistent business components:

  1. As EJB Entity Beans, or
  2. As lightweight Data Access Objects, as suggested in the J2EE Blueprints quote above.

As the textbook solution proposed by most introductory texts on EJB, Entity Beans seem like the obvious choice due to their familiarity. However, more advanced EJB books like the J2EE Blueprints propose lightweight Data Access Objects as a pragmatic alternative given the former's inherent remoting overhead. It is clear that, while Entity Beans are undoubtedly the incumbent in this technology election, there is a strong support base for the lightweight DAO solution among communities of J2EE developers that have already "been there, done that" with Entity Beans and who have come back having learned some lessons.

Entity Beans offer both container-managed (CMP) and bean-managed (BMP) persistence options, giving the developer a choice between higher productivity and more flexibility, respectively. In contrast, with the lightweight DAO approach, only the BMP approach is available. CMP Entity Beans would appear the obvious choice, due to the time they can save developers by avoiding hand-written persistence code. However, for both BMP Entity Beans and lightweight DAO's, the potential downside of hand-coding can be avoided through the use of a object/relational mapping framework. So again, the lightweight DAO approach, if powered by a framework, keeps its head in the race.

Since CMP Entity Beans drive their persistence mapping off XML-based deployment descriptors, it's widely held that they are easier to maintain. However, if the persistence framework you use with BMP Entity Beans or lightweight DAO's adopts a similar metadata-driven approach, then again any compelling distinction between the approaches is blurred anew.

CMP Entity Beans offer the promise of being portable among application servers, but again a properly written framework can offer bean-managed database persistence that easily runs in any J2EE application server and indeed can be designed to support multiple back-end databases, too. Yet again, our various options appear equally matched.

Luckily, two final facts help tip the scales in the underdog's direction:

  1. Both CMP and BMP Entity Beans that are compliant to the EJB 1.1 specification are required to be remotable objects, and as such have additional overhead
  2. Lightweight DAO's are free to fully exploit Java language features like inheritance and make sophisticated use of SQL, neither of which is easily supported using standard Entity Beans by the book.

So, as shown in the matrix in Figure 10, an ideal technology combination that offers high productivity, high flexibility, and low overhead is a lightweight Data Access Objects framework with metadata-driven, bean-managed persistence.

Optimum persistence architecture for EJB: metadata-driven, framework-based DAO's
Figure 10: Optimum persistence architecture for EJB: metadata-driven, framework-based DAO's

This combination provides the convenience and improved maintenance of CMP Entity Beans, since the framework implements the persistence for you based on metadata descriptions. It provides the flexibility and control that only BMP solutions enable, without incurring the chore of hand-coding. This combination achieves portability to the widest array of application servers, since it's a technique supported by both EJB 1.1 and EJB 2.0. And last but not least, it avoids the remoting overhead of EJB 1.1 Entity Beans which the Session Façade pattern makes unnecessary. By design, the business entities are totally encapsulated by the façade so no remoting is needed.

In summary, implementing business entities as lightweight DAO's using a metadata-driven object/relational persistence framework gives all of the benefits, with none of the drawbacks. In combination with EJB Session Beans implementing the Session Façade pattern, it's a technology layer that the J2EE Blueprints book confirms is growing in popularity for efficient J2EE applications:

"Data Access Objects fill a gap in the J2EE application architecture between responsibilities of application developers and those of service providers. They represent an excellent opportunity to add value. In the future, custom DAO’s will most likely be replaced by sophisticated object/relational tools.” (Section 5.5.1.4, J2EE Blueprints)

As we'll see in the next section, this is precisely the unconventional, yet unquestionably J2EE-compliant, technology combination that the BC4J framework provides for J2EE developers desiring an optimal approach with minimum effort.

Overview of the BC4J Data Access Objects Facilities

At its core, BC4J is a metadata-driven Data Access Objects framework. The framework offers J2EE developers time-saving features that add value in all of the tiers of the J2EE application architecture:

In this section we'll take a closer look at the key building-block components that make up the framework. Figure 11 shows the architecture of a typical J2EE application built using BC4J.

Architecture of a typical J2EE application built using BC4J
Figure 11: Architecture of a typical J2EE application built using BC4J

The figure describes a simple Payment Terms Management application, assembled from the core BC4J framework components:

The Oracle9i JDeveloper environment comes with comprehensive tools support for putting the BC4J framework components to use in your J2EE applications. You use interactive wizards, editors, property inspectors, and UML diagrammers to create, enhance, and deploy your BC4J components. Of course, since these tools are tightly integrated within a complete Java IDE that features unparalleled debugging, deployment, and source control support, you can work from the beginning to the end of your J2EE application development lifecycle under one convenient roof.

For example, to build the EJB Session Bean façade for the application in Figure 11, we can start by creating an empty UML class model. We can drop three new entity object classes on the diagram, type their desired class names and interactively add an initial set of attributes directly on the diagram. Next, we can associate the classes on the diagram and set appropriate multiplicity. The result is shown in Figure 12.

Oracle9i JDeveloper UML class model showing associated entity objects
Figure 12: Oracle9iJDeveloper UML class model showing associated entity objects

As we work, JDeveloper keeps the Java source and XML deployment descriptor for each of our data access objects in synch with any actions we make on the diagram in real time. For example, Figure 13 shows what the System Navigator and Structure Pane look like after creating the UML model above.

System Navigator and Structure Pane showing framework components
Figure 13: System Navigator and Structure Pane showing framework components

We can then use the Entity Object Editor to specify the object/relational mapping for the  Bill,  Customer, and  Payment entities, then use the Create Database Objects wizard to automatically create the desired relational tables in our database to store the  Bill,  Customer, and  Payment instances.

For this particular Payment Management application, we need to work with a collection of just our slow-paying customers, and for each of these customers, the corresponding collection of their late payments. We can use the View Object Wizard to create components named  SlowPayingCustomers and  LatePayments that contain the appropriate SQL queries to retrieve just the information we need. Figure 14 shows one panel of the View Object Wizard in action, allowing the developer to specify the complete query. When this complete flexibility is not required, the tool can automatically default the query statement for you based on the underlying entity object attributes that you select in an another panel in the wizard.

Use arbitrarily complicated SQL queries with the view object's 'Expert Mode'
Figure 14: Use arbitrarily complicated SQL queries with the view object's 'Expert Mode'

By introducing a view link component to link these two queries, our application code can easily work with the master/detail coordinated set of correlated information that we need. Finally, we can create an application module component named  PaymentTermsManagementApp to group our linked view components into a single MVC application object for testing and deployment. Using the handy, built-in Component Browser shown in Figure 15, we can even test the application module locally before deploying it to the J2EE server.

Testing your application model using the built-in Component Browser
Figure 15: Testing your application model using the built-in Component Browser

Once we're happy with the data access functionality exposed by our framework components, we are just one wizard away from deploying the whole thing as a complete EJB Session Bean to be a Session Façade for our data access objects. Selecting the Deploy... option from the project in the Navigator, we launch the Business Components Deployment Wizard shown in Figure 16. This allows us to chose what kind of EJB Session Bean we want, whether we want it to support a Bean-Managed or Container-Managed transaction, and which EJB server we are targeting.

Selecting desired EJB Session Bean type and target EJB server for deployment
Figure 16: Selecting desired EJB Session Bean type and target EJB server for deployment

Once we've made these selections, the wizard will assemble the entire J2EE-compliant EAR file automatically for deployment. In addition, if we're deploying to Oracle9iAS or WebLogic, the tools can help go the final step and actually perform the EAR file deployment directly to the server with no user interaction. In a section below, we'll explain the difference between the "AppModule Session Bean" and the "Service Session Bean" choices in Figure 16 to clarify the difference in functionality that you have to choose from.

First, however, we will take a quick tour to learn about the power that comes from the innovative way in which the view object "query beans" cooperate with the entity object "business beans". This duo are the yin and yang of the BC4J data access objects implementation.

Drilling Down Into the BC4J Data Access Objects

The combination of BC4J view objects and entity objects provides functionality equivalent to what developers can achieve by combining Fast-Lane Reader SQL queries with Entity Beans to handle updates. However, as we'll see in this section, the BC4J data access objects avoid a few gotchas with the Entity Bean approach, while providing lots of additional functionality and better performance.

Drawbacks to Combining Fast-Lane Reader SQL with Entity Beans

The J2EE design pattern called "Fast-Lane Reader" suggests that the absolute fastest way to get data into your application is by using JDBC to read the results of a SQL statement yourself:

Sometimes it's more important to access a list of data efficiently, than that the data in the list be up-to-date...The Fast-Lane Reader pattern can accelerate the retrieval of large lists of items from a resource. Instead of going through an enterprise bean, an application accesses data more directly by going through a data access object. (From Sun's Design Pattern Catalog, Fast-Lane Reader page)

As we've seen with other best-practices, this straight JDBC approach is not something that typical EJB tutorials discuss. Instead they present the textbook solution of using EJB Entity Bean's  findByPrimaryKey() and user-defined finder methods as the official way to retrieve data into an application. However, the Fast-Lane Reader design pattern emerged because:

Since relational databases have evolved to be extremely powerful engines for quickly filtering, projecting, and joining business information, the Fast-Lane Reader pattern basically says, "for fastest results, tell the database what data you need with a SQL statement and just fetch it!" For example, as shown in Figure 17 a Fast-Lane Reader SQL statement can be used to fetch data to populate a collection of value objects to return to the client from an EJB Session Façade.

Using the Fast-Lane Reader pattern in an EJB Session Bean
Figure 17: Using the Fast-Lane Reader pattern in an EJB Session Bean

Figure 17 also illustrates that if the client passes back changed copies of this queried data, these can be made permanent by writing code to directly use the Entity Bean to make the changes. In this way you only pay the price of loading the data you need, and you only bother to load the complete set of entity attributes for the entities that end up getting modified. Since most applications do a lot more reading and writing, this is a winning tradeoff in practice.

There are of course pros and cons to this hybrid approach when using Entity Beans. While just fetching the data you need is fast, it can be inaccurate if there are any pending changes in Entity Beans in the current transaction. If a previous step in the transaction has made a pending update to some attribute of a Product, a subsequent Fast-Lane Reader SQL statement in the same transaction will read the old value directly from the database, and therefore will not reflect the current state of the business object in the current transaction. If this value were, for example, the price of the Product, the inaccurate value might be used in subsequent calculations and cause the inaccuracy to bubble to other attribute values as well.

Understanding How View Objects and Entity Objects Cooperate

The BC4J framework's companion data access objects, view object and entity object, cooperate to maintain the performance benefit of Fast-Lane Reader without suffering the downside of reading incorrect data. As shown in steps 1 and 2 of Figure 18, view objects send their SQL query using JDBC directly to the database (1) and retrieve the results (2) using optimized JDBC code for best performance. For each row of query results, BC4J uses its generic  Row value object implementation to hold the results. In this way, view objects provide an implementation of the Fast-Lane Reader pattern with automatic support for the Value Object pattern, too.

View objects send SQL to the database, then cache results based on entity metadata
Figure 18: View objects send SQL to the database, then cache results based on entity metadata

In its XML deployment descriptor, each view object bean you create keeps metadata that tracks how columns in the SELECT list of their SQL statement correspond to underlying attributes of related entity objects. In Figure 18, this metadata is indicated by the dashed lines for the join SQL query in the  EmployeeList view object. The  DEPTNO and  DNAME columns in the query have been mapped to the  Deptno and  Dname attribute of the  Dept entity object, and the  ENAME,  SAL, and  EMPNO columns in the query have been mapped to the  Ename,  Sal, and  Empno attributes of the  Emp entity object.

The generic view object implementation code exploits this metadata to automatically delegate the storage of appropriate attributes retrieved in the query to the underlying entity object instances. These underlying entity instances are shared between view objects so that common data retrieved in multiple views is automatically kept consistent. So as illustrated above, for each row retrieved from the database, the two attributes mapped to the  Dept entity are actually stored under the covers in an instance of the  Dept entity in the cache. Likewise, the three attributes retrieved in the query that are mapped to the  Emp entity are stored in an instance of the  Emp entity in the cache. If several rows in the query contain data from department 20, each of these rows points to the common instance of the  Dept entity whose primary key ( Deptno) is 20. For derived attribute values like the  YearsOfService calculated with the SQL expression  TRUNC((SYSDATE-HIREDATE)/365), the view object itself handles the caching.

Note in Figure 18 that BC4J supports an entity cache allowing partial entities to exist. Since the  LOC column from the  DEPT table and the  HIREDATE column from the  Emp table do not appear in the query, they are not brought into memory. This is a simple example, but for large entities having 80 to 100 attributes each, this partial retrieval is a huge savings. Regardless of the underlying caching details, you work with the query result as an iteratable, updatable collection of  Row value objects. So, for example, to update the value of the salary of the employee in the current row, you can just call  curRow.setSal(3500), and the framework takes care of the rest.

Figure 19 illustrates the steps involved when one of the  Row value objects attributes is updated. The same metadata used above for caching the Fast-Lane Reader query results also comes into play to enable the automatic delegation that makes the update so easy to perform.

View objects delegate updates to entity objects to handle validation and persistence
Figure 19: View objects delegate updates to entity objects to handle validation and persistence

In step 1, the developer invokes the setter to change the value of the  Sal attribute in the current  Row value object instance. In step 2, the view object row automatically delegates the setter invocation to the appropriate instance of the underlying  Emp entity object with no user code required. If any business logic in the  Emp entity object class refers to attributes that are currently missing, like a business rule referencing the value of  Hiredate in our example above, then step 3 illustrates that the entity object implementation will manage the "fault-in" of all of the entity attributes, based on the primary key. If all entity object business rules succeed, then the attempt to set the attribute in the internal entity attribute storage causes the corresponding row to be locked in the database (step 4) if pessimistic locking is in effect. If the lock can be acquired, then the value is successfully set in the entity object instance (step 5). Since entity data is shared, any view objects whose result collections contain  Row value objects with the  Sal attribute of employee number 7788 (step 6) will instantly see the value change.

Before the transaction is committed by the Session Bean itself or the container, depending on the kind of transaction mode you pick, any subsequent view object Fast-Lane Reader queries that are executed repeat the steps we described above of sending the SQL query directly to the database. Of course, since the pending entity changes have not yet been committed, this queries will fetch the current values from the database. One key difference however when using the BC4J data access objects for your DAO layer, is that the query results will correctly reflect any pending changes in your business entities in the current transaction. That is, using BC4J you avoid the problem of typical Fast-Lane Reader implementations of accidentally working with logically inconsistent data.

This occurs thanks to the cooperation between view objects and entity objects that we've described in this section, since the entity cache will favor attribute values with pending changes over known stale values retrieved from the database. For example, the view object query might retrieve the value 10, but if that value had previously been modified in the current transaction to 15, then the user will see value 15. The net result is that the collection of  Row values objects that you work with as the developer reflects the logically correct values within the current transaction. Of course, any new rows created in the view object's result collection result automatically in the appropriate entity instances being created. And similarly, any rows removed from the collection automatically translated into  remove() calls on the appropriate underlying entity instances, too. If any associations are programmatically navigated while new, changed, or deleted changes are pending, the code sees the correct logical state of affairs reflecting these pending changes.

Finally, when the transaction is committed, the database insert, updates, and deletes for any new, changed, or removed entity instances will be carried out as illustrated in step 7.

Working with Joins That Include Entities For Reference

Frequently, your application will need to work with join views, where several of the tables in the join are contributing reference information. For example, if the user types in the  ItemId of some  InventoryItem on a form or page where they are typing in line items, hand-written code is usually responsible for looking up the corresponding information like the description, price, and supplier for the item. Recall that with BC4J, each view object knows which entity objects it is using and knows that entity objects can be related using associations. This enables BC4J to keep the reference information synchronized for you to save you from writing code to accomplish the task.

Figure 20 illustrates what happens when the value of the  ItemId attribute on the current row in the  LineItemsView is set. It causes the framework to automatically retrieve appropriate reference information from the  InventoryItem and  Supplier entity objects used by the view object. The shaded pattern on the II and S indicate the entity references that are participating in the view as reference entities, rather than being updatable. This causes the appropriate description, price, and supplier to be automatically looked up when a user types in a new SKU# with no additional code required.

Setting foreign key attributes fills in reference information automatically
Figure 20: Setting foreign key attributes fills in reference information automatically

Highlights of Additional Interesting BC4J DAO Features

As we've seen above, the core components in the BC4J framework are a powerful productivity ally to implement the Data Access Objects layer of your J2EE application. While we've explored the key features of the view object / entity object combination, a number of other interesting capabilities deserve a brief mention before we move on to study what kind of EJB Session Beans you can target with the BC4J framework in the next section.

Easily Produce and Consume XML Datagrams

XML is the lingua-franca for exchanging business information between applications both for application integration and Web Services. The need to rapidly deliver appropriate hierarchical views of business information as XML datagrams is now a core competence for J2EE developers. Using BC4J view objects and view links, you can declaratively build a hierarchy of master/detail SQL queries that deliver exactly the slice of nested business data you need.

Calling  writeXML() on your view object marshalls any or all of its contents as XML, as you desire. For example, calling  writeXML() on the  SlowPayingCustomers view object above might produce an XML datagram like the one shown in Example 21.

<SlowPayingCustomers>
   <SlowPayingCustomer>
      <id>101</id>
      <name>Big Al</name>
      <LatePayments>
         <LatePayment>
            <id>34112</id>
            <bill>9433</bill>
            <amount>185.23</amount>
            <payDate>2001-08-15</payDate>
            <DaysLate>14</DaysLate>
         </LatePayment>
         <LatePayment>
            <id>44563</id>
            <bill>9876</bill>
            <amount>34.76</amount>
            <payDate>2001-09-10</payDate>
            <DaysLate>9</DaysLate>
         </LatePayment>
      </LatePayments>
   </SlowPayingCustomer>
      <!-- etc. -->
</SlowPayingCustomers>
Example 21: XML datagram produced by calling  writeXML()on a view object

Even more interesting is the ViewObject's ability to  readXML() to turn the tables and quickly consume incoming multi-level, XML datagrams. Due again to the clever cooperation between view objects and entity objects we learned about above, one method call to  readXML() automatically creates, updates, or removes the corresponding business entity instances under the covers. This includes automatically enforcing all business rules that have been implemented at the entity object level. In addition, the  writeXML and  readXML methods can work in tandem with XSLT transformations to produce and consume XML in arbitrary formats.

Work with Typesafe Value Object Interfaces

In addition to working with the generic  Row value object interface, you can optionally choose to generate a typesafe value object interface like  EmpRow which extends the base  Row interface. The difference is that using the generic  Row value object interface, you make method calls like:

curRow.setAttribute("Salary",new Number(3500));

In contrast, using the optional typesafe value object interface, your code looks like:

curRow.setSalary(new Number(3500));

The typesafe value object option allows the Java compiler to catch more errors at compile time in your code.

Value Objects as Entity Façades with Exported Methods

We've seen that view objects can easily be used to narrow, project, and join data from zero or more entity objects. In addition to producing typesafe value object interfaces that expose a subset or join of underlying entity data, you can also optionally expose additional custom methods on the value object interface. This enables your value object to act as a true Entity Façade. For example, your custom  SlowPayingCustomersRow value object interface can expose methods like  addToWatchList() and  suspendService(). This allows your programmatic or UI client to iterate the view objects result collection of value objects, and invoke methods like:

// slowPayers in an instance of a SlowPayingCustomers view object bean
while (slowPayers.hasNext()) {
  SlowPayingCustomersRow r = (SlowPayingCustomersRow)slowPayers.next();
  if (...) r.addToWatchList();
  else if (...) r.suspendService(10);
}

Full Support for DAO Component Inheritance and Polymorphic Collections

It comes as a surprise to most J2EE developers that Entity Beans cannot leverage inheritance in the way they expect. In fact in the EJB 2.0 specification, component inheritance is on the list of features under consideration for a future release of the EJB specification, after the 2.0 release. With BC4J as your data access objects framework, whether you use the UML diagrammer or the wizards, creating business entities that fully leverage component inheritance is as easy as any Java developer would expect. You can create inheritance hierarchies of entity objects to model the structure of your business, and easily work with polymorphic collections of value objects. For example, if you created entity objects to represent  Person,  Doctor,  Patient, and  Surgeon, you can easily produce a view object that queries over all people and returns  Row value objects whose underlying entity object instances are correctly typed as  Person,  Doctor,  Patient, or  Surgeon. The polymorphic view object support works in tandem with the entity object support for object/relational mapping of inheritance hierarchies into a single table based on user-defined descriminator attributes. While other multi-table inheritance storage strategies are possible by overriding the framework yourself, BC4J currently implements the default strategy that optimizes SQL queryability across multiple types of objects in the same "family". In other words, with  Person,  Doctor,  Patient, and  Surgeon rows stored in a single table, a simple SQL query can easily query across common attributes instead of having to use more complicated, and less performant, UNION queries.

Unique Support for Oracle Database Features

While the BC4J framework's data access objects will work with any SQL92-compliant database, the framework includes unique support for working with an Oracle8i or Oracle9i database, if your company has standardized on the Oracle database. When connected to an Oracle database, BC4J's generic data access objects implementation takes advantage of many performance-enhancing features of the Oracle JDBC driver, including support for:

Share Common Validation Logic with Parameterized Rules

Validation rules are JavaBeans that encapsulate reusable validation code for use across any entity objects where they might be useful. In contrast to the validations performed using Java code written in your entity object's Java implementation class, you attach validation rules to your entity object declaratively through its XML deployment descriptor.

Figure 22 shows the result of using the "Rules" tab of the Entity Object Editor in JDeveloper to attach a  RangeValidationBean to the  Quantity attribute of the  LineItem entity object. Since validation rules are like little data-driven validation engines housed inside a JavaBean, they typically require a set of parameters to be supplied when they are used. These parameters are captured and represented in the XML deployment descriptor as XML attributes on the element representing the validation rule usage. This makes the values easy to set and easy to customize.

Parametrized validation rules are represented in the entity object's XML descriptor
Figure 22: Parametrized validation rules are represented in the entity object's XML descriptor

Validation rules can be attached both to individual entity object attributes as well as to the entity object as a whole, and the framework supports a collection of zero or more validation rules at each place. validation rules work in concert with Java code-based validation so you can mix and match the approaches as you desire.

While BC4J comes with a set of example validation rules, their real power lies in the fact that you can easily implement validation rules of your own. After all, they're just JavaBeans that implement a supplied Oracle Business Components interface! This lets you provide libraries of reusable validation rules to your development teams or to your end-customer for easy, declarative customization of your application's behavior. Readers familiar with EJB Entity Beans know that they provide no model for implementing declarative business rules, any kind of rule infrastructure for EJB Entity Beans is a "roll your own" proposition.

Create Your Own Reusable Datatypes with Domains

When building real applications, you frequently find yourself writing little routines to check:

Domains are immutable classes that represent scalar datatypes that occur often in your applications. Domains to represent the above situations might be called  TelephoneNumber,  CreditCard,  WebURL, and  FedExTrackingNumber, respectively.

Domains contain a validation in the constructor which performs the check you need to do to make sure they are proper values. Once-constructed, instances of Domains can be freely passed around in a type-safe way as method parameters. In fact, Domains makes it easy to avoid the mistake of passing a  Quantity to a method expecting a  Price since the compiler will flag the error immediately.

BC4J lets you easily use Domains as the datatype of entity object and view object attributes, which automatically enforces the Domain's built-in validation checks on any attribute values supplied by clients.

Layered Application Customization Through Factory Substitution

To support layered application customization, the BC4J framework is designed to support the factory pattern, allowing customized versions of existing components to substitute for the components from which they inherit at runtime. This allows existing applications to be customized to add new attributes, new business logic, new associations, without having to recompile or change any existing classes or XML deployment descriptors.

Of course, it goes without saying that the JDeveloper IDE provides full design-time support for taking advantage of these framework features. At this point you should have a good idea of the range of pre-built and pre-tested generic data access objects functionality that the BC4J framework can automate for you. Next we'll learn what choices you have for EJB Session Bean deployment.

What Kinds of EJB Session Beans Can You Build with BC4J?

Using BC4J you can easily build two different kinds of EJB Session Bean Façades:

  1. A classic EJB Session Bean called a "Service Session Bean" that exploits BC4J's generic design pattern components exclusively inside its own private implementation, but does not expose these framework objects to the remote client
  2. An enhanced EJB Session Bean called an "AppModule Session Bean" that provides full remote access to the BC4J design pattern components and features, including the implementation of a clever "Value Messenger" pattern that considerably reduces typical EJB client network traffic.

The Service Session Bean option is typically used when your EJB Session Bean interface must be given to third-party developers to interface programmatically with your application. The AppModule Session Bean option is best when you know that the client to your EJB Session Bean will be a client interface developed by your team (JSP, Servlet, Swing, etc.).

For either option, at deployment time you can select whether you want to use a Bean-Managed Transaction (BMT) or a Container-Managed Transaction (CMT). As required by the EJB spec, when deploying as a CMT bean, BC4J implements the  SessionSynchronization interface for you so the container can drive the transaction boundary. With the BMT bean deployment choice, the BC4J framework coordinates the call to the expected methods on the JTA  UserTransaction object as a part of its commit processing.

Let's start by comparing the classic BC4J-powered Service Session Bean to a hand-written one you might build without BC4J, then explain what enhanced features are enabled by choosing the AppModule Session Bean instead. You can change your mind at any time, or try both approaches. Either way, the choice is yours and is as simple as picking the desired selection(s) from a list in the deployment wizard.

The Mechanics of Hand-Written Session Bean Façades

Using hand-written Session Façade's, you typically end up coding a solution like the one shown in Figure 23. Your façade class produces collections of hand-written value objects by iterating the results of Fast-Lane Reader SQL statements, or alternatively by iterating the results of calling an Entity Bean finder.

Hand-coding a Session Façade to retrieve and handle modifications to Value Objects
Figure 23: Hand-coding a Session Façade to retrieve and handle modifications to Value Objects

Depending on the implementation of your hand-written value objects, the client either calls setter methods on the existing value object instances or constructs new instances of the value object classes to make changes to the copies of data returned. Then the client passes back a collection of values objects to the Session Façade to make the changes permanent. This last step is accomplished by one of the following:

  1. For modified entries, look up the Entity Bean and call setter methods to poke the values from the value object back into the appropriate attributes of the Entity Bean.
  2. For deleted entities, look up the Entity Bean and call  remove() on it.
  3. For new entries, call an appropriate  create() method on the Entity Bean's home interface and call setter methods as in (1).

In the example above, we're using a  Product value object. Note that the collection of  Product value objects passed in from the client might contain some new products, some modified products that were returned in the original collection, and possibly some removed products. Unless the developer wants to blindly process each Product passed in by the client, it's his/her responsibility to provide value object implementations that are smart enough to keep track of what instances have been modified, newly added, and deleted. In addition, unless the code inside the Session Façade wants to blindly set each attribute value, the value object implementation needs to due the necessary bookkeeping to track which attribute values have changed.

Using BC4J Data Access Objects in a Service Session Bean

When choosing to deploy your BC4J application module as a classic Service Session Bean, you are able to leverage the features of the BC4J data access objects we've learned about here in your backend enterprise bean implementation. However, as in the hand-written Session Façade above, you are still responsible for:

As shown in Figure 24, your code for constructing the value object collections can benefit by the improved convenience and efficiency of using BC4J view objects, and their update-processing code has the choice of either working directly with their lightweight entity objects (using API's nearly identical to the Entity Bean's), or setting the changes back on the same view object that produced the data originally and let the BC4J view object / entity object cooperation handle making the changes persistent.

Service Session Bean deployment leverages BC4J framework on the server tier
Figure 24: Service Session Bean deployment leverages BC4J framework on the server tier

The client code to use your classic Service Session Bean is identical to the client code that you would use for the equivalent hand-written Session Façade, however the EJB Tier implementation will be more efficient. For example, Example 25 the code that you might write to lookup, create, and use the BC4J-powered  CatalogService Session Bean. In this example we call a method on the session bean's remote interface to return a list of products, then proceed to iterate the list and update the value of each product's  Name attribute to a value which has the letter "X" tacked on the end of the current value...

Context ctx = new InitialContext(env);
CatalogServiceHome home = (CatalogServiceHome)ctx.lookup("CatalogService");
CatalogServiceRemote service = home.create();
Collection c = service.getProductsByStore("SFO-3");
Iterator i = c.iterator();
int row = 0; // Iterate over collection, update product name in even number rows
while (i.hasNext()) {
  ProductValueObject pvo = (ProductValueObject)i.next();
  if (++row % 2 == 0) pvo.setName(pvo.getName()+"X");
}
service.updateProducts(c);
Example 25: Client code to work with an EJB Session Bean

Deploying your application modules as classic Service Session beans is a good choice when you must publish your EJB interface to third party developers because the API of your service includes only the methods you specify. However, if you are building an application where you are writing both the client and the business logic tier for the application, we'll see the AppModule Session Beans offer a functionally-superior deployment choice. You can easily mix and match these techniques based on the application module at hand, or each deploy the same application module in both ways, so your choice is always very flexible.

Full-Throttle Design Patterns With the AppModule Session Bean

While the classic Service Session Bean saves you time and adds value to your EJB tier bean implementation, it is the enhanced AppModule Session Bean that really blows the doors off any hand-written counterpart. In contrast to the classic Service Session Bean, which only supports the remote methods that you create for it, an AppModule Session Bean inherits a rich set of remote collection functionality from the generic BC4J ApplicationModule object.

This means that out of the box, an AppModule Session Bean is equipped to efficiently support all of the J2EE Design Patterns we've discussed in this paper in a fully remotable and extremely network-efficient manner. Of course, it's not just any old Session Bean that can offer a generic implementation of all of these design patterns to save you so much hand-coding of application plumbing. It takes a sophisticated, carefully-engineered Session Bean to offer all this functionality, all the while playing within the rules established by the EJB specification. The fact is, when you deploy your application module as an AppModule Session Bean, BC4J automatically creates an EJB Session Bean whose bean implementation inherits from BC4J's generic implementation of just such a sophisticated bean. So, your AppModule Session Bean façade is, in effect, standing on the shoulders of a helpful giant.

BC4J achieves this network-efficiency for its generic design patterns functionality by implementing the "Value Messenger" design pattern on top of the standard EJB home and remote interface for the deployed Session Bean as shown in Figure 26. BC4J's Value Messenger implementation ensures that value objects returned to the client as generic Row objects are both fully-updatable and also kept in synch with the attribute values of the underlying business components that they represent in the business logic tier. As Figure 26 illustrates, by manipulating collections of generic value objects --  RowSets of  Rows in BC4J framework terminology -- values objects can be easily added, modified, and deleted, with automatic middle-tier synchronization. The Value Messenger pattern implementation saves you from having to write code to keep the changes made to your value objects in synch with middle-tier business entities.

BC4J's "Value Messenger" pattern enables efficient, updatable remote Value Objects
Figure 26: BC4J's "Value Messenger" pattern enables efficient, updatable remote Value Objects

By implementing the Value Messenger pattern, BC4J extends the full set of application module and view object component functionality, and by implication all the design patterns they implement, seamlessly to the remote client. The client can navigate page by page through results, create, update, and delete rows as needed, work with coordinated master/detail collections, etc., all without the expected network chattiness. Figure 26 illustrates that the client can work directly with the  Product (master) and  ProductItem (detail) collections of generic value objects without additional code. All changes made to the value objects in the collection on the client are automatically (and network-efficiently) synchronized at appropriate intervals with their EJB Tier counterparts. The picture also shows that the coordination between view objects and entity objects remains in the realm of the EJB Tier implementation. The client of an AppModule Session Bean sees and manipulates the world through the generic value objects in the view object result collections. This keeps the client API very simple.

How is this functionality achieved? Let's take it step by step. When you look up the  CatalogService AppModule Session Bean, the BC4J JNDI  InitialContext implementation caches the actual  CatalogServiceHome interface returned by the EJB server, and instead returns to the client a generic ApplicationModuleHome interface that is used to  create() the  CatalogWeb application module. As a client developer, you continue to work with the application module component using the same interface that you would have used on the server-side, however the implementation beneath that interface in the remote client implements the smart proxy functionality.

The thin layer of proxy code in the EJB client handles delegating any activity on the  CatalogWeb application module interface (or any of its contained view object interfaces), through the actual EJB Session Bean remote interface at the appropriate times. Using the AppModule Session Bean, the client code looks the same, but no additional hand-written value-object code is needed from the developer and no additional server-side create/modify/remove logical needs to be coded. The equivalent client code looks like what's shown in Example 27.

Context ctx = new InitialContext(env);
ApplicationModuleHome home = (ApplicationModuleHome)ctx.lookup("CatalogWeb");
CatalogWeb service = (CatalogWeb)home.create();
RowSet rs = service.getProductsByStore("SFO-3");
RowIterator i = rs.createRowSetIterator();
int row = 0; // Iterate over collection, update product name in even number rows
while (i.hasNext()) {
  Row pvo = i.next();
  if (++row % 2 == 0) pvo.setAttribute("Name",pvo.getAttribute("Name")+"X");
}
// Don't need to call an explicit Session Bean method to update the rows
// But you can have a method on the AppModule interface that accepts
// a RowSet argument to simulate the same kind of API as the bean above
service.updateProducts(rs);
Example 27: Client code to work with an EJB (AppModule) Session Bean

Note that the generic  ApplicationModuleHome stands in for a specific session bean home, since the BC4J JNDI  Context implementation introduces a thin indirection layer over the basic EJB Session Bean home and session bean remote interfaces to allow for numerous network traffic optimizations achieved through local caching. The small library of client-side implementation code behind the BC4J generic Design Pattern interfaces, automatically handles the EJB lookup and create, and hangs onto the actual interfaces and delegates calls through them as needed.

Note, the use of the generic  RowSet list interface and the generic  Row value object instead of hand-written, one-off value object classes used in the classic Service Session Bean example above.

Taking advantage of a further convenience that  RowSetimplements RowIterator by providing a built-in, default iterator implementation, and illustrating the use of optional type-safe custom value object interfaces ( ProductRow here, instead of using the base  Row interface), the example above can be shortened to look like Example 28.

Context ctx = new InitialContext(env);
ApplicationModuleHome home = (ApplicationModuleHome)ctx.lookup("CatalogWeb");
CatalogWeb service = (CatalogWeb)home.create();
RowSet rs = service.getDepartments();
int row = 0; // Iterate over collection, update product name in even number rows
while (rs.hasNext()) {
  ProductRow pvo = (ProductRow)i.next();
  if (++row % 2 == 0) pvo.setName(pvo.getName()+"X");
}
// Pass collection of partially-modified values objects back to server
service.updateProducts(rs);
Example 28: Using custom row interfaces to improve type-safety checking

These are simple, programmatic examples, but of course, all of the additional generic client functionality, like the generic JSP tag library and the generic JFC/Swing data bound controls work seamlessly over this remote AppModule Session Bean deployment, too. In the next section we drill down further on how BC4J implements the Value Messenger pattern to achieve these results.

Understanding the BC4J Value Messenger Pattern Implementation


NOTE:

Readers unfamiliar with EJB Session Bean implementation details may opt to skip to the next section


Instead of using straight Java classes with member variables to hold the value object attributes, the more sophisticated BC4J value object implementation automatically leverages a client-side value object cache to implement both network traffic optimization and middle-tier value object synchronization. So when you deploy an application module as an AppModule Session Bean, BC4J generates a thin layer of client proxy implementation classes to support your tier-independent component interfaces. These client classes implement the component interfaces that your client program uses to work with your application data model and custom application module methods. As we'll see in this section, your coding style does not need to change to take advantage of the additional features of Value Messenger.

Because BC4J's implementation of the generic  Row value object leverages a client-side value object cache for storage, you can make changes to several attributes of your value objects without incurring network round trips for each attribute changed. Once all necessary changes have been made, the pending changes to value object values sitting in the client cache are sent in bulk to the EJB tier in a single round trip. In addition, as part of that same network round trip, any EJB Tier attribute values that changed as a side effect of the current middle-tier synchronization are sent back in in bulk in a "Value Message" to refresh the corresponding value object attributes in the client.

An example, illustrated in Figure 29, will help clarify how the mechanism works. Suppose you've built an application module component that uses a single view object  EmployeeList, related to two underlying entity objects  Dept and  Emp. Assume that business logic written in the  Emp entity object implementation class forces any  Ename attribute value set to be in uppercase:

public void setEname(String value) {
  if (value != null) value = value.toUpperCase();
  setAttributeInternal(ENAME, value);
}

Furthermore, imagine that additional  Emp entity busines logic enforces the business policy that if an employee's salary is set to a value greater than $3000, then their vacation limit is automatically increased to 144 hours.

As shown in Figure 29 in step 1, the client can set the  Sal attribute of the value object to 3500 and set the  Ename attribute to "Steve". The pending changes are kept in the client-side value object cache. In step 2, an operation like UI navigation, explicit transaction commit, or explicit EJB Tier method invocation causes the changes to be sent to the middle tier in bulk. As part of the value object synchronization, the  Sal and  Ename attributes are set in the appropriate entity object instances in the cache (Step 3) using the view object / entity object coordination we've studied earlier. The business logic in the  Emp entity object causes the value of  Ename to be uppercased and the value of  VacationLimit to be set to 144 (Step 4). All relevant changes to value object attributes of interest to the client cache are bundled and returned as part of the network roundtrip to the client. In this example, the uppercased value "STEVE" and the updated value 144 of the  VacationLimit attribute are returned to the client (Step 5). Finally, in Step 6, the client value object "sees" the middle-tier updates and renders on the screen/page with the latest values. Of course, you don't need to write any application plumbing code to make any of this happen since your bean inherits the Value Messenger pattern implementation from the application module framework base class  ApplicationModuleImpl.

"Value Messenger" pattern automatically synchronizes Value Objects between client, server
Figure 29: "Value Messenger" pattern automatically synchronizes Value Objects between client, server

Without leveraging a Value Messenger pattern implementation of some kind, your client-side value objects remain stale copies of business data and are not updated to reflect changes that have occurred in the EJB tier due to routine business logic execution. In addition, as we've seen in previous sections, the task of updating EJB Tier business entities based on changes made to client value objects is left as an exercise for the coder.

It's interesting to examine a few details of how BC4J implements the Value Messenger pattern in practice. Consider an application module named  MyApp with a custom method that you publish on the application module's remote interface:

// Your application module component implementation class
public class MyAppImpl {

  // A custom method to be remotely accessible
  public Integer someMethod(String x, Number y) {
    // do some middle-tier business functionality and return an Integer
  }

}

When you deploy your application module component as an AppModule Session Bean, the Session Bean Façade and Value Messenger implementation are automatically generated for you and shown in the UML class model in Figure 30. Note that in order to handle sending the bulk "value message" from the client to the EJB Tier, the signature of each custom method is augmented with an additional byte-array parameter. Also, to handle returning the bulk "value message" from the EJB Tier as a part of the method invocation, each custom method's return value is changed to be of type  PiggybackReturn and code is generated to include the actual method return value as part of this "piggyback" object.

Auto-generated Session Façade & Value Messenger implementation for application module
Figure 30: Auto-generated Session Façade & Value Messenger implementation for application module

Luckily, as the application client you are shielded from knowing or caring about these implementation details. As shown in Figure 31, your client code works with the tier-independent  MyApp interface, which has exactly the same signature as your custom method in your application module implementation class.

Generated client component interfaces conceal Value Messenger pattern implementation
Figure 31: Generated client component interfaces conceal Value Messenger pattern implementation

The BC4J-generated client proxy objects that implement this interface worry about the details of sending any pending value object changes to the EJB tier, and worry about refreshing the client value object cache with any EJB tier value object attribute changes.

Haven't Embraced EJB Just Yet? Start By Deploying in Local Mode

Above we've explored the various ways to deploy BC4J application modules as EJB Session Bean façades. However, it's important to remember that many of today's J2EE applications are based purely on servlets and/or JSP's that access Java code in local classes. That is, they are J2EE applications that exploit the J2EE Web Tier but haven't yet embraced the J2EE EJB Tier. If you count yourself among the developers that haven't yet made the move to EJB, not to worry. BC4J-powered applications leave the J2EE deployment architecture decision to the developer and keep your options open throughout the lifecycle of your application.

The BC4J framework encourages a well-architected, coarse-grained "service façade" application architecture whether you decide to deploy your application module as an EJB Session Bean, or not. This means that any application module can also be deployed and used in "local mode" -- that is, as a simple Java bean -- to support application architectures that exclusively target the J2EE Web Tier. At any time in the future, by revisiting the Application Module Editor in Oracle9i JDeveloper, you can redeploy the same application module as an EJB Session Bean with no code changes to your application. So adopting the BC4J framework for your J2EE application development not only saves you from writing a lot of Design Patterns application plumbing code, but also gives you the deployment flexibility to plan your EJB Tier uptake when it makes most sense for your application development team.

What Client Technologies Can You Couple with BC4J?

The core BC4J framework implements the model layer of a Model/View/Controller architecture, giving you powerful features to work with data in any way you need to, update that data if neeeded, and automatically engage reusable business logic in the process. In addition, since application modules are a convenient place to write custom, task-specific methods that appear on your EJB Session Bean Façade, some users take advantage of this capability and write their "Controller" logic directly into their application module class for simplicity.

Either way, you have a lot of flexibility when implementing the "View" and "Controller" layers of your BC4J-powered J2EE application. Oracle9i JDeveloper ships with several complementary client frameworks that assist in implementing this part of your application. All of them feature built-in support for working with BC4J application modules, so by combining BC4J with these additional UI frameworks, your development productivity is further enhanced.

Web Tier Application State Management and Sharing with the Pooling Framework

J2EE Web Tier state management is one of the most common and most onerous development tasks facing web application developers. Web Tier state management comes into play when a logical application task requires the user to visit multiple pages to get the job done. All of the pending work must be saved "between pages" so that it can be committed or rolled back as a unit when the process it complete. However, this is easier said than done.

For example, imagine a web-based expense reporting system. To file a new expense report, a user needs to visit several pages to add, edit, and review multiple expense report entries before ultimately submitting the final report. With a traditional client/server application, this pending state is kept in the memory of a dedicated user process which uses a dedicated database connection. However, since web applications often need to scale to a large number of users, dedicating a server-tier process and a database connection to each web user is not practical.

Since web application developers generally choose stateless application architectures to address this scalability requirement, they need to invent a scheme to save away the pending work to a temporary store after each page request. To make this task simple, BC4J application modules support the ability to serialize their pending state to a convenient XML format at any time, and to instantly refresh their state from such pending-work "snapshots" at any time.

In addition, BC4J comes with an application module pooling framework that automates the use of this built-in "state snapshot" feature to manage pending web-user application state between page requests without requiring developer-written code. Pending state is snapshotted and saved to a central database to support web farm deployment configurations and to allow failover between different web listeners. The pool manages a dynamically allocated set of application module instances -- or client references to remotely deployed instances in the case of EJB Session Bean deployment -- to deliver a "stateless with affinity" web-tier state management approach.

"Stateless with affinity" means that across multiple page requests, the pool attempts to give the web user the application module instance that he was using on the last request if it is still available in the pool and hasn't been used by another web user in the meantime. If the same instance is not available, then any available instance is grabbed from the pool and the pending state of the application module is restored based on the persisted session state snapshot. This technique has proven in large-scale tests by the Oracle Applications development teams using BC4J to deliver excellent performance.

An additional way to improve performance for web applications is to share mostly read-only data across web users. The application module pool supports this by allowing application module instances of your choosing to be shared in a thread-safe way across clients. By doing this, access to common lookup information can be accelerated by avoiding requerying.

Databound JSP Pages with the BC4J Data Tags

BC4J Data Tags are a JSP 1.1-compatible tag library for easily rendering, navigating, and updating data from any view object in any application module. The example in the first section of this paper that illustrated rebuilding the master/detail web page from the Pet Store demo made use of these BC4J data tags. Oracle9i JDeveloper contains integrated support for using the Data Tags in your JSP pages, including wizard-driven tag assistance and context-sensitive "Tag Insight" help for always knowing what tags and attributes are legal anywhere you're typing in your page. In addition, JDeveloper supports running and debugging JSP pages locally for an even quicker test-fix-retest cycle, avoiding a deployment step while you're still in development.

Databound Swing Forms with JClient Framework

The Oracle JClient framework simplifies building databound Swing-based applications and applets by providing implementations of Swing models that handle the communication between the client UI controls and the BC4J view objects. Using wizards you can quickly produce databound forms using any model-based controls, including standard Swing controls, JClient controls, and third-party addin controls. Applications built with the JClient framework can also use Sun's Java Web Start to take advantage of this new web-based deployment paradigm for rich Java displays. Oracle9i JDeveloper contains integrated support for visually designing and modifying the layouts for your Swing-based UI panels.

XML/XSLT-based Information Publishing with Oracle XSQL Pages

The Oracle XSQL Pages Framework makes publishing XML-driven information over the web a snap. Oracle9i JDeveloper ships with additional XSQL action handlers to easily include XML information from any BC4J view object, as well as easily update any view based on incoming XML documents. Any XML published through XSQL pages can also be combined with XSLT stylesheets for convenient transformation into any target XML, HTML, or text-based format. Support in JDeveloper for running and debugging XSQL pages is similar to that offered for JSP pages mentioned above.

Oracle UIX Web Application Framework

The Oracle UIX web application framework simplifies the implementation of complete, sophisticated web applications -- for example, a multi-lingual, self-service Human Resources application -- by providing reusable technology to assist with many of the aspects you would typically have to write code to handle yourself. For example, UIX provides off-the-shelf assistance with web page rendering, data binding, event handling, page-to-page navigation, and customization. It offers a comprehensive set of pre-built page layout elements to deliver web applications with a rich, consistent look and feel across many different client agent types. Of course, as illustrated in Figure 32, UIX provides built-in support for BC4J data-binding, too, so including or modifying data from any BC4J view object is easy.

UIX framework offers page rendering, page flow, BC4J data-binding and other features
Figure 32: UIX framework offers page rendering, page flow, BC4J data-binding and other features

The Oracle UIX technologies can be used programmatically or declaratively via UIX XML page templates, as well as from with JSP pages using the UIX JSP tag library. Oracle9i JDeveloper features context-sensitive "Tag Insight" for the UIX XML elements and JSP tags, as well as a runtime preview facility to immediately see what your combination of layout components will look like in the browser.

The UIX Controller servlet implements the Front Controller design pattern and coordinates the use of other aspects of the UIX framework technologies as shown in Figure 33.

Oracle UIX Framework implements Front Controller and Model/View/Controller patterns
Figure 33: Oracle UIX Framework implements Front Controller and Model/View/Controller patterns

Using BC4J with Other MVC Frameworks

If none of the built-in options for client development suits your needs or development style, then it's easy to combine J2EE applications built using BC4J with third-party web application frameworks, or a framework of your own design. All of the API's used by the options above to enable automatic data-binding are available and documented for use by your own client-framework code. In fact, Oracle Consulting have leveraged this fact to develop the Oracle9i MVC Framework (formerly known as "JHeadstart" and "Project Cleveland"). This offering, to be made available for download on Oracle Technet, adds metadata-driven page generation facilities and a state-model-based page flow capability on top of the UIX framework and BC4J technologies.

How Does EJB 2.0 Change the Picture?

The BC4J framework team at Oracle has been promoting the Session Façade architecture with lightweight, local Data Access Objects even before there were official J2EE Design Pattern names for them. The EJB 2.0 specification, officially released a few months ago in its final form on August 14, 2001, introduces the notion of local interfaces, which allow other beans in the business logic tier to use entity beans without making a remote method invocation. Under this new version of the EJB specification, a data access object can be implemented as a lightweight entity bean, whose local interface abstracts data access functionality.

In addition to adding "Local Entity Beans" (analogous to BC4J's lightweight, local entity object classes), EJB 2.0 also introduces container-managed relations that provide functionality analogous to BC4J's navigable entity associations that we've seen briefly in this paper. Since this is a period of transition for EJB App Server vendors, including Oracle, the BC4J team has chosen in the Oracle9i JDeveloper release to continue targeting both EJB 1.1 and EJB 2.0 application servers. To this end, we've maintained the lightweight entity object classes for this release.

As Oracle9iAS, WebLogic, and other J2EE application server vendors begin to rollout complete support for the new EJB 2.0 specification in the first half of 2002, a new release of the BC4J framework will be released which includes support for the new local entity beans. This work entails enhancing our lightweight, local entity classes to support the necessary interface to be lightweight EJB 2.0 Local Entity Beans. At present, we don't expect these enhancements to require changes to your application code to take advantage of.

So while we have pushed for and applaud the inclusion of the lightweight, local entity beans in EJB 2.0, unfortunately the specification's authors ran out of time to include important features like an ORDER BY statement in the EJB-QL query language, support for Entity Bean component inheritance, and the ability to use the SQL language in finder methods without resorting to vendor-specific extensions. The collective experience of our 2000 internal application developers tells us time and again that you cannot write performant applications unless you fully embrace the ability to exploit the SQL language to squeeze the best performance out of the database. As a key member of the EJB 2.1 and J2EE 1.4 design efforts in the Java Community Process, Oracle will continue to bring its data access and application-building expertise to bear on the J2EE platform and push to improve its application-building facilities in future versions of the EJB specification.

Conclusion

We've seen through numerous examples in this paper that applications built leveraging the BC4J framework are not only fully J2EE-compliant and make optimal use of your application server's EJB 1.1 or EJB 2.0 architecture, but also benefit from a generic implementation of all the important J2EE Design Patterns. We learned that BC4J offers a great developer productivity boost, both for developers working with EJB as well as those still targeting only the J2EE Web Tier. As more and more teams appreciate and begin to reap the productivity benefits that a framework-based approach to J2EE development offers, the BC4J framework and its design-time tools built into Oracle9i JDeveloper will continue to add innovative features to keep BC4J-powered J2EE teams ahead of the pack.

BC4J Design Pattern Catalog

This section provides a handy summary of the J2EE Design Patterns that BC4J implements for you. Some of these are the familiar patterns from Sun's J2EE Blueprints book, and some are design patterns that BC4J adds to the list.

Pattern Name Description How BC4J Implements It
Data Access Objects Avoids unnecessary marshalling overhead by implementing dependent objects as lightweight, persistent classes instead of each as an Enterprise Bean. Isolates persistence details into a single, easy to maintain class. BC4J view objects automate the implementation of data access for reading data using SQL statements. BC4J entity objects automate persistent storage of lightweight business entities, an EJB 1.1-compliant implementation of the EJB 2.0 "local entity bean", not yet available in many EJB servers due to the emerging nature of the EJB 2.0 specification. BC4J view objects and entity objects cooperate to provide a sophisticated, performant data access objects layer where any data queried through a view object can optionally be made fully updatable without writing any "application plumbing" code.
Model/View/Controller Cleanly separates the roles of data and presentation, allowing multiple types of client displays to work with the same business information. The BC4J Application Module Session Bean provides a generic implementation of a Model/View/Controller "application object" that simplifies exposing the application data model for any application or service, and facilitates declaratively specifying the boundaries of a logical unit of work. Addtional UI-centric frameworks and tag libraries provided in Oracle9i JDeveloper help the developer implement the View and Controller layers.
Session Façade Avoids inefficient client access of Entity Beans and inadvertent exposure of sensitive business information by wrapping Entity Beans with a Session Bean. BC4J application modules are designed to implement a coarse-grained "service façade" architecture in any of their supported deployment modes. When deployed as EJB Session Beans, they provide an implemention the Session Façade pattern automatically.
Value Object Avoids unnecessary network round-trips by creating one-off "transport" objects to group a set of related attributes needed by a client program. BC4J provides an implementation of a generic Row object, which is a metadata-driven container of any number and kind of attributes that need to be accessed by a client. The developer can work with the generic Row interface and do late-bound getAttribute("Price") and setAttribute("Quantity") calls, or optionally generate early-bound row interfaces like OverdueOrdersRow, to enable type-safe method calls like getPrice() and setQuantity(). Smarter than just a simple "bag 'o attributes" the BC4J Row object can be introspected at runtime to describe the number, names, and types of the attributes in the row, enabling sophisticated, generic solutions to be implemented.
Page-by-Page Iterator Avoids sending unnecessary data to the client by breaking a large collection into page-sized "chunks" for display. BC4J provides an implementation of a generic RowSet interface which manages result sets produced by executing View Object SQL queries. RowSet allows the developer to set a desired page-size, for example 10 rows, and page up and down through the query results in these page-sized chunks. Since data is retrieved lazily, only data the user actually visits will ever be retrieved from the database on the backend, and in the client tier the number of rows in the page can be returned over the network in a single roundtrip.
Fast-Lane Reader Avoids unnecessary overhead for read-only data by accessing JDBC API's directly. This allows an application to retrieve only the attributes that need to be displayed, instead of finding all of the attributes by primary key when only a few attributes are required by the client. Typically, implementations of this pattern sacrifice data consistency for performance, since queries performed at the raw JDBC level do not "see" pending changes made to business information represented by Enterprise Beans. BC4J View Objects read data directly from the database for best performance, however they give developers a choice regarding data consistency. If updateability and/or consistency with pending changes is desired, the developer need only associate his/hew View Object with the appropriate Entity Objects whose business data is being presented . If consistency is not a concern, View Objects can simply perform the query with no additional overhead. In either case, the developer never has to write JDBC data access code. They only provide appropriate SQL statements in XML descriptors.
Front Controller Centralizes view management (navigation, templating, security, etc.) for a Web application in a single object that handles incoming client requests. The Oracle UIX web application framework's UIX Controller servlet implements this design pattern, managing page rendering, event handler, page flow, etc.
Factory Pattern Allows runtime instantiation of an appropriate subclass of a given interface or superclass based on externally-configurable information. All BC4J framework component instantiation is effected through factory classes allowing runtime substitution of specialized components to facilitate application customization.
Entity Façade Provides a restricted view of data and behavior of one or more business entities. The BC4J view object can surface any set of attributes and methods from any combination of one or more underlying entity objects to furnish the client with a single, logical value object to work with.
Value Messenger Keeps client value object attributes in synch with the middle-tier business entity information that they represent in a bidirectional fashion. BC4J's value object implementation coordinates with a client-side value object cache to batch attribute changes to the EJB tier and receive batch attribute updates which occur as a result of middle-tier business logic. The BC4J Value Messenger implemenation is designed to not require any kind of asynchronous messaging to achieve this effect.

Frequently Asked Questions

References

  1. Designing Enterprise Applications with the Java(TM) 2 Platform, Enterprise Edition (First Edition) (Kassem)
  2. EJB Design Patterns: Advanced Patterns, Processes, and Idioms (Marinescu, Roman)
  3. Core J2EE Patterns: Best Practices and Design Strategies (Alur, Crupi, Malks)