Open Development Platform

Eclipse Platform

Subscribe to Eclipse Platform: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Eclipse Platform: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Eclipse Platform Authors: Janakiram MSV, Ken Fogel, Marcin Warpechowski, Michael Meiner, Liz McMillan

Related Topics: Java EE Journal, Apache Web Server Journal, Eclipse Platform, Java Developer Magazine, MySQL Journal

J2EE Journal: Article

Java Feature — Bringing Together Eclipse,WTP, Struts, and Hibernate

Bringing Together Eclipse,WTP, Struts, and Hibernate

The file in Listing 8 contains two class tags, where each of our domain classes Customer and Order is mapped to the corresponding database table, with each instance variable mapped to a database column. One attribute worth mentioning is "lazy" - we have explicitly set to it to false, the reason being that when lazy is true (default), reading from the database is only done whenever a particular method is accessed. For example, it'll happen only when a getFirstName() is called, rather than pre-reading the whole set of customers right away - when the SQL query is issued. This may sometimes be beneficial when you read a large set of data and want to defer expensive database operations. In our example, we're only reading a small set of customers and don't want additional performance or database access issues to occur later, such as if the database session is closed at that later time, we'll get an exception from Hibernate if we still try to invoke the "lazy" method.

The Hibernate configuration is complete, and we have to modify our CommandExecutor class a bit to use the framework and remove hard-coded SQL code. This class has been used as a singleton for storing data sources and getting database connections. First of all, we'll be adding the instance variable to store the Hibernate session factory. The Hibernate session factory is similar to a data source, except instead of getting database connections from it, we'll be getting Hibernate database sessions. The instance variable will look simply as follows:

private SessionFactory sessionFactory = null;

Next, we want to create an access method for this instance variable (See Listing 9). This will maintain the object state encapsulated, and will also allow using techniques of the lazy initialization (access the data only when needed):

In this method, we initialize a session factory for the first time. Hibernate's Configuration object is used to read the configuration file from the classpath and initialize the framework accordingly.

We've used the executeDatabaseCommand() method before we started using Hibernate to perform our database operations: using the DatabaseCommand interface that required the executeDatabaseOperation() method. Since we now want to use Hibernate, we're going to introduce another method to the DatabaseCommand interface and another one to the CommandExecutor singleton object - this method will execute all of our database operations using Hibernate framework (See Listing 10).

This looks very like the executeDatabaseCommand() method, except that in this case, we're using a Hibernate Session object rather than a normal JDBC connection. The next step would be simply to add the following stub method to the DatabaseCommand interface:

public Object executeHibernateOperation(Session session) throws SQLException;

Now that we've added this new method to the interface, all the classes implementing this interface will be marked with red bullets in the Eclipse workbench, because the classes implementing the interface have to implement all the methods that it requires. We have four classes implementing the database command interface:

public class CreateCustomer implements DatabaseCommand
public class CreateOrder implements DatabaseCommand
public class ListCustomers implements DatabaseCommand
public class ListCustomerOrders implements DatabaseCommand

Hence we have to add an executeHibernateOperation() implementation method to each of them. Let's take a look at the CreateCustomer class first. Its executeDatabaseOperation() method is shown in Listing 11.

This method is fairly long and coding one requires a developer to know JDBC: how to create and execute prepared statements. Also, if one were to change the database from MySQL to some other one, it might require that the developer re-write the SQL because it may differ from one database to another. With Hibernate, you just change the SQL dialect in the hibernate.cfg.xml configuration file. Our corresponding executeHibernateOperation() method is in Listing 12.

In Listing 12 we tell the session object to save our class in the database. No SQL, no JDBC knowledge, no hard-coding of column and table names. If we have to change the table or column name, we don't have to go through possibly multiple lines of code in the application. Hibernate knows how to save the object, whether this object already exists in the database or not (to do an INSERT or UPDATE operation - it performs a check in either the optimistic way (tries to do an UPDATE, and if that fails, INSERT) or pessimistic way (does a SELECT to see if the row exists, if yes, then does UPDATE, otherwise INSERT). We flush the session after the execution of the command to make sure that all the database commands are executed right away without anything left over in the framework's buffer. In a similar fashion we perform the operation for the CreateOrder class.

First, the two operations that we have dealt with (in the JDBC version), CreateCustomer and CreateOrder, are database insert operations. However, one also has to handle database queries to make the application work. For that, we have ListCustomers and ListCustomerOrders commands. Let's look at how we get the customer list.

Listing 13 contains a bunch of JDBC calls. First, create an SQL statement, execute it using hard-coded column and table names, and then go through the ResultSet of the database query and construct a Customer domain object explicitly from each row read from the table, where we also have to remember the column order or names. All those operations are error prone and may become hard to maintain whenever changes to the database tables are required. This is where Hibernate comes to the rescue. It introduces a whole new language called the Hibernate Query Language (HQL), where one doesn't need to query database tables, but rather objects. Our executeHibernateOperation() method will look as in Listing 14.

Once again this method looks pretty similar to the old one, however, there are some significant differences. Here we are using a bunch of Hibernate objects. The first one is a Query class. It lets one create and execute database queries using either HQL (through the createQuery method) or regular SQL (through the createSQLQuery method). Let's look at the HQL we are using here:

from customer in class domain.Customer

Basically we're selecting all the customers identified by the variable customer from the domain.Customer class. Obtaining the iterator of the query lets us put "customers" in any collection. In our case it's ArrayList<Customer>.

A very similar method can be written for the ListCustomerOrders class, but HQL is a tiny bit more complex as you can see in Listing 15.

In this case we use the where-clause in our query. Note that in this where-clause we can use the instance variable of the Order class (custId) to query by. The syntax is similar to Java's dot notation.

Finally we have to update our Struts action classes to invoke the executeHibernateOperation() method instead of the executeDatabaseOperationMethod(). This can be done easily using Eclipse editors.

Exporting an Eclipse Project into WAR
Using WTP tools we can easily export our project into the WAR file to be deployed under Tomcat. Just select the DBTestStruts Web project, then select Export from the File menu. When prompted, select the WAR file, specify the file name, and you'll have the WAR file ready to be deployed in Tomcat.

Conclusion
The goal of this article was to how you how to integrate Struts and Hibernate support into a simple Web application developed using Eclipse and WTP tooling. These frameworks help to improve application maintainability and code reusability, as well as code clarity.

More Stories By Boris Minkin

Boris Minkin is a Senior Technical Architect of a major financial corporation. He has more than 15 years of experience working in various areas of information technology and financial services. Boris is currently pursuing his Masters degree at Stevens Institute of Technology, New Jersey. His professional interests are in the Internet technology, service-oriented architecture, enterprise application architecture, multi-platform distributed applications, and relational database design. You can contact Boris at [email protected]

Comments (10) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Achille 06/22/08 07:48:25 PM EDT

Reading this:
"// This abstract class overrides Struts action class execute method and provides abstract
// performAction method to be overwritten by sub-classes. This helps us isolate some
// common error processing into one place, rather than having it several places in the
// sub-classes."
I don't really see how handling the errror in the AbstraAction class simplify error handling the subclasses.
In errors.add("name", new ActionError("id")); the value & key pair are different from what we have in subclasses.

Mintara 12/26/07 04:18:28 PM EST

Hello,
Could you please tell me how this dbtest worked?
As I tried following the article but was lost when
it spoke of the different classes I did not know what these classes should contain and how they communicate with each other.
Thank you for your help

Lucas 06/09/06 06:07:15 PM EDT

Hi,

I got an error trying to uncompress the .war file, it seems that it's broken.

SEVERE: Exception fixing docBase: {0}
java.util.zip.ZipException: error in opening zip file

Lucas.

Boris Minkin 06/02/06 09:43:19 AM EDT

Some users have complained about corrupted .war file.
Here is a link to the good one:
http://www.panix.com/~bm/DBTestSH.war

karthik 05/31/06 05:25:25 PM EDT

The war file is corrupted

mark 05/31/06 09:47:56 AM EDT

I think the war file is corrupted. regards Mark

Jim 05/29/06 12:59:06 PM EDT

The provided DBTestSH.war is a corrupted one. You can not unzip it. Please check.
Thanks!

SYS-CON India News Desk 05/10/06 01:44:20 PM EDT

In the article 'Creating Web Applications with the Eclipse WTP' (http://jdj.sys-con.com/read/152270.htm ), we created a Web application using Eclipse Web Tools Project, the Tomcat application server, and the MySQL database server. That application (DBTest) was good, however, it had some limitations

DH Allingham 05/09/06 10:38:51 AM EDT

While it was nice to see you bring all of these technologies together (Struts, XML, Java, Hibernate, WTP, MySQL and it's connector). One has to ask; "But why is this necessary?". This represents 7 technology related fail points and 7 tools that a programmer needs a good familiarity with to be efficiently productive. This is way too many! Each additional tool adds extra cost to evaluating programmers to staff business level Java client/server application development positions and increases project risk. While I love Java, as a manager, this is a huge problem with it's use.

What I'd like to see a lot more of is POJO solutions to serious Web application development problems.

While its great that you can bring all of these tools together to solve a problem, it does little to address the fundamental flaw with Java (and several other languages) which is... Java is not really designed for Server/dumb client applications (which are Web apps.) and after 10 years have been spent kludging it to fit that round hole... here we are still trying to make a square peg round.

If I'm wrong, I'd be thrilled to admit it. But to prove me wrong you have to build a true business level Web app. with just Java, an IDE, a database engine and its aplicable connector, and any vanilla Web server engine you choose. That's it. No XML, no cocoon, jscript, Struts, nada, zip. Oh, one final condition... development time has to be within 15% of development with all those "assists". If this can't be done, then let's all stop fooling ourselves, find something that does, and leave Java to solve the other problems it is designed for and stop trying to fit it into the wrong type of hole.

DH Allingham 05/09/06 10:30:51 AM EDT

While it was nice to see you bring all of these technologies together (Struts, XML, Java, Hibernate, WTP, MySQL and it's connector). One has to ask; "But why is this necessary?". This represents 7 technology related fail points and 7 tools that a programmer needs a good familiarity with to be efficiently productive. This is way too many! Each additional tool adds extra cost to evaluating programmers to staff business level Java client/server application development positions and increases project risk. While I love Java, as a manager, this is a huge problem with it's use.

What I'd like to see a lot more of is POJO solutions to serious Web application development problems.

While its great that you can bring all of these tools together to solve a problem, it does little to address the fundamental flaw with Java (and several other languages) which is... Java is not really designed for Server/dumb client applications (which are Web apps.) and after 10 years have been spent kludging it to fit that round hole... here we are still trying to make a square peg round.

If I'm wrong, I'd be thrilled to admit it. But to prove me wrong you have to build a true business level Web app. with just Java, an IDE, a database engine and its aplicable connector, and any vanilla Web server engine you choose. That's it. No XML, no cocoon, jscript, Struts, nada, zip. Oh, one final condition... development time has to be within 15% of development with all those "assists". If this can't be done, then let's all stop fooling ourselves, find something that does, and leave Java to solve the other problems it is designed for and stop trying to fit it into the wrong type of hole.