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

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, 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.