Pages

Wednesday, October 19, 2011

Demo app on Cloudfoundry cloud

I have created a simple demo application that was deployed on cloudfoundry cloud. 
Cloudfoundry is a cloud service provider and currently supports Ruby, Spring applications. It also supports MySQL and MongoDB.



The demo app OFFICE LOCATOR shows the office and emplyee's location as markers on google map.
The initial data (employee and office address) was hard coded in a txt file as JSON string.

The application is deployed on cloudfoundry at the below location :

There is a menu in the left hand side of the page as shown below.



The menu shows two options.
1) View Map
2) View Distance

By default, when you load the page, the map will be shown.
In this page, the user can submit a new office. Then , the map will be updated with new and old offices.
Old office will be shown in "green" color and new office will be shown in "yello" color marker, while employees will be marked with "blue" color marker.


If users selects the second option in the menu ("view Distance" link), it will show a table with Employee name, address, distance from his address to new office and old office.The last column shows the difference
in the distance betwen new and old offices.
At the end,in the last row, it will show the average difference of distance of all employee's address.



Note :
Zoom in/out to see all the employee's address and old/new office locations.







Tuesday, July 5, 2011

Struts2+Spring+Hibernate Declarative Transaction

Problem Faced:

The DAO classes were annotated with @Transactional and the applicationContext.xml is updated with
 "<tx:annotation-driven mode="proxy" proxy-target-class="true" transaction-manager="transactionManager" / >"
 to use spring managed transactions in hibernate.


The below DAO method (reading from db) is working as expected.

public List findJourney(){
Query q=getSession().createQuery("from Journey");
List list=q.list();
return list;
}
However, the other method in the same DAO (save operation) is failing with HibernateException.
public boolean createJourney(Journey journey){
System.out.println("## createJurney in DAO");
try{
getSessionFactory().getCurrentSession().save(journey);
}catch(Exception e){
e.printStackTrace();
}
return true;
}

Exception throws is:
23:35:26,957 DEBUG SessionImpl:248 - opened session at timestamp: 13098891269
org.hibernate.HibernateException: save is not valid without active transaction
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
at $Proxy63.save(Unknown Source)
at com.red.travels.dao.JourneyDAOImpl.createJourney(JourneyDAOImpl.java:19)
at com.red.travels.dao.JourneyDAOImpl$$FastClassByCGLIB$$976443ed.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)

Solution:
In the applicationContext.xml file, for the sessionFactory bean configuration I have mentioned the property "hibernate.current_session_context_class" with "thread" as the value. This is required in hibernate, to use getCurrentSession()  i.e. to get the thread local session. However, this will not work with Spring transaction management. Spring 2.5+  override the default CurrentSessionContext (Spring's) with the standard Hibernate thread-local context. This is causing the problem. Refer to Spring JIRA

Once this property is removed from the sessionFactory configuration, everything works fine.

Struts2+Spring+Hibernate and OpenSessionInViewFilter


Problem Faced:

  • I have a struts2 action class (which is declared as a spring bean in application context) to retrieve the users list from the database and to show on the jsp.
  • Used Spring in the middle tier for transaction management (annotation based) and  HibernateDAOSupport form Spring to manage the DAO layer.
  • The action will call a service layer method which is transactional. The service method inturn called the UserDAO  to retrieve the User details. The User class has a relation with Account class.
  • By the time , the service layer method returns, only the User object will be initialized. Because , the Account entity is mapped as “lazy”.
  • In the JSP page, if I try to access Account property of the User, I’ll get LazyInitilizationException (as expected).

Now configured the “OpenSessionInViewFilter” in the web.xml. But still getting the same exception. The transaction is closing the underlying hibernate session once the transaction is completed.
In the logs I could see that the Filter is getting initialized, but no other statements related to it.
After some debugging found that, The OSIV filter is mapped in the web.xml after, struts2 filter. As a result, it is never applied to my urls. Changed the order of filters in web.xml. Now everything is working as expected.