Should You Use EJBs?

This book assumes that you’ve already made the decision to use EJBs. However, there are several instances where EJBs are not the best solution to a problem. It makes sense, therefore to review where EJBs are strong and then discuss situations in which EJBs don’t make as much sense. There are several situations—even some enterprise database-centric applications—in which EJBs are simply not the best choice. At the end of this section, we’ll look at some of the alternative approaches and where they might fit.

When to Use EJBs

Here’s a list of situations where EJBs are strong; we haven’t distinguished between different types of EJBs.

Single and multisystem business transactions

The ability to maintain transactional integrity for complex business entities is one of an EJB’s key strengths. EJBs aren’t alone in providing straightforward transactional control over a single data repository. However, EJBs shine where multiple resources (relational databases, messaging systems, etc.) are involved because they allow transactions to spread across as many different resources as you like, so long as the resources support distributed transactions.

Distributed functionality

Business services often live on a remote server. For example, a business enterprise will have many different systems, ranging in degrees of inflexibility and entrenchment. One of these systems may need to access another; EJBs, which are inherently distributed, are often the simplest way to distribute remote services. EJB also allows you to provide business services to remote clients more easily than some alternatives. Remote access through components is easier to maintain than direct database access, because the component code can shield the client from database schema changes.

Portable components (not classes)

Until recently, if you wanted to share your business services with another application developer, you were forced to share classes or at least packages. Java did not allow for the easy creation of enterprise components, reusable software building blocks that can be assembled with other components to form an application. EJBs allow you to package your business logic into a tidy, distributable unit that can be shared in a loosely coupled fashion. The user of your component need only tweak a descriptor file for her environment.

Applications relying on asynchronous messaging

EJBs (specifically MDBs) provide a strong technology for handling asynchronous communication such as JMS-based messaging or web services.

Security roles

If your application’s business operations can be mapped to specific business roles in your enterprise, then EJBs may be a good choice. So much is made of the transaction management capability of EJBs that their deployment-descriptor-based security management features are overlooked. This capability is very powerful; if your application’s users fit into distinct roles and the rules for those roles dictate which users can write what data, EJBs are a good choice.

When Not to Use EJBs

There are several situations in building a software application—even an “enterprise” software application—in which using EJBs may actually be a barrier to meeting your business goals. The following list represents places where you might not want to use EJBs:

Read-mostly applications

If your application requires only (or even mostly) database reads (as opposed to writes), then the added complexity and performance overhead of EJBs may be unwarranted. If your application is only reading and presenting data, you should go with straight JDBC (see below) or another persistence mechanism. That said, if your application’s writes (database update and inserts) require transactional support (especially if those transactions go over multiple systems), then EJBs may be the way to go—at least for the write portion of the application.

Applications requiring thread control

If your application design requires extensive use of threads, then the EJB spec actually prevents you from using EJBs (although some EJB container vendors may provide nonportable ways around this restriction). Container systems manage resources, transactions, security, and other qualities of service using threads; threads you create are outside of the container’s control and can potentially cause system failures. Also, EJB containers may distribute EJBs across multiple JVMs, preventing the synchronization of threads.

Performance

Because EJBs do so much more than plain Java classes, they are slower than plain Java classes. The EJB container has to do a lot: maintain transactional integrity, manage bean instances and the bean pools, enforce security roles, manage resources and resource pools, coordinate distributed operations, synchronize shared services (if the vendor offers clustering capabilities), and so on. The security and transactional management operations can have a significant impact on the performance of method calls (on both local and remote interfaces). If you require real-time or near-real-time performance characteristics, EJB may not be your best choice.

Alternatives to EJB

There are several alternatives to EJB; some of them are growing in popularity and maturity. EJBs still rank as the de facto standard for enterprise transactional needs, but some of the alternatives, like JDO, are also available.

JDBC

The first (and likely most common) alternative to using EJB is to write straight JDBC functions. While EJB provides you with many niceties, there are situations in which JDBC makes more sense. The simplest case is when your application is only reading (and not writing) data from a database table in a row-column format (list displays, for example). In this scenario, using EJB would not only be more complex but also quite a bit slower than straight JDBC.

If you are writing only simple rows of data without parent-child or foreign key relationships it may be better to use JDBC—especially if your application is built for a single user working with a single database or multiple users using a single database with little chance of contention while writing (relatively rare writes). This case is a little more ambiguous, because you are writing as well as reading data. But if the way you’re using the database is simple, JDBC may end up being easier.

However, there is one scenario in which people often go with JDBC when EJB might make their lives easier. Say that you have no need of transactional support and the data with which you are interacting does not involve parent-child or foreign key relationships, but you still need to represent that data as an object (potentially in relation to other objects that also represent data). To be more specific, suppose your application handles only contact management. The application may not write data very often and there may be little need for the transactional support or security provided by EJB. However, your application needs to represent contacts (and their affiliated phone numbers, addresses, and so on) as business objects. The ease with which EJB can help you represent this data as business objects, specifically as entity beans, may save a great deal of time.

The situations in which straight JDBC is preferable to EJB are not concrete. You should use straight JDBC when the need for speed outweighs the need for transactional support or security provided by EJB. Here’s a simple example that uses JDBC:

import java.sql.*;
 
public class JDBCExample {
 
 public static void main(java.lang.String[] args) {
   try {
     // Load driver
     Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
   } 
   catch (ClassNotFoundException e) {
     System.out.println("Cannot load driver.");
     return;
   }
  
   try {
     // Connect to database.
     Connection con = DriverManager.getConnection("jdbc:odbc:contactdb",
              "", "");
  
     // Create SQL Statement and execute.
     Statement stmt = con.createStatement( );
     ResultSet rs = stmt.executeQuery("SELECT name FROM contacts");
 
     // Display the SQL Results.
     while(rs.next( )) {
       System.out.println(rs.getString("name"));
     }
 
     // Release database resources.
     rs.close( );
     stmt.close( );
     con.close( );
 
     } 
     catch (SQLException se) {
       // Display error message upon exception.
       System.out.println("SQL Exception: " + se.getMessage( ));
       se.printStackTrace(System.out);
      } 
    } 
}

JDBC is very straightforward; it allows you to access your data repository directly. However, you must understand a fair amount of the underlying mechanics in order to use it (SQL, database connection properties, and so on). Now, in a “real” application using JDBC, you centralize most of this code into a few classes, but you still must write all the SQL yourself.

Java Data Objects

Java Data Objects or JDO is a recent Sun specification for database persistence and access with Java. According to the JDO specification (JSR 12), its objectives are:

...first, to provide application programmers a transparent Java-centric view of persistent information, including enterprise data and locally stored data; and second, to enable pluggable implementations of data stores into application servers.

This description sounds very similar to the objectives laid out for JDBC or EJB. Why another specification to allow for database connectivity and use? For one thing, after setting up a mapping file, you need not deal with database information again; you can access data as you would access Java objects. You can edit and delete data using a “persistence manager” (more on this in a moment) that insulates you from having to deal directly with the SQL involved.

But EJB does these things as well. Once you have set up your EJB and created a suitable descriptor file, you deal with the data through the use of the objects representing the data (as opposed to through result sets as in JDBC, for example). However, JDO allows for a simpler mapping (JDO mapping files are simpler than EJB descriptor files); in addition, there’s no mucking about with remote and home interfaces. JDO classes look like any other classes.

There are six basic steps to using JDO in your applications:

  1. Create a Java class that represents the underlying database business entity.

  2. Create a metadata file containing information about the fields of your Java class. This metadata file can contain data about your already existing database, or not. If it does not, you can run a schema builder that looks at this object and generates the SQL for the database generation.

  3. Compile your Java to a .class file.

  4. Run the JDO enhancer against your metadata file. The enhancer grabs your class name from the metadata file and uses it to grab the compiled .class file. The enhancer then modifies the .class file—at the bytecode level—to implement JDO’s PresistenceCapable interface.[70]

  5. Run the JDO schema builder[71] against your metadata file and the (now modified) .class file for your Java class. The schema builder generates DDL SQL that you can use to create the database objects required for your newly modified JDO class. (Optional)

  6. Create an application that uses your Java class. This application will use the PersistenceManagerFactory and PersistenceManager classes from your JDO implementation. These two classes are your handlers for interacting with your newly created class file.

The best way to demonstrate this process is through a brief example. We’ll create a very simple Contact class and uses JDO to persist it to a database. We use the LIBeLIS LiDO JDO implementation (community edition). In this implementation, the generation of a database schema involves the use of a separate application from the JDO enhancer:

package com.oreilly.ejb.jdoexample;

public class SimpleContact {
        public String name;
        public String ssn;
        
        public AddressImpl(String pName, String pSsn){
                this.name = pName;
                this.ssn = pSsn;
        }
        
        public String getName( ) {
                return this.name;
        }

        public String getSsn( ) {
                return this.ssn;
        }

        public void setName(String pName) {
                this.name = pName;
        }

        public void setSsn(String pSsn) {
                this.ssn = pSsn;
        }
}

The SimpleContact class contains no details on how the information will be persisted to the database, nor the fact that it will implement the PersistenceCapable interface.

Next, we create a metadata file for SimpleContact, called SimpleContact.jdo:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "file:/c:/work/jdo.dtd">
<jdo>
   <package name="com.oreilly.ejb.jdoexample">
      <class name="SimpleContact" identity-type="datastore">
      </class>
   </package> 
</jdo>

This code is pretty straightforward. The metadata points to the location of the JDO DTD (which you can get from your implementation), the package name for your class, and the name of the class itself.

We’ll assume you compile your SimpleContact.java file to SimpleContact.class. Now you must “enhance” the SimpleContact.class file so that it implements the JDO PersistenceCapable interface like so:

java com.libelis.lido.Enhance -metadata SimpleContact.jdo

This command reads the SimpleContact.jdo file, uses it to find SimpleContact.class, and modifies its bytecodes to implement the JDO PersistenceCapable interface. Next, you can build a schema like this:[72]

java com.libelis.lido.ds.jdbc.DefineSchema
     -driver org.gjt.mm.mysql.Driver
     -database jdbc:mysql://localhost/jdoexample
     -metadata metadata.jdo

This generates a series of SQL files (not shown) that you can use to generate the database for your SimpleContact data. All that’s left is to create an application that allows you to use your new persistent object. The following class allows you add a new SimpleContact instance to the database:

package com.oreilly.ejb.jdoexample;

import javax.jdo.PersistenceManagerFactory;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;

public class Test1 {
    public static final String DBURL = "jdbc:mysql://localhost/jdoexample";
    public static final String DBDRIVER = "org.gjt.mm.mysql.Driver";

    public static void main(String[] args) {
        try {
            // Use a factory class to generate PersistenceManager.
            // You are using the LIBeLIS JDO implementation
            // of the PersistenceManagerFactory and PersistenceManager
            // classes.
            PersistenceManagerFactory pmf = (PersistenceManagerFactory)
              Class.forName("com.libelis.lido.PersistenceManagerFactory")
                   .newInstance( );
            pmf.setConnectionURL(DBURL);
            pmf.setConnectionDriverName(DBDRIVER);
            PersistenceManager pm = pmf.getPersistenceManager( );

            // Grab the current transaction.
            Transaction t = pm.currentTransaction( );

            // Start a new transaction
            t.begin( );

            SimpleContact a =
            new SimpleContact("Gern Blanston", "222334444");
            pm.makePersistent(a);
            // Commit the transaction.
            // All changes made between the begin and 
            // commit are persisted to the DB.
            t.commit( );

            pm.close( );
        } catch (Exception e) {
            e.printStackTrace( );
        }
    }
}

You start by instantiating a PersistenceManagerFactory, which then generates a PersistenceManager for your use. Finally, you create an instance of our SimpleContact class and then tell the PersistenceManager to write it (by committing the transaction begun earlier.

There is much more to JDO than this very simple example demonstrates (such as editing, deleting, and querying using the JDO query language). For more information about JDO, see Java Data Objects, by David Jordan and Craig Russell (O’Reilly). JDO is worth investigating, especially if you have no need for the extra transactional and security features provided by EJB.

While JDO is an alternative to EJB, the context in which it is used must be seriously considered. EJB is designed for high-traffic transaction-centric systems. These types of applications are not a very good fit for JDO because it doesn’t have the enterprise level support for transactions, security, clustering and sessions that EJB does. Smaller systems can frequently be built using JDO, but really big systems are best left to EJB.

Others

There are, of course, other alternatives to EJB than straight JDBC and JDO. Here are a few worth reviewing for suitability, should you determine that your application does not require EJB or that certain requirements (speed, for example) demand an alternative approach.

Castor JDO[73] (http://www.exolab.org)

While Castor JDO contains the word “JDO,” Exolabs built it independently from Sun’s specification. Like JDO, its primary function is to perform data binding. Castor generates Java class source files from an XML schema document that describes the XML data model of an object. You can instantiate objects of these classes directly from XML documents, if those documents conform to the original XML schema. However, the conversion of an XML document into an object instance is only half of what Castor provides; it can also turn an object instance back into an XML document. Conversion from object to XML document is called marshalling, and it’s Castor’s original focus. In addition, Castor has the ability to map objects to database tables through mapping files very similar to those for JDO.

Hibernate (http://www.hibernate.org)

Hibernate is another Java class-to-database table mapping project. While JDO is designed for mapping Java objects to relational or object-oriented data stores, Hibernate is specifically designed for object relational (OR) mapping. It allows you to create straight Java classes and a database-mapping file (by hand or automatically, using XDoclet tags or something similar). The mechanics of interacting with the database are similar to those of JDO, but with slightly different manager objects (sessions and connections instead of managers, etc.). This is gross oversimplification of all that Hibernate will do, but suffice it to say that Hibernate is functionally equivalent to something like JDO, which maps Java objects to database entities through an XML mapping file and handles the persistence machinery for you. Take a look at Hibernate instead of EJB if you are considering JDO, as the two are similar and fit in similar situations.

Prevayler (http://www.prevayler.org)

Prevayler approached data binding from a very different perspective, one that does not rely on mappings. Prevayler is all about speed. It uses a fairly old idea: keep all your data in RAM throughout the life of your application and write your data en masse to the database from time to time. This approach makes accessing database information much faster (mostly because you are accessing RAM instead of the database after your data is loaded into memory). Where would it make sense to use Prevayler? The most effective target for something like Prevayler is a single-user database application when storage of database changes can be non-realtime. It is also appropriate for read-only “static” systems in which the data is mostly unchanging.

As you can see, there are several alternatives to EJB. If your application doesn’t need the complexity or some of the features of EJB, take a look around. Data persistence with Java has been around for some time and there is a wide assortment of approaches.



[70] The use of an implementation-specific JDO enhancer to modify your compiled class at the bytecode level is still debated often in the JDO community. The specification does not force this implementation. You can also simply modify your Java class to implement the PersistenceCapable interface yourself.

[71] In some JDO implementations, the schema builder is just a side effect of the enhancer. In these implementations, you must specify a command-line parameter to tell the enhancer to generate schema generation SQL (rather than run a separate schema builder application).

[72] There are several details carefully ignored here so as not to interfere with the JDO example. For example, we will not cover the setup of the MySQL JDBC driver or MySQL itself.

[73] Castor JDO was developed and useful before Sun’s JDO spec. There is some debate as to whether “JDO” should be used with Castor or not, but this seems too contrived to some extent to build support for Sun’s JDO. While Castor JDO is still useful, the debate as to whether it constitutes “real” JDO has led to a decline in its acceptance in some circles.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.22.179