Friday, 29 February 2008

Hibernate is Lazy : The LazyInitializationException scenario

While Lazy Instantiation is an important feature and does improve performance in J2EE applications, it can be a bit of a headache if not correctly used or should I say implemented.

Consider a J2EE scenario where you might have a one-to-many parent-child relationship defined between two classes.In the scenario, data retrieval is handled by the DAO layer. In it a DAO retrieves a dataset and passes it to a view. The view is controller by a servlet and rendered by a JSP. The JSP attempts to print out the parent's name and voila, you have a LazyInitializationException.

As section 19.1.4 of the Hibernate documentation states " A LazyInitializationException will be thrown by Hibernate if an uninitialized collection or proxy is accessed outside of the scope of the Session, ie. when the entity owning the collection or having the reference to the proxy is in the detached state."

Two obvious (and suggested) counter strategies would be
1. Keep the session open until all objects that are required have been initialised.

In my opinion, this is not a good approach as you are liable to forget closing a session and will end up nesting transactions. Something which the J2EE container does not like.
(Yes, Yes..you can use a servlet filter to ensure that you do close the session but you can have performance degradation with requests being parsed by the filter. In addition to this, you will also need to have a robust exception handling mechanism in place to ensure that sessions do get closed when exceptions occur.

2. Prepare all uninitialized collections in the business layer before they get passed to the view.
I feel that this is a better and a much more organised strategy as you can initialise the objects and their associated objects in the same DAO call (and the same session).
Of course you need to be sure that you are going to really use these objects otherwise you will end up with a lot of unused objects on the heap and a sluggish application to boot.

While there are several strategies to counter the LazyInitializationException scenario, To fully understand the solution, one should have a good grasp of the Fetching strategies employed by Hibernate as they are the key to the problem and to the solution.

Tuesday, 11 December 2007

India's upcoming tour of DownUnder 2007

Later this month, the Twenty20 champions will be traveling DownUnder to play the mighty Australians on their home-turf.

The tour will perhaps be the last visit for a number of Indian stalwarts who will be looking to leave a lasting impression. The team is a good blend of youth and experience and with a new coach (in Gary Kirsten) looking on as a consultant (He joins the team as a coach officially after the tour), the guys will be looking to create the right impression. On the other hand, the Australian team will be without their long time warriors, Warne, Martyn, Langer and McGrath but it hardly seemed to make much of a difference while clinically destroying the Sri Lankans on their recent tour of two test matches.

Can India do any better?? Only time will tell.

We (in DownUnder) are in for an an exciting time this summer and it never really looked better.

Thursday, 11 October 2007

Configuring Middlgen to generate Hibernate files from MySQL

Following on from my earlier post , I'll now show you how to configure Middlegen and talk to your MySQL database. You will need to have ANT installed in order to run the ANT tasks that I customized to build the hbms and the Java objects.

I performed the Middlegen connection tasks using ANT version 1.7, MySQL version 5.0.24-community-nt and MySQL client version 5.1.11 and Middlegen 2.1

In your build.xml, set the following Middlegen property
<property name="Middlegen.home" value="${lib}/Middlegen"/>

The lib directory has 2 main jars, Middlegen-2.1.jar and Middlegen-hibernate-plugin-2.1.jar.

Both these jars are required to
(1) Run Middlegen and connect to MySQL
(2) Create Hbm mappings from the database and convert the hbm mappings into Java objects.

Firstly create a directory where you are going to store your generated files using the Middlegen-init ANT task.

<target name="Middlegen-init"
description="Initializes everything, creates directories, etc.">
<mkdir dir="${gen.java}" />
</target>


The next task is Middlegen which talks to the database but inorder to do so, it needs to know where the database is located, what driver file to use and what connection properties to use, so make the task know all this by defining the following properties in the build.xml

<property name="database.initialise.script" value="${main.resources}/database/ddl/FULL_DROP_INITIALISE.sql"/>
<property name="database.driver.file" value="${lib}/mysql-connector-java-3.0.14-production-bin.jar"/>
<property name="database.driver.classpath" value="${database.driver.file}"/>
<property name="database.driver" value="org.gjt.mm.mysql.Driver"/>
<property name="database.url" value="jdbc:mysql://localhost/testdatabase"/>
<property name="database.userid" value="root"/>
<property name="database.password" value="root"/>
<property name="database.schema" value="testdatabase"/>
<property name="database.catalog" value=""/>

You'll notice that the properties talk about a 'database.driver' which should be on the 'database.driver.classpath'.
This driver can be found within the mysql-connector-java-3.0.14-production-bin.jar so it should be downloaded and made available to the application.

Now, write the following ANT tasks in your build.xml

<!-- Middlegen related Tasks --->
<!-- =================================================================== -->
<!-- Run Middlegen -->
<!-- =================================================================== -->
<target
name="Middlegen"
description="Run Middlegen"
unless="Middlegen.skip"
depends="Middlegen-init"
>

<taskdef
name="Middlegen"
classname="Middlegen.MiddlegenTask"
classpathref="lib.class.path"
/>

<Middlegen
appname="${name}"
prefsdir="${Middlegen.prefs}"
gui="${gui}"
databaseurl="${database.url}"
initialContextFactory="${java.naming.factory.initial}"
providerURL="${java.naming.provider.url}"
datasourceJNDIName="${datasource.jndi.name}"
driver="${database.driver}"
username="${database.userid}"
password="${database.password}"
schema="${database.schema}"
catalog="${database.catalog}"
includeViews="false"
>

<!-- Sets up the hibernate plug-in for Middlegen -->

<hibernate
destination="${gen.java}"
package="${name}.persistence"
genXDocletTags="true"
javaTypeMapper="Middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>
</Middlegen>

</target>

<!-- =================================================================== -->
<!-- Run hbm2java -->
<!-- =================================================================== -->
<target name="hbm2java" description="Generate .hbm and then .java from .hbm files.">
<taskdef
name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask"
classpathref="lib.class.path"
/>
<hbm2java output="${gen.java}">
<fileset dir="${gen.java}">
<include name="**/*.hbm.xml"/>
</fileset>
</hbm2java>
</target>
<!-- End of Middlegen related Tasks --->

To create the HBM mappings for ALL tables in your 'testdatabase' schema:
Run the 'Middlegen' task which will
(1) create a directory to store the generated files
(2) connect to your MySQL database based on the params supplied and generate the hbm mapping files.

You can customize the hbm files according to your requirements, now run the hbm2java mapper task on these files by invoking the target 'hbm2java'. The java files will be generated and stored in the same directory alongside their respective hbms.

Well, that's all there is to it.

Middlegen is a very useful tool as it takes away the pain of manually creating these files and helps you setup your Hibernate environment within a couple of hours.

For more info on the subject refer to the Middlegen homepage.

Sunday, 7 October 2007

Securing your Web-App:The WEB-INF story, FORMS, JBOSS and JAAS

Securing your web application is a multi-step process and requires careful planning.If you are not careful, you can end up leaving the application vulnerable to hacker attacks or lock yourself in and throw away the key which is what happened to me recently.

I was securing a web application that was to be deployed on JBOSS. Taking the first step in security, I placed all my web-resources in my WEB-INF. Good move.No. Bad move.Yes.
It was a good move in the sense that by placing every resource under WEB-INF, I was securing them from being accessed externally, i.e no one could get to them unless they pretended to be a servlet call. I had locked myself in and thrown away the key. Hang-on what if I got to a resource as an Authenticated subject. Yeah, you could. I redeployed the application and pointed it to my login.jsp that was sitting in the WEB-INF under a pages directory. It worked fine except for one thing. My login.jsp requested a style-sheet and try as much as I could, I could not get it to load. That was when the lightening struck.

The call to load the stylesheet was a new request being made before the authentication process had completed and of course the WEB-INF would bar the request. I moved my jsp pages, stylesheets, images and scripts out of WEB-INF and secured them using security tags defined in the web descriptors.

Securing web-resources placed outside the WEB-INF folder is carried out using the web.xml and your server specific descriptor. Access to web-resources is granted based on user-authentication and authorization policies. These policies are user role base.

To secure your web-resource folders in JBOSS, follow this tutorial or follow this link in the Sun Forum. Both tutorials are very succinctly written and bring out the salient features required to configure and set up security in JBOSS. If you are after WebLogic, then this guide will be useful. It also describes FORM based authentication in sufficient detail which is what most web-applications are based on.

Well, there you go! Enjoy locking yourself in but don't throw away the key...yet!!