Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Using a Generic SQL Entity EJB Wrapper to Simplify EJB Development

Tony Lau (tktlau@ca.ibm.com), Software Engineer, IBM, Software Group
Tony Lau is an IBM certified Systems Expert. He earned his Bachelor Degree of Applied Science in computer engineering from the University of Waterloo. He is an active member in UW Alumni. His current focus is DB2 performance for WebSphere and ebusiness applications. You can reach him at tktlau at ca.ibm.com.

Summary:  Enterprise JavaBeans (EJBs) are designed to reduce development time for enterprise applications, but it is possible to misuse EJBs and end up with an application that is difficult to maintain and performs poorly. This article describes a coding technique to simplify bottom-up EJB development and which enables end-to-end code generation. The examples presented in the article are based on IBM DB2 Universal Database and WebSphere Studio.

Date:  05 Jun 2003
Level:  Introductory

Activity:  5034 views
Comments:  

Important: Read the disclaimer before reading this article.

Introduction

Enterprise JavaBeansTM (EJBs) are designed to help significantly reduce development time for enterprise applications. As a quick review, there are two types of EJBs: session beans that provide business logic, and entity beans that encapsulate business data. Session beans are analogous to database stored procedures, and entity beans are analogous to database result sets. EJBs provide built-in features for remote access, scalability, security, and transactions. These built-in features do not come without cost. A simple stored procedure, one that does a single SQL statement, is one small source file. A simple session EJB that performs the same task requires more than 10 class files. It is easy to misuse EJBs and therefore end up with an application that is difficult to maintain and performs poorly.

JavaTM 2 Enterprise Edition (J2EE) uses entity EJBs to provide a layer of abstraction to the underlying relational database system. However, the interface of entity EJBs complicates the process of simply using SQL statement for database applications. Especially in bottom-up development projects and in legacy database development, design is database-oriented, which means it makes sense for architects to think in terms of SQL calls rather than EJB factories and objects.

I propose a design pattern that generalizes the use of entity EJBs to simplify EJB development. The design pattern retains the intuitive SQL interface, yet delivers the reusability and built-in distributed transaction support of EJBs. Many common cases can be handled. Because it is generalized, it can be used for automatic code generation. Given a database table, the bottom-up approach can generate code from Container-Managed Persistence (CMP) entity beans, session beans, up to a Java Server Page (JSP) or even a Web service.


The generic entity EJB wrapper

The generic SQL entity EJB wrapper is a helper class that manipulates entity EJB factories and interfaces to achieve the goal as to execute certain SQL statements by providing an intuitive SQL interface.

Figure 1 illustrates a typical EJB facade pattern. The EJB session facade pattern provides a stable, high-level gateway to the server-side components. The model layer consists of the relational database and a collection of entity EJBs. Each entity bean is an abstraction of a row of data; the relational database is responsible for persistent storage. The business layer consists of a session EJB, which is a client to the entity bean. Any method defined in the session bean is a transaction. The method in the session bean is where you implement the business logic.


Figure 1. EJB programming modelFigure 1. EJB programming model
EJB programming model

The functions inside the entity bean are called through the home and remote interfaces of the bean, which involves extensive use of the following packages:

 
javax.ejb.* 
java.rmi.* 
javax.naming.* 

The home interface of an entity bean lets a client create new entity bean instances, look up existing entity beans, and remove entity bean instances. The remote interface of an entity bean allows a client to invoke the business methods of the bean such as the setter and getter. All of these are translated to JDBC calls by the container. To ensure correct use of the EJB and to ensure efficient resultant SQL statements, you may want to refer to the best practices articles in IBM Developer Domain [Ref.1].

Figure 2 shows how the generic SQL EJB wrapper can simplify these tasks. With the helper class, database development becomes more intuitive and generic. This class is basically doing a reciprocal mapping of functions. The EJB container maps SQL JDBC calls to a complex matrix of methods inside the entity beans, and the SQL EJB helper class maps the methods back to SQL wrappers.


Figure 2. EJB programming model using the SQL EJB wrapper
EJB programming model using the SQL EJB wrapper

In the business method inside the session bean, get a handle to a generic SQL EJB wrapper and call the desired SQL methods provided by the wrapper. The SQL EJB helper methods will manipulate the entity bean interfaces to execute the desired SQL statements. Furthermore, the SQL EJB wrapper can also leverage the entity bean local interface when both the facade bean and the entity beans are in the same machine. All best practices can be encapsulated into the wrapper. These are all transparent to the business logic developers.


Usage example 1: Application development

In this section, I compare how you can develop a single transaction using the current technology to how you can perform the same task using the generic entity bean wrapper.

Current technology

Consider the steps involved in developing a single transaction in the Application Developer configuration of WebSphere® Studio:

  1. Use the Enterprise Bean wizard to generate the entity beans.
  2. Use the Enterprise Bean wizard to generate a facade session bean.
  3. Implement the EJB helper code.
  4. Develop the transaction logic.

With the current technology, Websphere Studio can easily generate a layer of entity bean objects and an empty facade session bean as listed in Steps 1 and 2 above. WebSphere Studio can retrieve the database schema by simply going through DB2® Universal DatabaseTM (UDB) JDBC metadata support.

Step 3 is the development of the EJB helper code. Listing 1 is the helper code extracted from the WebSphere Performance Benchmark Sample [Ref. 2]. This is where you as a developer code the routines to handle the EJB context, home lookup and caching. This would also involve intensive exception handling and inline documentation.

Listing 1. The EJB helper code

public class TradeStaticContext 
{ 
 
private static boolean verbose = true; 
static InitialContext _initContext = null; 
static QuoteHome _marketHome = null; 
 
public static QuoteHome getQuoteHome() 
{ 
 
if (_initContext == null) 
{ setContext(); } 
return _marketHome; 
 
} 
 
private static synchronized void setContext() 
{ 
 
InitialContext localContext = null; 
//Trade 2.037 - Fixes startup race condition - 
//if _initContext has been set, another thread got here first 
//and has already setup the EJB Homes 
 
if (_initContext != null) 
 return; 
 
if (verbose) 
{ 
 System.out.println( "TradeStaticContext.setContext: Setting context" ); 
} 
 
try 
{ 
 localContext = new InitialContext(); 
} 
catch (Exception me) 
{ 
 System.out.println( 
 "TradeStaticContext.setContext: Get InitialContext failed!!"); 
 me.printStackTrace(); 
} 
 
try 
{ 
 Object obj = null; 
 //#x2026 
 obj = localContext.lookup("java:comp/env/ejb/Quote"); 
 _marketHome = 
(QuoteHome) javax.rmi.PortableRemoteObject.narrow(obj, QuoteHome.class); 
 // Trade 2.037: Set _initContext after all EJB Homes have been setup to avoid 
race condition 
 _initContext = localContext; 
} 
catch (Exception me) 
{ 
 System.out.println("TradeStaticContext.setContext: Lookup Homes failed!"); 
 me.printStackTrace(); 
 _initContext = null; 
} 
 
//#x2026 
if (_marketHome == null) 
{ 
 
 System.out.println( 
 "TradeStaticContext.setContext: Exception creating QuoteHome"); 
 _initContext = null; 
 
} 
 
} 
 
}


Step 4 is where you implement transaction logic. The body of the transaction is put inside the session bean. Some helper functions are called to facilitate the coding, as shown in Listing 2.

Listing 2. Transaction logic inside the session bean

public class TradeBean implements SessionBean 
{ 
 
public QuoteObject getQuote(String symbol) 
 throws RemoteException, TradeException 
{ 
//#x2026 
Quote quote = findQuote(symbol); 
} 
 
private Quote findQuote(String symbol) 
 throws RemoteException, TradeException 
{ 
//#x2026 
QuoteHome qhome = TradeStaticContext.getQuoteHome(); 
retval = qhome.findByPrimaryKey(new QuoteKey(symbol)); 
} 
 
} 

Very clearly, a simple transaction (a single SELECT statement to the underlying database) is a nontrivial task in the EJB programming model.

Generic EJB wrapper technology

Consider the same tasks with the help of generic SQL entity EJB wrapper:

  1. Use the Enterprise Bean wizard to generate the entity beans.
  2. Develop (or generate) the generic SQL entity EJB wrapper code.
  3. Use the Enterprise Bean wizard to generate a facade session bean.
  4. Fill in the business logic inside the facade session bean.

Very similarly, Websphere Studio can easily generate a layer of entity bean objects and an empty fa#x437ade session bean as listed in Steps 1 and 3 above. WebSphere Studio can retrieve the database schema by simply going through DB2 JDBC metadata support.

One possible way to execute Step 2 is to develop an Eclipse plug-in that generates the generic SQL entity EJB wrapper code based on best practices and lessons learned. (Sample code will be provided in a followup article.) This can greatly improve your productivity. With a generic SQL entity EJB wrapper, just a few mouse clicks will enable you to generate a J2EE application that is ready for the Universal Test Client (UTC), including the Select, Insert, Delete, and Update default methods for any table. Developers can now customize the code and define their own business methods.

In Step 4, business transactions can be put into the body of the facade session bean. In Listing 3, a getQuote transaction is added.

Listing 3. getQuote transaction added to facade session bean

public class RegistryFacadeBean implements SessionBean 
{ 
// Add user defined business methods here 
public QuoteData getQuote(String symbol) 
{ 
		QuoteWrapper wQuote = new QuoteCMPWrapper(); 
		Vector vQuote = wQuote. 
		Select( symbol, null, null ); 
		if( vQuote.size() == 0 ) 
			return null; 
		else 
			return ( QuoteData ) vQuote.get( 0 ); 
} 
 
} 

When working from the bottom up, getQuote is more naturally implemented as a SELECT. To do this, simply obtain a handle to the generated model helper (that is, the entity bean wrapper) and call the Select() method.

In this implementation, the Select() method is more than just a wrapper. It is a SELECT template, which supports different possible combination of "=" Boolean predicates. For example, the statement: Select( symbol, null, null )

Will be turned into the following EJBQL:

 
Select object(q) from Quote q where q.symbol=?l  

If you changed this to:

 
Select( symbol, price, null )  

The following is executed:

 
Select object(q) from Quote q where q.symbol=?l and q.price=?2 

And so on.

The IBM® AccessBean also shields the client program from the complexities of managing enterprise bean lifecycles. It would be interesting to see how AccessBeans and the SQL wrapper interface can work together to make bottom-up EJB development easier.


Usage example 2: Generating EJB Web pages

WebSphere Studio has an excellent Database Web Pages wizard. Given a SQL statement, the wizard can generate the HTML and JSP code that can access the database through JDBC. If you want to do this in EJBs instead of JDBC, you may want to leverage the generic entity EJB wrapper. This section describes how end-to-end EJB Web pages can possibly be generated as sample code using the generic SQL entity EJB wrapper.

Sample database

This is bottom-up code generation, and the database is the starting point. The example below illustrates how end-to-end bottom-up code is generated starting from a DB2 database table using the generic SQL entity EJB wrapper. Consider the following table definition as a starting point of our code generation example.

 
Column                         Type      Type 
name                           schema    name 
 
------------------------------ --------- ------------ 
 
USERID                         SYSIBM    VARCHAR 
 
PASSWORD                       SYSIBM    VARCHAR 
 
STATUS                         SYSIBM    INTEGER 

Entity bean

An entity bean is generated using the Enterprise Bean Wizard for the table shown above. An entity bean is an abstraction of a row of data. The table columns are mapped to the container-managed fields.

Listing 4. Generating an entity bean

public class RegistryBean implements EntityBean 
{ 
	// Container managed fields 
	public java.lang.String userid; 
	public java.lang.String password; 
	public java.lang.Integer status; 
//... 
} 

Generic SQL entity EJB wrapper

A SQL entity EJB wrapper is generated by the Eclipse plug-in that we mentioned in Usage Example 1 for the entity bean. The wrapper implements the Select, Insert, Delete, and Update method interfaces.

Listing 5. The SQL entity EJB

public interface RegistryWrapper 
{ 
	public Vector Select( RegistryData dRegistry ); 
	public Vector SelectForUpdate( RegistryData dRegistry ); 
	public void Insert( RegistryData dRegistry ); 
	public void Delete(); 
	public void Update( RegistryData dRegistry ); 
} 

The RegistryData class is a data class. In our case, it is used as placeholders for the SQL predicates and for the result sets passed to and from the session bean and entity beans.

Facade session bean

The Enterprise Bean Wizard can generate a facade session bean for the entity bean for the entity bean. The session bean is where you implement business methods. The Select, Insert, Delete, and Update business methods are generated by default. The entity bean wrapper is called within the relational database business methods.

Listing 6. The facade bean for the entity bean

public class RegistryFacadeBean implements SessionBean 
{ 
	public Vector Select( RegistryData dRegistry ) {	 
		RegistryWrapper wRegistry  
			= new RegistryCMPWrapper(); 
		return wRegistry.Select( dRegistry ); 
	} 
	 
	public Vector SelectForUpdate( RegistryData dRegistry ) 
	{ /*...*/ } 
	 
	public void Insert( RegistryData dRegistry ) { /*...*/ } 
	 
	public void Delete() { /*...*/ } 
	 
	public void Update( RegistryData dRegistry ) { /*...*/ } 
 
	// Add user defined business methods here 
} 

In the example in Listing 6, the generated Select() business method is completed by simply calling the Select() method in the Registry entity bean wrapper. The implementation of the Insert, Delete, Update business methods are similar.

Client

The SQL methods in the facade session bean can then be promoted to the controller layer and/or the presentation layer for testing purpose. This is not limited to servlets and JSPs. There is nothing preventing the methods from being promoted to clients like J2EE applications, Java Applets, and Web services.


Conclusion

The generic SQL entity EJB wrapper not only simplifies bottom-up EJB database development, but also allows end-to-end code generation in many situations. As shown in the examples, the generalization provides an opportunity to use generated code, and the encapsulation greatly enhances the productivity of bottom-up EJB programming and legacy database development. This implementation can be used by WebSphere and DB2 UDB. A coming article will talk about the practical usage of the design pattern in details.


Disclaimer

This article contains sample code. IBM grants you ("Licensee") a non-exclusive, royalty free, license to use this sample code. However, the sample code is provided as-is and without any warranties, whether EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. IBM AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE THAT RESULT FROM YOUR USE OF THE SOFTWARE. IN NO EVENT WILL IBM OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents.


Acknowledgements

The author would like to thank Peter Shum, Matthew Huras, and Grant Hutchison for their valuable input and suggestions.


References


Appendix A - Generated SQL EJB wrapper interface for the Registry bean with Inline documentation

 
/** 
 * The Select() method maps to the Registry EJB finder method. Initial 
 * context is obtained and Home interface is looked up if necessary. The 
 * parameters are used as the predicates in the where clause. Any reference to 
 * null will be taken away from the clause. For example, a call to  
 *  
 * 	Select( null, null, 1 ) 
 *  
 * translates to the SQL statement 
 *  
 * 	select * from Registry where status = 1  
 */ 
public Vector Select(java.lang.String userid, java.lang.String password, 
java.lang.Integer status); 
 
/** 
 * Same as above except parameters are passed in form of RegistryData 
 * wrapper. 
 */ 
public Vector Select(RegistryData data); 
 
/** 
 * The Insert() method maps to the Registry EJB create method. Initial 
 * context is obtained and Home interface is looked up if necessary. The  
 * parameters are the data to be inserted to the underlying table. 
 */ 
public void Insert(java.lang.String userid, java.lang.String password, 
java.lang.Integer status) 
throws javax.ejb.CreateException, java.rmi.RemoteException; 
 
/** 
 * Same as above except parameters are passed in form of RegistryData 
 * wrapper. 
 */ 
public void Insert(RegistryData data) 
throws javax.ejb.CreateException, java.rmi.RemoteException; 
 
/** 
 * The Delete() method maps to the Registry EJB remove method. Initial 
 * context is obtained and Home interface is looked up if necessary. The  
 * Select() method must be called beforehand with resultset not null 
 */ 
public void Delete(); 
 
/** 
 * The Update() method maps to the Registry EJB setter methods. Initial  
 * context is obtained and Home/Remote interface is looked up if necessary. The 
 * parameters contain the updated data for the current row(s). The  
 * Select() method must be called beforehand with resultset not null 
 */ 
public void Update(java.lang.String userid, java.lang.String password,
java.lang.Integer status); 
 
/** 
 * Same as above except parameters are passed in form of RegistryData 
 * wrapper. 
 */ 
public void Update(RegistryData data); 

IBM, DB2, DB2 Universal Database and WebSphere are trademarks or registered trademarks of IBM Corporation in the United States, other countries, or both.

Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

Other company, product, and service names may be trademarks or service marks of others.

IBM copyright and trademark information


Resources

About the author

Tony Lau is an IBM certified Systems Expert. He earned his Bachelor Degree of Applied Science in computer engineering from the University of Waterloo. He is an active member in UW Alumni. His current focus is DB2 performance for WebSphere and ebusiness applications. You can reach him at tktlau at ca.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management, WebSphere
ArticleID=13968
ArticleTitle=Using a Generic SQL Entity EJB Wrapper to Simplify EJB Development
publish-date=06052003
author1-email=tktlau@ca.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers