Hibernate inheritance ClassCastException (Part 2)

In the last post, I was discussing about the solutions to the ClassCastException caused by typecasting the child entity to the parent entity. Using the proxy interfaces did solve the issue but not a better solution. The second solution Proxy Visitor Pattern is being discussed in the hibernate user forums.

Before discussing the Proxy Visitor Pattern, let me explain the other possible solution (but again not a great one). The main issue that we are stuck with is we can’t cast the child class to the proxy object as the proxy doesn’t extend the child class but the actual child entity is hidden within the proxy object. Fortunately hibernate does allow us to retrieve the actual entity being held by the proxy object.

Seller seller = (Seller)((HibernateProxy)proxyEntity).getHibernateLazyInitializer().getImplementation();

If you would like to hide the hibernate usage in your application layer, you can always move this to the DAO layer. But just imagine, whenever you are going to refer to the polymorphic entity, you have to get the implementation and work with it.

Now back to the Proxy Visitor Pattern, the example being discussed there is in reference to a collection of polymorphic entities. I have to admit that it did took some time to understand how it would work. I had a similar kind of requirement, but its not something to deal with a collection but rather a single entity. In fact the visitor pattern looks powerful when dealing with collections but not the case with a single entity (at least from what I have understood :-) ). In my requirement, I had to deal with the payment account chosen by the buyer for an order.

public class PaymentAccount {

	public String getName(){};

	public void setName(String name){};

	public String getPaymentType(){};

	public void setPaymentType(String type){};
}

public class OnlinePaymentAccount extends PaymentAccount {

	public String getServiceUrl(){};
}

public class OfflinePaymentAccount extends PaymentAccount {
	
	public boolean isMoneyOrderAllowed(){};

	public void setMoneyOrderAllowed(boolean allowed){};
}

public class XyzPaymentAccount extends OnlinePaymentAccount {
	
	public String getMerchantApiToken(){};

	public void setMerchantApiToken(String token){};

	public String getMerchantId(){};

	public void setMerchantId(String id){};
}

public class AbcPaymentAccount extends OnlinePaymentAccount {
	
	public String getUserName(){};

	public void setUserName(String userName){};

	public String getPassword(){};

	public void setPassword(){};
}

So say I do a find by id for this payment entity and assume the row corresponds to AbcPaymentAccount, how would I get the username/Password ??? If I were to follow what’s being explained in the proxy visitor pattern, I should have a Visitor interface being used by the PaymentAccount class as below,

public interface PaymentAccountVisitor {

	public void visit(OfflinePaymentAccount account);

	public void visit(XyzPaymentAccount account);

	public void visit(AbcPaymentAccount account);
}

public class PaymentAccount {

	public String getName(){};

	public void setName(String name){};

	public String getPaymentType(){};

	public void setPaymentType(String type){};

	// to accept the visitor
	public void accept(PaymentAccountVisitor visitor) {
		visitor.visit(this);
	}
}

So in my application I have to do some thing like this to get the username/password,
PaymentAccount account = order.getPaymentAccount();
if(account.getPaymentType().equals("Abc")) {
	String username = null;
	String password = null;
	PaymentAccountVisitor visitor = new PaymentAccountVisitor() {
		
		public void visit(OfflinePaymentAccount account) {
			// do nothing
		}

		public void visit(XyzPaymentAccount account) {
			// do nothing
		}

		public void visit(AbcPaymentAccount account) {
			username = account.getUserName();
			password = account.getPassword();
		} 
	};
}

Uhh… just to call a couple of getters, I have to write such a huge code :-( Though its an elegant solution certainly not a solution I would like to go with. I would prefer going with the proxy interfaces for both the class and joined-subclass and cast them to the class I’m interested in instead of writing a huge piece of code just for calling a getter.

I’m eagerly waiting for someone to come up with a better solution (or shout at me that my understanding of the Visitor Pattern solution is wrong ;-) ) for this problem !!

submit to reddit Digg!

Comments (1)

Hibernate inheritance ClassCastException (Part 1)

Yet another FAQ by hibernate users,

Why do I get a ClassCastException when I try to typecast an entity to its child class?

Hibernate uses cglib library to create proxies at runtime. Hibernate provides us with two ways to decide how the lazily loaded object should like.

  • Use the same entity class as the proxy interface
  • Specify your own proxy interface using the attribute proxy

If you go with the first approach, cglib will create a new proxy class that would extend the entity class and override all the methods in the entity class. If the entity object is a sub class, still the proxy will extend the super class but will override the methods from the child class. So there’s no way you can typecast your object to the child class.

Many developers tend to go with the first approach and end up with the ClassCastException. The solution to this issue is to go with the second approach where your entity and its subclass will have their own interfaces. In this case cglib creates a proxy class that implements all the interfaces specified in the proxy attribute (in both class and joined sub-class tags). Everywhere in your code, you should access the entity through the interfaces and not the implementation classes for the same reason mentioned above.

public interface User {

	public Long getId();

	public void setId(Long id);

	public String getName();

	public void setName(String name);
}

public interface Seller extends User{

	public String getCompanyName();

	public void setCompanyName(String name);
}

public class UserImpl implements User {
}

public class SellerImpl extends UserImpl implements Seller {
}

The mapping file will look like this,

<class name=”UserImpl” proxy=”User”>
	<id name=”id”/>
	<joined-subclass name=”SellerImpl” proxy=”Seller”>  
		..... 
		..... 
		..... 
	</joined-subclass>
	..... 
	..... 
</class> 

So when you retrieve the child class, you can typecast the entity to the child interface.

One thing to note here is, is you specify the proxy attribute for the parent, you should also specify it for the joined-subclass.

The only heck/drawback that I see with this solution is you will end up including all the methods to the interface as you can’t cast it to the implementation class :-(

There’s another solution (happened to see in some other blogs) that’s been tipped as the elegant solution “The Visitor Pattern”. I will discuss about this in my next blog…

submit to reddit Digg!

Comments (2)

Limitations of OpenSessionInViewFilter

If you have been backing your web application using Hibernate, you would have certainly encountered this famous issue. How to use the lazy loaded objects in View? When you try to use the lazy loaded objects in your jsps, you will encounter the below exception,

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

As I mentioned in my previous post, this would occur when we try to initialize a lazily loaded entity after the underlying session is closed. But there’s a great work around for this issue provided by Spring framework, OpenSessionInViewFilter. We just need to plug this filter to our web.xml and thats it, you gotta do nothing. This filter takes care of opening up a session when a request arrives and keeps it open till the response is sent back to the client. This means the session will be alive in the jsps too :-) Wow!! that’s really great indeed but at the cost of below limitations.

Long connection hold time
One good thing about hibernate is everything can be (is) done lazily. For instance, the db connections will be retrieved only when we try to execute a query and not when you open up a session. Hibernate allows provides a couple of connection release strategies that can be configured in the hibernate prperties,

connection_release_mode=after_transaction | after_statement

after_transaction will make sure that the connection is released immediately after the transaction is committed/rolled back. after_statement will release the connection immediately after executing a statement.

So where is the long connection hold time? The issue again comes with the lazily loaded proxy objects. Under normal circumstances, hibernate attempts to release the connection after every operation (You can see the source for the methods get/load in SessionImpl. The finally block has a call to afterOperation that takes care of releasing the connection). But when you try to initialize a lazy loaded proxy object, hibernate makes a call to,
session.immediateLoad()
This method doesn’t release the connection after the object is loaded. What the heck!! So the connection is held by the session till it is closed. In case of the OpenSessionInViewFilter, it’s till the response is sent back to the client. So the maximum time the connection is held is equal to the time that you take to respond to the request.

Danger of Memory/Connection leaks
The OpenSessionInViewFilter adds value when the request is processed within the same thread but consider the case where you want to parallelize the work using multiple threads. Bang!! your session per request model is gone. You would have coded your application under the assumption that session will be kept open throughout the request life time.

If you assume still the session per request model to work, you would start seeing all crazy lazy exceptions from hibernate. Since you are not handling the sessions in those threads, and Spring DAO anyways creates the session internally, you will be leaking out the sessions and hence the connections (as explained in limitation one above).

You are now force to handle the session cleanup on your own. Fortunately I managed to find a *hack* to fix this issue. It just makes the thread to do the cleanup once the job is done.

public class HibernateSessionAwareThread extends Thread {
	
	public void run() {
		super.run();
		cleanup();
	}

	public void cleanup() {
		Session session = TransactionSynchronizationManager.unbindResource(factory);
		SessionFactoryUtils.closeSession(session);
	}
}

You can make use of this thread when you want to parallelize the work. If you are extending the thread, override the run method and call super.cleanup() at the end of the job,
public class MyThread extends HibernateSessionAwareThread {

	public void run() {
		try {
			// all the hibernate related job
		} catch(Exception e) {
			// Handle the exception
		} finally {
			super.cleanup();
		}
	}
}

If you pass on a Runnable interface to the thread, the session cleanup is automatically taken care of by the HibernateSessionAwareThread thread.

One might say that a thread should not know anything abt the session handling. But the idea here is to make the application return a custom thread for processing. A bad design but quite a neat hack !!

submit to reddit Digg!

Leave a Comment

Weird Hibernate Sessions

I came across a bizarre behavior in my hibernate code. Just copying the code snippet here,

Transaction transaction = session.beginTransaction();
User user = null;
try {
	user = session.load(User.class, id);
	// Some entity operations
	// ......
} catch(Exception e) {
	transaction.rollback();
	logger.error("Failed to blah blah blah..", e, user.toString());
} finally {
	if(noErrors) {
	transaction.commit();
}

I had my application using Spring OpenSessionInViewFilter and hence one hibernate session is created per request. The issue that I encountered was in the log line,

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

Hibernate will throw this exception when we try to initialize a lazy object and a session is attached to the lazy object. In my case, the log statement does nothing but just prints the ‘user’ entity. The user entity of course was lazy loaded but since the session is kept open throughout the request life time, I wasn’t expecting hibernate to throw this exception.

After spending close to an hour (checking the hibernate logs), I decided to debug the application. Here are my findings,

  1. An exception was thrown in the try block
  2. In the catch block, the transaction was rolled back
  3. The log statement was executed

And the exception was thrown… What’s wrong with my code? I decided to debug further to the hibernate code. This is what hibernate does when a transaction is closed. It clears the session :-( Removes all the lazy objects from the session cache and disassociates itself from the lazy object and hence the above error.

This is certainly what I would expect from hibernate. Why should it remove the lazy objects from the session? Why should it disassociate itself from the lazy object? At the least I don’t find a reason why it should be cleared of from the session.

I had to make a worst of the hacks by moving the log statement before the rollback statement :-(

submit to reddit Digg!

Comments (2)

Get rid of stored procedures

I have been seeing lot many developers using stored procedures in their application without a real need for that. Most of them are carried over as a legacy code. The days when writing transactional code were not that simple, we used to create stored procedures. But with the coming of all the data access frameworks, writing transactional code has become much simpler. Moving these stores procedures to the business layer would certainly make the code much readable. Isn’t handling the business logic within the application sound a lot better? Of course, not all stored procs can be moved. Doing so will bring severe performance impact on the application in some cases. For instance, when you work with huge set of data, its better to do that in the database end rather in the application.

submit to reddit Digg!

Leave a Comment

« Newer Posts
Follow

Get every new post delivered to your Inbox.