Wednesday, February 27, 2008

10 important things using Hibernate/JPA

1) Become friends with the DBAs.

There is a tendency for some Java developers to marginalize the importance of DBAs. This is a huge mistake - a good working relationship with the keepers of the data is critical to success with any ORM technology. This is important for two reasons:

  • DBAs alone usually can’t make your Hibernate efforts successful, but they often can make them fail.
  • They usually have really good insight into the database itself, good modelling practices, and any pitfalls or shortcuts for you. I can think of several instances where a timely suggestion from a DBA saved us days and gave us an elegant solution.

In most cases, having good DBAs and having good relationships with them is highly critical to the success of your ORM efforts. Plus, database guys are usually pretty cool people :)

2) Use (and enforce) good naming standards from the beginning.

Who knew naming standards discussions could be so contentious? One of the things we try to accomplish with ORM tools is to make our data model more meaningful, which makes it easier for developers to use and helps avoid confusion. To this end, how we name entities and attributes is very important. I have naming standards I like and think are best, but I won’t try to push them on you here. The important thing is that you decide on something upfront and get everyone to use it. Actually, this should extend beyond just naming standards and should be inclusive of other standards as well (ie, Boolean vs “Y/N” or 0/1, primitive vs Object, Integer vs Long, etc).

3) Don’t try to map every attribute (and association).

We started out trying to use tools like Dali to map everything on a table quickly (some tables had several hundred columns!). This turned out to be a bad idea. Why? Since we were on a shared, legacy database, there were a ton of fields we didn’t care about and never used. Mapping them led to performance issues and confusion.

4) Let the database do the things it is good at.

We really wanted to have a good, clean data model, and so we avoided at all costs writing extra queries to fetch things pertinent to an object or using stored procedures or functions at all. This was also a mistake - databases are good for stuff other than just holding the data Hibernate creates and reads :) For example, we had one object that had a status associated with it. The status was used all over the app so it had to be performant, but we also didn’t want to have to make a separate query every time we needed it. The problem is, the status was derived based on some calculations that operated on several one-to-many relationships. Pulling back all that data as part of each load of the object would have been way to expensive. Working with one of our database guys (see #1), we found a sql function we could use to get the status very quickly. We mapped this to a status attribute using @Formula and had everything we wanted - it was part of the domain model still, and was very performant. Sometimes little compromises like this can yield big dividends.

5) Break up the database.

When we first started, I wanted to model the whole databse in Hibernate at the beginning. This turns out to have been really impractical for a few reasons:

  • a) It was a huge job and would have consumed weeks of time while the customer would have seen no actual work being done.
  • b) I was unlikely to get it right the first time, meaning developers would have to change it anyway as we got started.

There is a tendency to want to map the whole thing out before starting, but a lot of times you just have to work on it as you go. I did find it useful to break it up into pieces and try to do a whole piece at a time as we went - which really seems to have helped.

6) Watch out for triggers.

Watch out for database triggers for two reasons:

  • a) They can do sneaky things behind the scenes that can lead you to pulling your hair out, wondering what happened.
  • b) Sometimes they do stuff that you need to replicate on the Hibernate side. Several times before we fully learned this lesson, we missed some important things that triggers were doing and almost caused ourselves some real grief.

7) Shy away from tools to auto-generate your model.

Yeah, they can save time (although we found Dali to be terribly buggy at the time we used it), but you end up having to re-do a lot of it anyway. It doesn’t take that long to map them by hand, and it gives you a chance to familiarize yourself with the data more as you do it.

8) Use NamedQueries where you can.

It is easy to just pound a query out in-line, but in a lot of cases it is better to use NamedQueries. This helps to do two things:

  • a) It fosters more re-use, since the named queries are generally located in central places in the code.
  • b) Your queries get validated on startup, making it so errors in the queries (especially down the road when they can get messed up by model or table changes) discovered much more quickly.

It sometimes takes a bit of getting used to (and strong-arming!), but it is worth the effort.

9) Manage Expectations.

This is probably important to keep in mind for any new framework, technology, or even concept. For some reason, people tend to get sold on certain features that simply don’t exist, or are highly exaggerated. Sometimes it is small and understandable (ie, underestimating the actual work required to map stuff in Hibernate), and sometimes I have no idea how they came up with such ideas (ie, that Hibernate can somehow manage schema revisioning). At any rate, finding out what the expectations are and then managing them can be really important. If your team thinks that Hibernate will make DBAs completely obsolete (usually quite false) and fires them all, you will probably have a big problem on your hands.

10) Use rich domain modeling.

One of the sadder things I’ve seen with projects that use Hibernate (and in some cases, I’ve seen it because I’ve done it!) is when the domain objects become no more than simple containers of data. The goal of tools like Hibernate is to let us use data in an object-oriented fashion - simply mapping the data only gets us halfway there. As I’ve made conscious efforts to practice rich domain modeling, I’ve noticed that we reuse a lot more code, our other layers become less cluttered, and our code is more testable and easier to refactor.

Source: SpencerUresk

Wednesday, January 16, 2008

Acegi Security for Spring Framework

Acegi Security provides comprehensive security services for J2EE-based enterprise software applications. There is a particular emphasis on supporting projects built using The Spring Framework, which is the leading J2EE solution for enterprise software development. If you're not using Spring for developing enterprise applications, we warmly encourage you to take a closer look at it. Some familiarity with Spring - and in particular dependency injection principles - will help you get up to speed with Acegi Security more easily.

People use Acegi Security for many reasons, but most are drawn to the project after finding the security features of J2EE's Servlet Specification or EJB Specification lack the depth required for typical enterprise application scenarios. Whilst mentioning these standards, it's important to recognise that they are not portable at a WAR or EAR level. Therefore, if you switch server environments, it is typically a lot of work to reconfigure your application's security in the new target environment. Using Acegi Security overcomes these problems, and also brings you dozens of other useful, entirely customisable security features.

As you probably know, security comprises two major operations. The first is known as "authentication", which is the process of establishing a principal is who they claim to be. A "principal" generally means a user, device or some other system which can perform an action in your application. "Authorization" refers to the process of deciding whether a principal is allowed to perform an action in your application. To arrive at the point where an authorization decision is needed, the identity of the principal has already been established by the authentication process. These concepts are common, and not at all specific to Acegi Security.

At an authentication level, Acegi Security supports a wide range of authentication models. Most of these authentication models are either provided by third parties, or are developed by relevant standards bodies such as the Internet Engineering Task Force. In addition, Acegi Security provides its own set of authentication features. Specifically, Acegi Security currently supports authentication with all of these technologies:

  • HTTP BASIC authentication headers (an IEFT RFC-based standard)

  • HTTP Digest authentication headers (an IEFT RFC-based standard)

  • HTTP X.509 client certificate exchange (an IEFT RFC-based standard)

  • LDAP (a very common approach to cross-platform authentication needs, especially in large environments)

  • Form-based authentication (for simple user interface needs)

  • Computer Associates Siteminder

  • JA-SIG Central Authentication Service (otherwise known as CAS, which is a popular open source single sign on system)

  • Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker (a Spring remoting protocol)

  • Automatic "remember-me" authentication (so you can tick a box to avoid re-authentication for a predetermined period of time)

  • Anonymous authentication (allowing every call to automatically assume a particular security identity)

  • Run-as authentication (which is useful if one call should proceed with a different security identity)

  • Java Authentication and Authorization Service (JAAS)

  • Container integration with JBoss, Jetty, Resin and Tomcat (so you can still use Container Manager Authentication if desired)

  • Your own authentication systems (see below)

Many independent software vendors (ISVs) adopt Acegi Security because of this rich choice of authentication models. Doing so allows them to quickly integrate their solutions with whatever their end clients need, without undertaking a lot of engineering or requiring the client to change their environment. If none of the above authentication mechanisms suit your needs, Acegi Security is an open platform and it is quite simple to write your own authentication mechanism. Many corporate users of Acegi Security need to integrate with "legacy" systems that don't follow any particular security standards, and Acegi Security is happy to "play nicely" with such systems.

Sometimes the mere process of authentication isn't enough. Sometimes you need to also differentiate security based on the way a principal is interacting with your application. For example, you might want to ensure requests only arrive over HTTPS, in order to protect passwords from eavesdropping or end users from man-in-the-middle attacks. Or, you might want to ensure that an actual human being is making the requests and not some robot or other automated process. This is especially helpful to protect password recovery processes from brute force attacks, or simply to make it harder for people to duplicate your application's key content. To help you achieve these goals, Acegi Security fully supports automatic "channel security", together with JCaptcha integration for human user detection.

Irrespective of how authentication was undertaken, Acegi Security provides a deep set of authorization capabilities. There are three main areas of interest in respect of authorization, these being authorizing web requests, authorizing methods can be invoked, and authorizing access to individual domain object instances. To help you understand the differences, consider the authorization capabilities found in the Servlet Specification web pattern security, EJB Container Managed Security and file system security respectively. Acegi Security provides deep capabilities in all of these important areas, which we'll explore later in this reference guide.

Source: Official Reference Guide

Sunday, December 16, 2007

Interview with Gavin King, founder of Hibernate project

Gavin King is the founder of the Hibernate project, a object / relational mapping framework for Java. Currently, he works full time in the project, paid by the JBoss Group. In this interview, Gavin King talks about his entering in the JBoss Group, and the Hibernate Project, what's new in version 3 and the integration of the framework with the new features of Java 5.

1. Please, tell us a little about yourself and your 'real' job.

I live in Melbourne, Australia and I've been working in IT - mostly Java - for about five years now. For the past year my "real" job has been Hibernate. I'm a rare example of a developer who is paid to write open source software. In fact, myself, Christian Bauer, Steve Ebersole and Max Andersen now all work for JBoss, developing Hibernate and providing commercial services. I'm also an active member of the JSR-220 (EJB 3.0) spec committee.

2. In your opinion, Hibernate become so successful?

Hibernate became successful because it solves a very common problem reasonably elegantly, because it is an open source solution, and because it is practical. We took seriously the idea that OO and relational technologies should work smoothly together. And we allowed our project to be driven by user requirements. We also knew that great technology is useless if you can't explain it.

3. What was your main motivation when you created Hibernate?

I wanted to solve an interesting problem, a problem that affected me personally. I was frustrated with working with EJB 2 style entity beans and brittle handwritten persistence layers.

Also, I wanted to win an argument with my then-boss; -)

4. What benefits your decision of joining the JBoss Group may bring to the Hibernate project?

In the long run, it's simply not possible to do a project with the scope of Hibernate in your spare time. By the time I joined JBoss, I was spending so much time responding to questions from users and fixing minor bugs, that there was no time left for sleeping, let alone improving Hibernate. So working for JBoss has made it possible for Hibernate to continue to exist and grow. It also allows us to actually get out there in the field, speaking at conferences and JUGs, working on site with Hibernate users, and participating in the JCP.

From the point of view of Hibernate users, they get not just a better product (due to having four fulltime developers), but also the opportunity to get training and buy 24 / 7 production support. Not everyone cares about these things, but a lot of people do, especially in larger organizations.

5. How do you see other ORM tools like OJB, JDO and Toplink? Do you evaluate or spend time looking at feature of those products? Why people would choose Hibernate?

Um, traditionally, no, we did not pay that much attention - I was much more comfortable being guided by request from users, than by "what the other guys got". However, more recently, we have done some feature-by-feature competitive evaluations of the two leading commercial ORM solutions, just to make sure we didn't miss anything. This has had some influence upon the feature list of Hibernate3, where there are a couple of features that I would describe as being more useful for marketing than for practical purposes.

The Hibernate3 core is the most powerful ORM engine in the world - and it will take a little while for others to catch up. However, we've realized more recently that there is more than just the runtime engine to think about and over the next year there will be a lot more focus upon polishing and in some cases rewriting our development-time toolset. Max is leading that effort. Hibernate will evolve into a suite of products that address the whole problem of writing Java applications which use relational data.

6. How do you see alternatives to relational databases, like XML and OO databases, or Prevayler?

We don't see them; -)

Truly, the relational data model is a wonderful innovation, and it would be an absolute disaster to replace it with flawed persistence technologies like XMLDBs or OODBMS. Fortunately, that simply won't happen, since there is simply no industry interest or momentum behind either.

Technologies like OODBMS sacrifice sound, application technology agnostic data management for sort-term convenience (convenience for one single application, written using one particular programming language). Relational technology essentially completely replaced network or hierarchical database technology, and there were excellent reasons why that happened. We should most certainly not be reviving either of those discredited approaches by slapping on the latest buzzwords (OO, XML, etc) as window dressing.

7. Are there any changes you would like to see in the JDBC API to make Hibernate better and faster?

It would be great to be able to batch together different SQL statements using the JDBC batch update API (at present, you can only batch multiple parameter sets for the same statement).

However, rather than seeing many new features in JDBC, I would be incredibly happy if vendors would simply provide complete, reliable implementations of the features that are already there in JDBC 3. It's actually quite disgraceful how broken the JDBC drivers of certain big-name RDBMS vendors are. They don't seem to care.

8. Is there any plan to make Hibernate compliant with the JDO Spec?

No. Hibernate will provide an implementation of the EJB3 EntityManager defined by the JSR-220 specification. Sun has just announced that the scope of JSR-220 will be expanded to cover operation outside the traditional monolithic J2EE container.

We don't see any future for JDO.

9. Do you foresee the upcoming release of EJB3 reducing the need for Hibernate? Are there any benefits of using both, like in a BMP environment?

EJB 3.0 is a specification. Hibernate will be an implementation of that specification. So you can use both at the same time; -) Alternatively, we intend that some people, who don't care about standards as much, will continue to use Hibernate-specific APIs, especially for functionality that is not yet standardized by JSR-220.

10. Could you tell us about what's new in Hibernate 3, and the benefits these changes will bring to users?

The biggest, most innovative new thing is the support for parameterized "filters". This feature let's you see an object graph that is just a subset of the total data in the database. This is incredibly useful when dealing with temporal, versioned, regional, or permissioned data. In fact, I expect that most business domains have usecases for this feature and that it will soon be considered an indispensable feature of Hibernate.

We have done a huge amount of work on adding greater mapping flexibility, to support more complex (or even broken) relational models. This takes the form of a number of small new features, that are really most significant when taken together. Hibernate is now able to handle just about any crazy thing you are likely to find in a legacy database.

In addition, it is now possible to override any SQL statement that Hibernate generates with your own hand-written SQL. This gives your DBA the freedom to hand-tune the SQL when necessary.

Some further major changes in Hibernate3 were designed to align us more closely with JSR-220.

Finally, we put a huge amount of thought into what small changes we could make that would make Hibernate easier to use for beginners. Hopefully that will reduce the incidence of certain FAQs in the Hibernate forum!

11. How about Metadata in Java 5.0? Do you have plans to support it? It is a real alternative to hbm.xml?

Absolutely! Emmanuel Bernard is working on implementing the EJB 3.0 ORM metadata for Hibernate, and adding Hibernate-specific extensions.

We've seen how many people like to use XDoclet annotations to express their Hibernate mappings, and so I'm quite certain that even more people will feel comfortable using JSR-175 annotations.

In fact, I fully expect that this will be the most common way to use ORM in the future.

12. How can Generics change our Hibernate code?

Not a great deal. Hibernate can already persist templated collections, so you can get a bit more strongly typed in your domain model. Templated collections could even help Hibernate guess the type of an association and reduce the amount of metadata you have to write. However, I don't think this is an especially significant new feature in the context of ORM.

13. Which of Tiger's new features are more likely to be used in the Hibernate code base in the future? Why?

Well, we are a bit stuck. We can't use many of the new features, because Hibernate needs to stay source-level compatible with older JDKs. The annotations stuff is okay, because we can provide it as an add-on package.

Certainly, annotations are the most significant new feature of Java 5, and it's very likely that they will completely change the way we write code.

14. What do you do in your free time?

Retail therapy.

Source: www.javafree.org

Friday, October 5, 2007

Understanding "inverse" mapping attribute

Generality

This page intends to give an internal view and understanding of inverse="true". Please, please, please read the Hibernate reference guide and especially:

  • Mapping a collection
  • Bidirectional Association
  • Parent Child Relationships

and the FAQs (the official ones and the one from the Wiki) before reading this.

Inverse defines which side is responsible of the association maintenance. The side having inverse="false" (default value) has this responsibility (and will create the appropriate SQL query - insert, update or delete). Changes made to the association on the side of the inverse="true" are not persisted in DB.

Inverse attribute is not related in any way to the navigation through relationship. It is related to the way hibernate generate SQL queries to update association data. Association data are:

  • a column in the one-to-many association
  • a row in the association table in a many-to-many association

Monodirectional association is managed by the only side available through navigation. When association is bidirectional, choosing the manager side allow better SQL optimization, this is the recommended behaviour.

one-to-many sample

Let's have a look at a simple one-to-many sample. Setting inverse="true" is recommanded and allow SQL optimization.

Note that <many-to-one> is always inverse="false" (the attribute does not exist).

<class name="net.sf.test.Parent" table="parent">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<set name="children" lazy="true" inverse="true">
<key column="parent_id"/>
<one-to-many class="net.sf.test.Child"/>
</set>
</class>

<class name="net.sf.test.Child" table="child">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<many-to-one name="parent" column="parent_id" not-null="true"/>
</class>

The inverse="true" is set to the one side.

Proper code

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.save(c);
session.flush();

Will do the following SQL queries

Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)

Hibernate insert parent then insert child. Note that my DB has a not null FK constraint on Child(parent_id), inserts work fine because I set <many-to-one not-null="true"

Note that I explicitly save parent and child objets. A better way is to use the cascade="save-update" element. I didn't do it to keep this explanation easier to understand and avoid concepts mismatch.

inverse="true" sample

Insert

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.flush(); //flush to DB
System.out.println("Parent saved");

session.save(c);
System.out.println("Child saved");
session.flush(); //flush to DB

Will do the following SQL queries

Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Parent saved
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into child (parent_id, id) values (?, ?)
Child saved

As you can see the relationship (incarnated by the parent_id column) is set during the child save : this is of the child responsibility. When saving parent, nothing is done on the relationship.

Update

Let's have a look at a relationship update

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);

c = (Child) session.find(
"from Child as child where child.parent = ?",
p, Hibernate.entity(Parent.class)).get(0);

// change parent of child c from p to p2
p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);

Will do the following SQL queries

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children of parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this with set, see FAQ)

Hibernate: update child set parent_id=? where id=?

After a proper Java setting of the Parent child relationship (both side), Hibernate, set parent_id column to the proper value. As you can see, only 1 update is executed.

Now, we'll see inverse="true" in action ;-)

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);

c = (Child) session.find(
"from Child as child where child.parent = ?",
p, Hibernate.entity(Parent.class)).get(0);

c.setParent(p2);

Will do the following SQL queries

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children

Hibernate: update child set parent_id=? where id=?

The relationship is updated because I change it on the child side. Note that the object tree is not consistent with the Database (children collections are not up to date). This is not recommanded.

On the contrary,

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);

c = (Child) session.find(
"from Child as child where child.parent = ?",
p, Hibernate.entity(Parent.class)).get(0);

p.getChildren().remove(c);
p2.getChildren().add(p);

Will do the following SQL queries

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)

Relationship update is not executed because update is only done on the parent side.

inverse="false"

inverse="false" (the default value) is not optimized for bidirectional relationships.

<class name="net.sf.test.Parent" table="parent">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<set name="children" lazy="true" inverse="false">
<key column="parent_id"/>
<one-to-many class="net.sf.test.Child"/>
</set>
</class>

<class name="net.sf.test.Child" table="child">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<many-to-one name="parent" column="parent_id" not-null="true"/>
</class>

The inverse="false" is set to the one side.

insert

Parent p = new Parent();
Child c = new Child();
p.setChildren(new HashSet());
p.getChildren().add(c);
c.setParent(p);

session.save(p);
session.save(c);
session.flush();

Will do the following SQL queries

Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: select SEQ_DEFAULT.nextval from dual
Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)
Hibernate: update child set parent_id=? where id=?

Parent is responsible of the relationship. Hibernate insert parent, insert child then update the relationship (as a request to the parent). Two SQL orders are executed (one insert and one update) instead of one.

Note that I cannot do a flush between session.save(p) and session.save(c) because, parent, which is responsible of the relationship, needs a persistent child to play with.

update

Let's have a look at a relationship update

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);

c = (Child) session.find(
"from Child as child where child.parent = ?",
p, Hibernate.entity(Parent.class)).get(0);

p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);

Will do the following SQL queries

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)

Hibernate: update child set parent_id=? where id=? // child.setParent
Hibernate: update child set parent_id=null where parent_id=? //remove
Hibernate: update child set parent_id=? where id=? // add

As you can see, having set inverse="true" allow the relationship to be managed by the parent side AND the child side. Several updates to the association data are done. This is inefficient considering the inverse="true" equivalent.

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);

c = (Child) session.find(
"from Child as child where child.parent = ?",
p, Hibernate.entity(Parent.class)).get(0);

p2.getChildren().add(c);

Will do the following SQL queries

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
//load childrens of Parent 1 and 2 (can't avoid this see FAQ)

Hibernate: update child set parent_id=? where id=? // add

The relationship is properly set but the object model is in inconsistent state. This is not recommanded.

Conclusion

Using and understanding inverse="true" is essential to optimize your code. Prefer using inverse="true" on bidirectional association. After this tutorial it will be soooo easy ;-)

Source: simoes.org

Tuesday, September 11, 2007

CMP-EJB vs. Hibernate

The J2EE field is agog with excitement about a very popular Open Source technology - Hibernate. This technology being elevated to the status of JCP standard. Feedback from J2EE programmers in industry says that knowledge of Hibernate is mandatory for all J2EE aspirants.

Hibernate is an ORM Object-Relational-Mapping technology. It is an Open-Source and free technology, developed in SourceForge. net. There have been a number of such ORM technologies,in recent past. . TopLink is one such tool, subsequently adopted by Oracle and so proprietary. Hibernate from SourceForge and OJB(Object-Relational-Bridge) from Apache are two well known ORM tools, open-source and free. JDO, also falls within the same category.

Gavin King is the lead for Hibernate and Craig Russell & David Jordan, the lead authors for SUN-sponsored JDO effort. Due to some technical problems, it appears that the majority in JCP favours Hibernate today instead of JDO. At first reading though, the difference is not, all that apparent. The syntax and the approach appear to be almost same, but Hibernate syntax is easier to learn.  

It is interesting to note that Craig Russell works for SUN and Gavin King is now with JBoss. It shows that JCP is a democratic community and SUN is not dictating terms except to protect the language and its enterprise-level users.

EJB-3, is the latest version and it is heavily influenced by Hibernate. Some readers equate EJB-3 with Hibernate. Oracle supports EJB-3 proposals and as it is the main Database company in j2ee world, EJB-3 has bright future. J2EE by its very name is an Enterprise level technology, and as EJB is the essence of such Enterprise applications, because of the built-in container services offered, the significance of the surging interest in Hibernate can be really appreciated only in association with EJB and hence a detour into EJB is inevitable.

EJB has three types. One type is the SESSION BEAN, residing in ENTERPRISE container, which can be thought of as a function-bean, invoked in RMI-IIOP style. Such session-bean, may be either stateless or stateful. The stateless bean working in Enterprise container has an exact counter-part in Microsoft COM+(MTS), but the other types are said to be available in MS platform only through third-party extensions.

ORM tools have been sometimes used along with Session beans. The only problem till recently was that they were proprietory and rather costly. But nowadays, very reliable open-source ORM tools are available, and even Richard Monson Haefel approves this method as a safe and productive alternative to Entity beans.

The other branch, the ENTITY BEAN has been less lucky. EJB-1. 1, EJB-2. 0 and then EJB-2. 1, have meant a number of changes in the specification relating to Entity Beans.
We can say that an Entity bean is an 'Attribute bean' or 'property-bean', with setter and getter methods, invoked in RMI-IIOP style and persisted in Enterprise container. The pattern of defining a typical Javabean is a recurring theme in Java. The same style occurs in BDK, EJB-Entity beans, Struts, JSF and now in Hibernate too. So, it is very important and elegant.

The third branch is Messaging paradigm and MDB. An Enterprise by its very name implies huge number of customers and concurrent transactions, RPC style being like telephone call, could result in 'line-engaged!' problem. If the call involves the called person referring to some records before replying, it leads to line- blocking. But, messaging style, as in email, atleast ensures that the message has been sent. It is evident that dubbing RPC( read 'telephone') as unsuitable, is over-statement. Sometimes, we desire immediate response,too. By the same token, even XML webservice, if it is really serious, should adopt messaging style and it does. MDB (Message-Driven bean) has weathered the storm and is in fact gaining more and more acceptance.

So, why is it that Entity beans alone were found wanting and the specification keeps on changing?
Entity beans are of two types. CMP & BMP.
CMP stands for Container-Managed Persistence and BMP stands for Bean-managed persistence. Theoretically, the EJB specification does not say anything about the method to be adopted in persisting objects for permanent storage and retrieval. It could be simple object serialization. The database may be object-database or Object-relational database or XML. In practice, however, a database has always meant a Relational Database and its SQL.

In CMP, the coder deals with objects, only in memory. He creates new objects, modifies them, deletes them and views them, all in memory. The task of saving these objects in memory ,to the relational database table is done by the container, automatically. The coder does not write any sql-related code for this.

In BMP, the coder has to write the sql to persist the object in memory to the relational database.

CMP in EJB1. 1 was suitable for simple tables, without complex relationships to other tables. CMP avoids all references to the underlying database. So, it is more portable. There is no vendor-lock-in. CMP can persist data to Object- databases also, besides Relational databases.

But, CMP is not always suitable. If the database is some legacy type, which cannot be used with SQL, the database company gives a proprietory code for persistence and such code has to be used in our program to persist data. The facilities given in CMP originally were found to be too elementary and there were complaints.

But, what matters is that CMP makes use of ORM concepts, though the implementation left much to be desired. It did not expose how the EJB vendor implements it. Weblogic, Oracle, IBM WebSphere, SUN , JBoss, each may implement CMP in any way that they deem fit. Except in special circumstances, it will be better to use CMP, not merely because, it makes the code more portable & is easy to write. Much more important reason is that the EJB container can optimize the performace dramatically, if we adopt CMP. So the developer community wanted to adopt CMP but found it unsuitable for really complex jobs.

Even with all these improvements, CMP was found to be less than the ultimate solution. There was no spossibility for Inheritance.  

Though the container services provided by the EJB container are indispensable in a truly large enterprise application, the J2EE camp is almost vertically split into WebTier & EJB-Tier votaries. The WebTier supporters claim that EJB with its steep learning curve and error prone development environment for developers is not really necessary for most applications. And they would like to have an ORM tool, built into the J2EE specification. For afterall, ORM task is not specific to EJB alone. Even Servlets and JSP could use them. In fact, they have been using them, though the J2EE specification was silent about it. ORM tools like OJB, JDO and Hibernate can be used not only in EJB containers but in webcontainer and even in standalone containers. Gavin King makes it a special point in favour of Hibernate. Making such a tool, a J2EE standard, would make development tasks far easier ,to develop either web-tier application or ejb-tier application. saving us from the medley of classpath to required jars.

In a scathing attack on the complexity and questionable performance of EJB Entity beans, Rod Johnson, prophesies, that in a few years time, J2EE will cease to include EJB. Whether, we agree or not, it is worth looking into the criticisms against EJB Entity beans, raised by him. ( 'J2EE Development without EJB' - Wrox/Wiley/DreamTech-2004). For, he is proposing the Spring Framework as an alternative to EJB container and the idea is gaining ground. J2EE developers and students may have to re-orient themselves rather abruptly, to remain relevant to industry.

Source: in.geocities.com/rsramsam

Friday, August 24, 2007

Struts2 + Spring + JUnit

Hopefully this entry serves as some search engine friendly documentation on how one might unit test Struts 2 actions configured using Spring, something I would think many, many people want to do. This used to be done using StrutsTestCase in the Struts 1.x days but Webwork/Struts provides enough flexibility in its architecture to accommodate unit testing fairly easily. I’m not going to go over how the Spring configuration is setup. I’m assuming you have a struts.xml file which has actions configured like this:

<struts>
<package namespace="/site" extends="struts-default">
<action name="deletePerson" class="personAction"
method="deletePerson">
<result name="success">/WEB-INF/pages/person.jsp</result>
</action>
</package>
...
</struts>

You also might have an applicationContext.xml file where you might define your Spring beans like this.

<beans>
<bean id="personAction"
class="com.arsenalist.action.PersonAction"/>
...
</beans>

Then of course you also need to have an action which you want to test which might look something like:

public class PersonAction extend ActionSupport { 

private int id;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String deletePerson() {
....
return SUCCESS;
}
}

Remember than in Struts 2, an action is usually called before and after various other interceptors are invoked. Interceptor configuration is usually specified in the struts.xml file. At this point we need to cover three different methods of how you might want to call your actions.



  1. Specify request parameters which are translated and mapped to the actions domain objects (id in the PersonAction class) and then execute the action while also executing all configured interceptors.
  2. Instead of specifying request parameters, directly specify the values of the domain objects and then execute the action while also executing all configured interceptors.
  3. Finally, you just might want to execute the action and not worry about executing the interceptors. Here you’ll specify the values of the actions domain objects and then execute the action.

Depending on what you’re testing and what scenario you want to reproduce, you should pick the one that suits the case. There’s an example of all three cases below. The best way I find to test all your action classes is to have one base class which sets up the Struts 2 environment and then your action test classes can extend it. Here’s a class that could be used as one of those base classes.


See the comments for a little more detail about whats going on. One point to note is that the class being extended here is junit.framework.TestCase and not org.apache.struts2.StrutsTestCase as one might expect. The reason for this is that StrutsTestCase is not really a well written class and does not provide enough flexibility in how we want the very core Dispatcher object to be created. Also, the interceptor example shown in the Struts documentation does not compile as there seems to have been some sort of API change. It’s been fixed in this example.

public class BaseStrutsTestCase extends TestCase {

private Dispatcher dispatcher;
protected ActionProxy proxy;
protected MockServletContext servletContext;
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;

/**
* Created action class based on namespace and name
*/
protected T createAction(Class clazz, String namespace, String name)
throws Exception {

// create a proxy class which is just a wrapper around the action call.
// The proxy is created by checking the namespace and name against the
// struts.xml configuration
proxy = dispatcher.getContainer().getInstance(ActionProxyFactory.class).
createActionProxy(
namespace, name, null, true, false);

// set to true if you want to process Freemarker or JSP results
proxy.setExecuteResult(false);
// by default, don't pass in any request parameters
proxy.getInvocation().getInvocationContext().
setParameters(new HashMap());

// set the actions context to the one which the proxy is using
ServletActionContext.setContext(
proxy.getInvocation().getInvocationContext());
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
ServletActionContext.setServletContext(servletContext);
return (T) proxy.getAction();
}

protected void setUp() throws Exception {
String[] config = new String[] { "META-INF/applicationContext-aws.xml" };

// Link the servlet context and the Spring context
servletContext = new MockServletContext();
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setServletContext(servletContext);
appContext.setConfigLocations(config);
appContext.refresh();
servletContext.setAttribute(WebApplicationContext.
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appContext);

// Use spring as the object factory for Struts
StrutsSpringObjectFactory ssf = new StrutsSpringObjectFactory(
null, null, servletContext);
ssf.setApplicationContext(appContext);
//ssf.setServletContext(servletContext);
StrutsSpringObjectFactory.setObjectFactory(ssf);

// Dispatcher is the guy that actually handles all requests. Pass in
// an empty Map as the parameters but if you want to change stuff like
// what config files to read, you need to specify them here
// (see Dispatcher's source code)
dispatcher = new Dispatcher(servletContext,
new HashMap());
dispatcher.init();
Dispatcher.setInstance(dispatcher);
}
}

By extending the above class for our action test classes we can easily simulate any of the three scenarios listed above. I’ve added three methods to PersonActionTest which illustrate how to test the above three cases: testInterceptorsBySettingRequestParameters, testInterceptorsBySettingDomainObjects() and testActionAndSkipInterceptors(), respectively.

public class PersonActionTest extends BaseStrutsTestCase { 

/**
* Invoke all interceptors and specify value of the action
* class' domain objects directly.
* @throws Exception Exception
*/
public void testInterceptorsBySettingDomainObjects()
throws Exception {
PersonAction action = createAction(PersonAction.class,
"/site", "deletePerson");
pa.setId(123);
String result = proxy.execute();
assertEquals(result, "success");
}

/**
* Invoke all interceptors and specify value of action class'
* domain objects through request parameters.
* @throws Exception Exception
*/
public void testInterceptorsBySettingRequestParameters()
throws Exception {
createAction(PersonAction.class, "/site", "deletePerson");
Map params = new HashMap();
params.put("id", "123");
proxy.getInvocation().getInvocationContext().setParameters(params);
String result = proxy.execute();
assertEquals(result, "success");
}

/**
* Skip interceptors and specify value of action class'
* domain objects by setting them directly.
* @throws Exception Exception
*/
public void testActionAndSkipInterceptors() throws Exception {
PersonAction action = createAction(PersonAction.class,
"/site", "deletePerson");
action.setId(123);
String result = action.deletePerson();
assertEquals(result, "success");
}
}

The source code for Dispatcher is probably a good thing to look at if you want to configure your actions more specifically. There are options to specify zero-configuration, alternate XML files and others. Ideally the StrutsTestCaseHelper should be doing a lot more than what it does right now (creating a badly configured Dispatcher) and should allow creation of custom dispatchers and object factories. That’s the reason why I’m not using StrutsTestCase since all that does is make a couple calls using StrutsTestCaseHelper.


If you want to test your validation, its pretty easy. Here’s a snippet of code that might do that:

 public void testValidation() throws Exception {
SomeAction action = createAction(SomeAction.class,
"/site", "someAction");
// lets forget to set a required field: action.setId(123);
String result = proxy.invoke();
assertEquals(result, "input");
assertTrue("Must have one field error",
action.getFieldErrors().size() == 1);
}

This example uses Struts 2.0.8 and Spring 2.0.5.

Thursday, August 2, 2007

Familiarity with Stripes

Taken from the official site Stipes.


Stripes is a presentation framework for building web applications using the latest Java technologies. The main driver behind Stripes is that web application development in Java is just too much work! It seems like every existing framework requires gobs of configuration. Struts is pretty feature-light and has some serious architectural issues. Others, like WebWork 2 and Spring-MVC are much better, but still require a lot of configuration, and seem to require you to learn a whole new language just to get started.

Stripes was born out of ongoing frustration with the lack of a high quality, easy to use web framework. Sure, Struts has its good points, but there are a lot of small things that really add up. A lot of small things that you learn to work around, and live with, without realizing how unproductive it's making you.

Up until recently it would have been difficult to create a framework that was better-enough to warrant competing with Struts. And with JSF on the horizon (perpetually?), and other web frameworks in play (WebWork, Tapestry, Wicket) some might question the rationale behind yet another framework. But with Java 1.5 and Servlet 2.4 I think the time has come. The rationale is plain and simple - I wanted a web framework that made it easy, no, fun, to write web applications in Java. The best way to demonstrate is perhaps by a comparison with Struts.

Number of artifacts

One of prime frustrations with Struts is the fact that just to implement a single page/form, I have to write or edit so many files. And I have to keep them in sync, or else things start going horribly wrong. With Struts I have to write JSP, Action, Form, a form-bean stanza in the struts-config.xml, an action stanza in the struts-config.xml, and if I'm going to do it the Struts way, a bunch of forward stanzas. And let's not go into the fact that since this is all stored in one xml file I'm continually facing merge conflicts with team mates. Yes, there are annotations for Struts, but they are just literal translations of what's in the XML file, and they don't feel natural to me.

Compare this with Stripes. I write JSP. I write ActionBean and annotate it with a @UrlBinding to specify the URL it should respond to, and one or more @HandlesEvent annotations to map events to methods. I'm done. All the information about the form and the action is in the same place.

Incremental development

Write a JSP with a Struts <html:form> tag on it and try to preview it in your container before you write your form-bean. Boom! You can't. Exception! Could not find form bean! Now write your form bean. Wait - that's still not good enough. Since everything is hooked together through the action stanza in the XML you better have an action, and edit that too.

Maybe it's just me, but I like to be able to write JSP, see if it looks ok, then go and write the back end components to go with it. It's not brain surgery, and Stripes lets you do it.

Property binding

Struts lets you use nested properties, and that's great. But say you have a property on your Form 'person.address.line1'. Struts will try and set it for you, but if person or address is null, you'll be very sad indeed. So you have to pre-instantiate any objects on which you want to use nested properties. This just seems like too much work.

Stripes will instantiate just about anything for you. Just so long as 'person' and 'address' have no-arg constructors Stripes will build them, join them together, set them on your ActionBean and then set the 'line1' property. It'll even instantiate implementations for any of the Collections interfaces, which leads us to...

Indexed Properties

The JavaBean specification is great for the most part, but it is clearly a child of the Java GUI side of the house. Struts' implementation of indexed properties matches the JavaBean specification. But in a disconnected web model, your Action won't know (and shouldn't have to know) how many indexed properties are coming back. To make it work you end up coding "smart" indexed getter and setter methods that extend lists and insert objects just to keep Struts happy.

Stripes does it all for you. You provide a getter and setter that use a List or Map type, using generics to inform Stripes what type of thing should be in the List or Map. Stripes will instantiate the List or Map for you if necessary, extend it when needed, manufacture new objects and put them in the list and, you know, set properties of objects in the list.

Validation

Other frameworks take shots at Struts for Validation. It's just fundamentally in the wrong place. Forget that the Struts Validator requires yet another XML file with yet more information about your Form that has to be kept in sync. Validation in Struts is divorced from Type Conversion. This is just plain wrong. Why validate that something is a well formed date, then spend a whole bunch more effort converting it to one? Well Struts almost does that. It expends a lot of effort validating it, tosses it all away and then performs some pretty weak type conversion. It's inefficient, and a pain to use. Which is why most of the Struts projects I've seen steer clear of Struts Validator.

In Stripes validation is tied closely to type conversion. A number of commonly used validations can be applied pre-conversion using a simple annotation. This includes things like required field checks, length checks, regex checking etc. Then type conversion happens, or tries to. If it fails, type converters produce validation errors that can be displayed to the user. So you can put your effort into creating good type converters (if the built in ones don't cover your needs) and be done.

Null mean Null (or does it)

Ask yourself this. You have an int property in your form bean and the user doesn't enter a value in a text box. What should your property be set to? Zero sounds like a sensible default right? Now, what if you have an Integer property? If the user doesn't submit anything I'd say that means null wouldn't you? Apparently Struts thinks it means zero again. And if there are validation errors, the form will even repopulate with the value zero! The only way to get around this is to declare your number properties as Strings and do your own conversion (which is a lot of effort if your dealing with multiple Locales).

Stripes takes the position that the HTML specification is a little inconsistent, and does what it can to make it more consistent for application developers. As a result, empty strings are treated the same as if the field didn't get submitted. The user didn't enter a value, so why should your ActionBean receive one and have to figure out what it means?

Formatting

The Struts FAQ says this (among other things) in answer to why the Struts tags provide so little formatting:

Great. JSTL doesn't have form tags, so while JSTL is great, it doesn't really help here. JSF and Struts don't mix so well even now, and that's a reason to leave people without formatting for years? And the last is just a cop-out. I want to be able to format data in the right way for each page. And it needs to be localizable etc.

Stripes provides high quality formatting support using the same java.text APIs that the JSTL formatting is built on. It's as similar to JSTL formatting as it can be, while being constrained to living on form tags (i.e. we can't have a separate tag for formatting a date vs. a number and so on).

Multi-Event Actions

If you want to have a form that submits multiple different events in Struts you have to either extend the DispatchAction or write your own support for it. And since the DispatchAction requires all buttons to have the same name, and uses the value to determine the method to invoke, it's a huge pain if you're using localized or even just externalized values for your buttons.

Stripes uses the name of the button itself, and has built in support for multi-event Actions. You can localize to your heart's content, and Stripes will detect which button was pressed and invoke the right method for you.

JSP / View Helpers

Struts doesn't really provide a good pattern for providing dynamic data to JSPs that are not the result of another Action. This leaves you with the options of writing a pre-action for the page or doing something outside of Struts. Then, what if another Action wants to forward to your page after it's completed processing. Do you chain the actions? Do you make the second action meet the dependencies of the page also?

Stripes has a neat way of handling this. A custom tag allows the use of ActionBeans as view helpers. It works similarly to the jsp:useBean tag in that if the ActionBean already exists it just gives you a reference to it. If it doesn't exist, the tag will bring it into existence, bind data out of the request on to it, and get it ready for use.

"HTML" Tags

Maybe it's just me who could never get used to it, but why do the Struts form input tags use 'property' instead of 'name'? And why is it 'styleClass' instead of 'class'? It also makes it hard to change a tag back and forth from a plain HTML tag to a Struts tag.

Stripes takes pains to make all the form input tags as close to (if not identical to) their HTML counterparts as possible.


Who had experience with Stripes? Does it make sense to use it? Your comments are welcome.

Tuesday, July 31, 2007

Some Words About JUnit Testing

Testing is not a very interesting thing sometimes. Some developers use standard output or debugger in order to test their classes. But there is another way...
In this article you’ll find the introduction into JUnit library. JUnit framework makes the process of test-writing much easier.
To show you the power of JUnit let me create the small class in Java and write some test cases for it. Consider the following code:
public class MathFunc {
private int variable;

public MathFunc() {
variable = 0;
}
public MathFunc(int var) {
variable = var;
}

public int getVariable() {
return variable;
}
public void setVariable(int variable) {
this.variable = variable;
}

public long factorial() {
long result = 1;
if (variable > 1) {
for (int i=1; i<=variable; i++)
result = result*i;
}
return result;
}

public long plus(int var) {
long result = variable + var;
return result;
}
}

At first, you have to create the class which extends junit.framework.TestCase. The proper constructor also must be defined. This constructor has to provide String parameter to the parent class’ constructor. At last, you have to write as many test methods as you want:

public class TestClass extends TestCase {
public TestClass(String testName) {
super(testName);
}

public void testFactorialNull() {
MathFunc math = new MathFunc();
assertTrue(math.factorial() == 1);
}

public void testFactorialPositive() {
MathFunc math = new MathFunc(5);
assertTrue(math.factorial() == 120);
}

public void testPlus() {
MathFunc math = new MathFunc(45);
assertTrue(math.plus(123) == 168);
}
}

Method assertTrue checks the parameter’s value for “true” result. So, we can compare the output value of some method to the expected value. Methods assertEquals, assertFalse, assertNull, assertNotNull, assertSame are also useful ones.
In order to combine few tests together you can use TestSuite class. Just add some tests with addTest method. Finally, you have to use TestRunner to execute tests. I prefer to use junit.textui.TestRunner (there are also graphical implementations - junit.swingui.TestRunner, junit.awtui.TestRunner). The main method of the test class looks like this:

public static void main(String[] args) {
TestRunner runner = new TestRunner();
TestSuite suite = new TestSuite();
suite.addTest(new TestClass(“testFactorialNull”));
suite.addTest(new TestClass(“testFactorialPositive”));
suite.addTest(new TestClass(“testPlus”));
runner.doRun(suite);
}

Output after execution:

Time: 0,02
OK (3 tests)

For the testing of more complex classes you can use methods setUp and tearDown. The first method initializes several instances of the specified class in order to use them in several test cases. The second method serves to release unused resources after tests have passed.
I hope this article will help you a little.



Technorati Tags: , , ,

Friday, July 27, 2007

Using OSF Layers in Your JWeb Application

This article will discuss one strategy for combining frameworks using three popular open source frameworks. For the presentation layer we will use Struts; for our business layer we will use Spring; and for our persistence layer we will use Hibernate. You should be able to substitute any one of these frameworks in your application and get the same effect. Figure 1 shows what this looks like from a high level when the frameworks are combined.





Figure 1. Overview of framework architecture with Struts, Spring, and Hibernate.

Application Layer

Most non-trivial web applications can be divided into at least four layers of responsibility. These layers are the presentation, persistence, business, and domain model layers. Each layer has a distinct responsibility in the application and should not mix functionality with other layers. Each application layer should be isolated from other layers but allow an interface for communication between them. Let's start by inspecting each of these layers and discuss what these layers should provide and what they should not provide.

At one end of a typical web application is the presentation layer. Many Java developers understand what Struts provides. However, too often, coupled code such as business logic is placed into an org.apache.struts.Action. So, let's agree on what a framework like Struts should provide. Here is what Struts is responsible for:

- Managing requests and responses for a user.

- Providing a controller to delegate calls to business logic and other upstream processes.

- Handling exceptions from other tiers that throw exceptions to a Struts Action.

- Assembling a model that can be presented in a view.

- Performing UI validation.

Here are some items that are often coded using Struts but should not be associated with the presentation layer:

- Direct communication with the database, such as JDBC calls.

- Business logic and validation related to your application.

- Transaction management.

Introducing this type of code in the presentation layer leads to type coupling and cumbersome maintenance.

The Persistence Layer

At the other end of a typical web application is the persistence layer. This is usually where things get out of control fast. Developers underestimate the challenges in building their own persistence frameworks. A custom, in-house persistence layer not only requires a great amount of development time, but also often lacks functionality and becomes unmanageable. There are several open source object-to-relational mapping (ORM) frameworks that solve much of this problem. In particular, the Hibernate framework allows object-to-relational persistence and query service for Java. Hibernate has a medium learning curve for Java developers who are already familiar with SQL and the JDBC API. Hibernate persistent objects are based on plain-old Java objects and Java collections. Furthermore, using Hibernate does not interfere with your IDE. The following list contains the type of code that you would write inside a persistence framework:

- Querying relational information into objects. Hibernate does this through an OO query language called HQL, or by using an expressive criteria API. HQL is very similar to SQL except you use objects instead of tables and fields instead of columns. There are some new specific HQL language elements to learn; however, they are easy to understand and well documented. HQL is a natural language to use for querying objects that require a small learning curve.

- Saving, updating, and deleting information stored in a database.

- Advanced object-to-relational mapping frameworks like Hibernate have support for most major SQL databases, and they support parent/child relationships, transactions, inheritance, and polymorphism.

Here are some items that should be avoided in the persistence layer:

- Business logic should be in a higher layer of your application. Only data access operations should be permitted.

- You should not have persistence logic coupled with your presentation logic. Avoid logic in presentation components such as JSPs or servlet-based classes that communicate with data access directly. By isolating persistence logic into its own layer, the application becomes flexible to change without affecting code in other layers. For example, Hibernate could be replaced with another persistence framework or API without modification to the code in any other layer.

The Business Layer

The middle component of a typical web application is the business or service layer. This service layer is often the most ignored layer from a coding perspective. It is not uncommon to find this type of code scattered around in the UI layer or in the persistence layer. This is not the correct place because it leads to tightly coupled applications and code that can be hard to maintain over time. Fortunately, several frameworks exist that address these issues. Two of the most popular frameworks in this space are Spring and PicoContainer. These are referred to as microcontainers that have a very small footprint and determine how you wire your objects together. Both of these frameworks work on a simple concept of dependency injection (also known as inversion of control). This article will focus on Spring's use of setter injection through bean properties for named configuration parameters. Spring also allows a sophisticated form of constructor injection as an alternative to setter injection as well. The objects are wired together by a simple XML file that contains references to objects such as the transaction management handler, object factories, service objects that contain business logic, and data access objects (DAO).

The way Spring uses these concepts will be made clearer with examples later in this article. The business layer should be responsible for the following:

- Handling application business logic and business validation

- Managing transactions

- Allowing interfaces for interaction with other layers

- Managing dependencies between business level objects

- Adding flexibility between the presentation and the persistence layer so they do not directly communicate with each other

- Exposing a context to the business layer from the presentation layer to obtain business services

- Managing implementations from the business logic to the persistence layer

The Domain Model Layer

Finally, since we are addressing non-trivial, web-based applications we need a set of objects that can move between the different layers. The domain object layer consists of objects that represent real-world business objects such as an Order, OrderLineItem, Product, and so on. This layer allows developers to stop building and maintaining unnecessary data transfer objects, or DTOs, to match their domain objects. For example, Hibernate allows you to read database information into an object graph of domain objects, so that you can present it to your UI layer in a disconnected manner. Those objects can be updated and sent back across to the persistence layer and updated within the database. Furthermore, you do not have to transform objects into DTOs, which can get lost in translation as they are moved between different application layers. This model allows Java developers to work with objects naturally in an OO fashion without additional coding.

First, we will create our domain objects since they will interoperate with each layer. These objects will allow us to define what should be persisted, what business logic should be provided, and what type of presentation interface should be designed. Next, we will configure the persistence layer and define object-to-relational mappings with Hibernate for our domain objects. Then we will define and configure our business objects. After we have these components we can discuss wiring these layers using Spring. Finally, we will provide a presentation layer that knows how to communicate with the business service layer and knows how to handle exceptions that arise from other layers.

Conclusion

This article covers a lot of ground in terms of technology and architecture. The main concept to take away is how to better separate your application, user interface, persistence logic, and any other application layer you require. Doing this will decouple your code, allow new code components to be added, and make your application more maintainable in the future. The technologies covered here address specific problems well. However, by using this type of architecture you can replace application layers with other technologies.

Tuesday, July 24, 2007

Data Validation in Hibernate

While it's important to build data validation into as many layers of a Web application as possible, it's traditionally been very time-consuming to do so, leading many developers to just skip it - which can lead to a host of problems down the road. But with the introduction of annotations in the latest version of the Java™ platform, validation got a lot easier. In this article, author shows you how to use the Validator component of Hibernate Annotations to build and maintain validation logic easily in your Web apps.

Java SE 5 brought many needed enhancements to the Java language, none with more potential than annotations. With annotations, you finally have a standard, first-class metadata framework for your Java classes. Hibernate users have been manually writing *.hbm.xml files for years (or using XDoclet to automate this task). If you manually create XML files, you must update two files (the class definition and the XML mapping document) for each persistent property needed. Using HibernateDoclet simplifies this (see Listing 1 for an example) but requires you to verify that your version of HibernateDoclet supports the version of Hibernate you wish to use. The doclet information is also unavailable at run time, as it is coded into Javadoc-style comments. Hibernate Annotations, illustrated in Listing 2, improve on these alternatives by providing a standard, concise manner of mapping classes with the added benefit of run-time availability.
Listing 1. Hibernate mapping code using HibernateDoclet

/** 
* @hibernate.property column="NAME" length="60" not-null="true"
*/
public String getName() {
return this.name;
}

/**
* @hibernate.many-to-one column="AGENT_ID" not-null="true" cascade="none"
* outer-join="false" lazy="true"
*/
public Agent getAgent() {
return agent;
}

/**
* @hibernate.set lazy="true" inverse="true" cascade="all" table="DEPARTMENT"
* @hibernate.collection-one-to-many class="com.triview.model.Department"
* @hibernate.collection-key column="DEPARTMENT_ID" not-null="true"
*/
public List getDepartment() {
return department;
}

If you use HibernateDoclet, you won't be able to catch mistakes until you generate the XML files or until run time. With annotations, you can detect many errors at compile time, or, if you're using a good IDE, during editing. When creating an application from scratch, you can take advantage of the hbm2ddl utility to generate the DDL for your database from the hbm.xml files. Important information -- that the name property must have a maximum length of 60 characters, say, or that the DDL should add a not null constraint -- is added to the DDL from the HibernateDoclet entries. When you use annotations, you can generate the DDL automatically in a similar manner.

While both code mapping options are serviceable, annotations offer some clear advantages. With annotations, you can use constants to specify lengths or other values. You have a much faster build cycle without the need to generate XML files. The biggest advantage is that you can access useful information such as a not null annotation or length at run time. In addition to the annotations illustrated in Listing 2, you can specify validation constraints. Some of the included constraints available are:

  • @Max(value = 100)
  • @Min(value = 0)
  • @Past
  • @Future
  • @Email

When appropriate, these annotations will cause check constraints to be generated with the DDL. (Obviously, @Future is not an appropriate case.) You can also create custom constraint annotations as needed.

Validation and application layers

Writing validation code can be a tedious, time-consuming process. Often, lead developers will forgo addressing validation in a given layer to save time, but it is debatable whether or not the drawbacks of cutting corners in this area are offset by the time savings. If the time investment needed to create and maintain validation across all application layers can be greatly reduced, the debate swings toward having validation in more layers. Suppose you have an application that lets a user create an account with a username, password, and credit card number. The application components into which you would ideally like to incorporate validation are as follows:

  • View: Validation through JavaScript is desirable to avoid server round trips, providing a better user experience. Users can disable JavaScript, so while this level of validation is good to have, it's not reliable. Simple validations of required fields are a must.
  • Controller: Validation must be processed in the server-side logic. Code at this layer can handle validations in a manner appropriate for the specific use case. For example, when adding a new user, the controller may check to see if the specified username already exists before proceeding.
  • Service: Relatively complex business logic validation is often best placed into the service layer. For example, once you have a credit card object that appears to be valid, you should verify the card information with your credit card processing service.
  • DAO: By the time data reaches this layer, it really should be valid. Even so, it would be beneficial to perform a quick check to make sure that required fields are not null and that values fall into specified ranges or adhere to specified formats -- for instance, an e-mail address field should contain a valid e-mail address. It's better to catch a problem here than to cause avoidable SQLExceptions.
  • DBMS: This is a common place to find validation being ignored. Even if the application you're building is the only client of the database today, other clients may be added in the future. If the application has bugs (and most do), invalid data may reach the database. In this event, if you are lucky, you will find the invalid data and need to figure out if and how it can be cleaned up.
  • Model: An ideal place for validations that do not require access to outside services or knowledge of the persistent data. For example, your business logic may dictate that users provide at least one form of contact information, either a phone number or an e-mail address; you can use model layer validation to make sure that they do.

A typical approach to validation is to use Commons Validator for simple validations and write additional validations in the controller. Commons Validator has the benefit of generating JavaScript to process validations in the view. But Commons Validator does have its drawbacks: it can only handle simple validations and it stores the validation definition in an XML file. Commons Validator was designed to be used with Struts and does not provide an easy way to reuse the validation declarations across application layers.

When planning your validation strategy, choosing to simply handle errors as they occur is not sufficient. A good design also aims to prevent errors by generating a friendly user interface. Taking a proactive approach to validation can greatly enhance a user's perception of an application. Unfortunately, Commons Validator fails to offer support for this. Suppose you want your HTML to set the maxlength attribute of text fields to match the validation or place a percent sign (%) after text fields meant to collect percentage values. Typically, that information is hard-coded into HTML documents. If you decide to change your name property to support 75 characters instead of 60, in how many places will you need to make changes? In many applications, you will need to:

  • Update the DDL to increase the database column length (via HibernateDoclet, hbm.xml, or Hibernate Annotations).
  • Update the Commons Validator XML file to increase the max to 75.
  • Update all HTML forms related to this field to change the maxlength attribute.

A better approach is to use Hibernate Validator. Validation definitions are added to the model layer through annotations, with support for processing the validations included. If you choose to leverage all of Hibernate, the validator helps provide validation in the DAO and DBMS layers as well. In the code samples that follow, you will take this a step further by using reflection and JSP 2.0 tag files, leveraging the annotations to dynamically generate code for the view layer. This will remove the practice of hard-coding business logic in the view.

Hibernate DAO implementations use the validation annotations as well, if you want them to. All you need to do is specify Hibernate event-based validation in the hibernate.cfg.xml file.

Saturday, July 21, 2007

Introducing Hibernate

Hibernate is a full-featured, open source OR mapping framework for the Java platform. In many ways Hibernate is similar to EJB CMP CMR (container-managed-persistence/container-managed-relationships), and JDO (Java Data Objects). Unlike JDO, Hibernate focuses entirely on OR mapping for relational databases, and includes more features than most commercial products. Most EJB CMP CMR solutions use code generation to implement persistence code, while JDO uses bytecode decoration. Conversely, Hibernate uses reflection and runtime bytecode generation, making it nearly transparent to end users. (Earlier implementations of Hibernate used reflection only, which aids in debugging, and current versions retain this option.)       

Porting Hibernate-based apps

If your application must run on many RDBMS systems, Hibernate-based applications port almost effortlessly from IBM DB2, MySQL, PostgreSQL, Sybase, Oracle, HypersonicSQL, and many more. I even recently worked on an application port from MySQL to Firebird, which isn't all that well supported by Hibernate, and the port was effortless. See Resources for a case study of a switch between Postgres and MySQL.

Hibernate allows you to model inheritance (several ways); association (one-to-one or one-to-many, containment, and aggregation); and composition. I'll cover several examples of each type of relationship in this article.

Hibernate provides a query language called Hibernate Query Language (HQL), which is similar to JDO's JDOQL and EJB's EJB QL; although it is closer to the former. But Hibernate doesn't stop there: it also allows you to perform direct SQL queries and/or use object criteria to compose criteria easily at runtime. I'll use only HQL in the examples for this article.

Unlike EJB CMP CMR and like JDO, Hibernate can work inside of or outside of a J2EE container, which is a boon for those of us doing TDD and agile development.

Introducing Spring

The first time AOP expert Nicholas Lesiecki explained AOP to me, I didn't understand a word he was saying; and I felt much the same the first time I considered the possibility of using IOC containers. The conceptual basis of each technology alone is a lot to digest, and the myriad of new acronyms applied to each one doesn't help -- particularly given that many of them are variations on stuff we already use.

Like many technologies, these two are much easier to understand in practice than in theory. Having done my own research on AOP and IOC container implementations (namely, XWork, PicoContainer, and Spring), I've found that these technologies help me gain functionality without adding code-based dependencies on multiple frameworks. They'll both be a part of my development projects going forward.

In a nutshell, AOP allows developers to create non-behavioral concerns, called crosscutting concerns, and insert them in their application code. With AOP, common services like logging, persistence, transactions, and the like can be factored into aspects and applied to domain objects without complicating the object model of the domain objects. 

Developing with a new framework without unit testing is like walking on a new trapeze wire without a net: sure you could do it, but you're going to bleed. I prefer to develop with a net, and for me that net is TDD. Before DbUnit came along, testing code that was dependent on a database could be a little tough. DbUnit is an extension of JUnit that provides a framework for unit tests dependent on a database. I used DbUnit to write the test code for the example classes in this article. While not present in the article, the DbUnit code is part of the article source code (see Resources). Or for an introduction to DbUnit, see "Control your test-environment with DbUnit and Anthill" (developerWorks, April 2004) by Philippe Girolami.

IOC allows me to create an application context where I can construct objects, and then pass to those objects their collaborating objects. As the word inversion implies, IOC is like JNDI turned inside out. Instead of using a tangle of abstract factories, service locators, singletons, and straight construction, each object is constructed with its collaborating objects. Thus, the container manages the collaborators.

Spring is both an AOP framework and an IOC container. I believe it was Grady Booch who said the great thing about objects is that they can be replaced; and the great thing about Spring is that it helps you replace them. With Spring, you simply inject dependencies (collaborating objects) using JavaBeans properties and configuration files. Then it's easy enough to switch out collaborating objects with a similar interface when you need to.

Spring provides an excellent on-ramp to both IOC containers and AOP. As such, you don't need to be familiar with AOP in order to follow the examples in this article. All you need to know is that you'll be using AOP to declaratively add transactional support to your example application, much the same way that you would use EJB technology. See Resource to learn more about Spring.