Jun 2, 2010

How to Implement Hashcode() and Equals(): Dos and Don'ts

The hashcode() and equals() method have always intrigued me a lot! I had never wanted to dive in depth into this! However, I thought I should dive deep into the bet practice related to the implementation of equals() and hascode() for domain objects.

Before we dive deep into this let me tell you the problems that you might confront if you do not override hashcode() and equals() in your persistent domain objects

Consequences of Not Overriding the Equals() and Hashcode()

  1. When you try to load the same persistent object from 2 different sessions, then you might have unexpected results. Let us say that we have the following code where in the domain object Sample does not have the overridden equals() and hashcode()
  2. int i=2;//2 is the existing id of the Sample object in the db
    Sample s1 = firstSession.load(Sample.class, i);
    Sample s2 = secondSession.load(Sample.class, i);
    assert(s1.equals(s2));
    
    In the above case, we would expect that the assert statement would return true! But this would never be the case since the s1.equals(s2) would just make a == comparison and would return false. For a simple Sample class given below:
    public class Sample {
    private int id;
    private int rollNo;
    
    public int getId() {
    return id;
    }
    
    public void setId(int id) {
    this.id = id;
    }
    
    public int getRollNo() {
    return rollNo;
    }
    
    public void setRollNo(int rollNo) {
    this.rollNo = rollNo;
    }
    }
    
    The following code would return false if the hashcode() and equals() are not overridden
    Sample s2 = new Sample();
    s2.setRollNo(2);
    s2.setId(1);
    Sample s3 = new Sample();
    s3.setRollNo(2);
    s3.setId(1);
    System.out.println("am here:"+s2.equals(s3));
    
  3. If you are planning to use the domain object as a composite id, it is imperative that you override both the methods. Else the equals() of the Object class would be used where in the == would be used and it would never suffice!

ID Based Equals() and Hashcode() Implementation: Hidden Dangers

One of the very common implementation of the equals() and hashcode() methods that I come across is as given below: It uses the id property for the implementation
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Sample)){
return false;
}
Sample other = (Sample)obj;
if (!(other.getId() == this.id)) return false;
return true;
}

@Override
public int hashCode() {
return this.id;
}
But how far is the above code reliable? Is this the right way of implementing the equals() and hashcode()? In case of ORM solutions like Hibernate, where the ORM would not generate the id till it saves the domain object to the db, the above implementation proves to be hazardous. Here is a very nice article that tells the problems associated with the implementation given above!

  1. First and foremost, putting the unsaved domain objects with equals() and hashcode() (in ORM like Hibernate) described above into sets would produce unexpected results.
  2. Let us have a look at the below code:
    Sample s = new Sample();
    s.setRollNo(2);
    Sample s1 = new Sample();
    s.setRollNo(2);
    Set<Sample> newSet = new HashSet<Sample>();
    newSet.add(s);
    newSet.add(s1);
    System.out.println(newSet.contains(s));// returns true
    System.out.println(newSet.contains(s1));// returns true
    System.out.println("size:" + newSet.size()); // returns 1: unexpectedly
    // due to improper
    // implementation of
    // equals() and hashcode()
    
    In the above code, the id of both s and s1 would be 0 if int or null if the type is Integer. As a result, the second s1 when put in the set overrides the first s object and hence when tested for contains the hashcode() method returns 0 for id and hence both return true. But, the set size is just 1!
  3. Secondly, the collections would produce unexpected results before and after saving them to the db. Lets see this issue in detail.Consider the following code:
  4. HashSet newSet = new HashSet();
    Sample s4 = new Sample();
    newSet .add(s4);
    session.save(s4);
    assert(newSet .contains(s4)); // returns false since the id before and after save changes.
    

Here the id of the Sample object before saving is 0 and after saving is different and is determined by the ORM. As a result the assert returns false in contrary to what is expected!

Best Alternative Implementation

Amidst such issues, the best option would be to implement equals() and hashcode() using a combination of business keys! In an IDE like Eclipse. it is going to be easy. Just right click, point to source --> Generate equals() and hashcode() and you have the option as shown below to choose the business keys that you want to be a part of the equals and hashcode() checks. With all, this proves to be the best and the most reliable option to me! However, do keep me updated with your suggestions too!

Best Practices
  1. Ensure that your customized implementation abides by the contract dictated by sun.
  2. Ensure that you are making use of a combination of immutable business keys of the domain object for the implementation.
  3. Do have a look at the hibernate forum discussion before you go ahead withe the implementation.
  4. Yet another article that is worth checking is here. Have a look and then go ahead with your customizations further!

May 18, 2010

Java Code Optimization: Tip # 1: How To Use Java Map .contains() and .get()

One very common mistake that I see in application code written in java is the way maps are accessed! Though it is very common, in my opinion I would say that this is an expensive mistake! Go ahead, get to know what the error literally is and correct the same if you come across one in future for that would help you to have an optimized code on the fly.

Let us say that we have a map! Let us create the map
Map<Integer,String> testMap = new HashMap<Integer, String>();
testMap.put(1,"one");
testMap.put(2,"two");

Here, while looping through the keyset of the above Hashmap, a java developer very often tries to do the following:

Un-Optimized Code:
<br />if(testMap.contains(1))<br />{<br />    String tempString = testMap.get(1);<br />    System.out.println(tempString);<br />}<br />

This is emphatically a stress to the memory and makes an un-optimized code. Here,
  • We check whether the map contains the key we are looking for.
  • Next, we try to get the value of the key if the key is present in the map
  • We access the map 2 times and if this is placed within a for loop, imagine the number of times we would be accessing the map

The above code can easily be replaced by:

Optimized Code:
<br />String tempString = testMap.get(1);<br />if( tempString == null)<br />{<br />    System.out.println(tempString);<br />}<br />

In the optimized code,
  • we are not checking whether the map contains the key we are looking for.
  • We are just trying to get the value for the key specified.
  • If the key exists in the map, we would have a valid value in the tempString.
  • Else, this would be null and hence we access the map just once for every check we do!

In my opinion, rather than accessing map.contains() and map.get() for every check, trying to get the value by using map.get() would render an optimized code
That was one optimization technique that I found was really utile! And hence thought of sharing the same with you all!

May 10, 2010

Spring Annotations: A Remarkable Reference

I was surfing the Internet and accidentally came across a nice reference for Spring. Since i work with more of Spring annotations, I really found it to be very cool!!! A reference card for Spring annotations is emphatically rare! It is quite useful too!! I thought it is a must have for a programmer who works in java and especially Spring based web application using annotations.

This thought forced me to share the same with you guys too! Here is a list of Core Spring Annotations, Spring MVC annotations, Aspect J and JMX annotations along with JSR 250 and Testing annotations too!! Go through this and have a good time! Keep me posted with your feedback as usual!

Reference Card for Spring Annotations


Source: Dzone.com

May 5, 2010

How To Use @Async in Spring Web Application?

I decided to give the @Async annotation a try! The recently added @Async annotation in the Spring Framework 3.0 seems to be an easy fit for applications that would require asynchrous calls to be invoked while the application is running or deployed! Here is a sample code that can help you with making your @Async annotation work with ease!
  1. As the first step, you have to incorporate the schema location detail and the xmlns detail for the task tag in Spring framework. The xmlns configuration details that you need to include is:
    xmlns:task=http://www.springframework.org/schema/task
  2. The schema location configuration details that you need to include in your application context includes


    http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-3.0.xsd
    
  3. Next, make Spring container understand that you are going to invoke asynchrous tasks that are annotation driven. So, remember to add the following line in your applicationContext.xml file.


    <br /><task:annotation-driven><br />
  4. After this, check your configuration xml file to ensure that you have implemented the context scanning on the code package where you are going to define the asynchronous jobs that you expect to be run by the spring framework. Let us say, we have a package org.webapp.services.tasks where we are going to have a class that would have all the methods annotated with @Async here and these would in turn be invoked by the scheduler. Then, ensure that you have this package as a part of the component scanning tag within the configuration xml file as follows:


    <br /><context:component-scan base-package="org.webapp.services.tasks"><br />
  5. Now, we are almost complete with the changes in the configuration files. Next, let us go ahead with a class that would have methods annotated with @Async which are in turn the asynchronous tasks that would be invoked within our application. Remember, as discussed earlier, this class needs to be in org.webapp.services.tasks package. Let us refer to this class as MyScheduler.java. The code for this class would look something like:


    <br />package org.test.common.utils.Tasks;<br />import java.util.Date;<br />import org.springframework.scheduling.annotation.Async;<br />import org.springframework.transaction.annotation.Transactional;<br />import org.springframework.stereotype.Component;<br />@Component<br />public class MyScheduler implements Scheduler{<br />@Transactional(readOnly = false)<br />@Async<br />public void testTask() {<br />System.out.println("Starting to process the task at " + new Date()); <br />}<br />}<br />
  6. And that is it! You are done. The @Async tells the spring container that the method underneath is an asynchronous task that would be invoked within the application. You can call this method from any class using the snippet as given below:


    <br />@Autowired<br />private Scheduler s;<br /><br /> s.newTask();<br />
  7. Further, when you use @Async you can return parameters from those methods and that should be Future typed. Say Future etc! That is unbelievable. Even if you want to update the db, you can go ahead and get the current session and process this method within a transaction to make db updates on a periodical basis.
If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!



May 4, 2010

How to Implement a Task Scheduler/ Job Scheduler in Spring Framework using Annotations?

I had a chance to analyze how the task scheduler works in Spring framework today!! The recent addition of the @Scheduled and @Async into Spring framework 3.0 forced me to tgive them a try! Emphatically, spring framework is remarkable. With a few tweaks in code, everything gets in place as expected. In this article, let me give you a very brief overview on how to implement a scheduled task in spring using @Schedule annotation! This would be a nice tutorial for a newbie and an intermediate Spring programmer! If you intend to have a scheduled job run periodically and if you are using Spring, please read further and get to know the nuances involved.Let us dive into action right away!.
  1. First and foremost, let us decide on incorporating the task:annotation-driven in the applicationContext.xml file. This is the configuration file that would be loaded by the ContextLoaderListener within your spring application. I have decided to have the task:annotation-driven tag within the application since this is where I would be including the beans that would form a part of my service layer and I am going to include the TaskScheduler class a service in my application.
    Next, go ahead and add the xmlns details to your configuration. The following code needs to be added to the applicationContext.xml file in your application.

    xmlns:task=http://www.springframework.org/schema/task
  2. Further, you have to add the schema location details for the task-annotation driven tag in your applicationContextxml. This is as follows:

    http://www.springframework.org/schema/task  <br />http://www.springframework.org/schema/task/spring-task-3.0.xsd<br />
  3. Note: If you do not add the configurations given in point # 1 and #2 in your applicationContext.xml where we would be defining the services used in our application (I am conidering that I would have a class containing the scheduled jobs as a service and this would be a part of my services package), you are likely to get the "The prefix 'task' for element '' is not bound" error.
  4. Next, you have to make your Spring container understand that you would be having some scheduled jobs within your application and those tasks are driven by annotations. You can do so by adding the following line to the applicationContext.xml file.

    <task:annotation-driven><br />
  5. Now, it is important that the Spring framework should be aware of the class details where you would be using your @Scheduled annotation. For this, let us consider we have a package or.webapp.services.tasks. In this package, let us consider that we have a class MyScheduler.java. This is the class that would contain all the methods which would be invoked as scheduled tasks/jobs in your application. It is important that you add this package in the component-scan tag within your applicationContext.xml as follows:

    <context:component-scan base-package="org.webapp.services.tasks"<br />
  6. Next, we need to code the details of the scheduled job within the class MyScheduler. As a sample, we will have one method testTask. This task would be annotated as @Scheduled with the required attributes. This would in turn make Spring container understand that the method underneath this annotation would be run as a job that is scheduled by the Spring Framework. This can be done as follows:

    package org.test.common.utils.Tasks;<br />import java.util.Date;<br />import org.springframework.scheduling.annotation.Scheduled;<br />import org.springframework.stereotype.Service;<br />@Service<br />public class MyScheduler {<br />  <br />    @Scheduled(fixedRate = 5000)<br />    public void process() {<br />        System.out.println("Invoking testTask at " + new Date());<br />    }<br /><br />}<br />
  7. Attributes for @Scheduled Annotation:If you want a job or a task to be run every 5 secondsm then you need to modify the @Scheduled annotation sued above as: @Scheduled(fixedRate = 5000). If you want a time gap of 5 seconds between the end of previous execution and the start of the succeeding execution then you need to modify the @Scheduled annotation as @Scheduled(fixedDelay= 5000). You can also trigger a cron job and define your cron parameters say try running a job at 6.30pm everyday by using @Scheduled(cron="30 18 * * * ")
  8. And that is it! You deploy the application. You would see the 'Invoking testTask at " + current date' getting printed every 5 seconds in your console!
  9. Further, Even if you want to update the db, you can go ahead and get the current session and process this method within a transaction to make db updates on a periodical basis.
  10. Note: Remember that the methods annotated with @Scheduled should not have parameters passed to them. They should not return any values too.If ever you want the external objects to be used within your @Scheduled methods, you should inject them into the MyScheduler class using autowiring rather than passing them as parameters to the @Scheduled methods
If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!Technorati Tags: , , , , ,

Understanding the Different ApplicationContexts in Spring Application

As a beginner to spring, one might often not know the difference between the several applicationContexts that we use in a spring application. Spring documentation is the best place that can really guide you though the process of completely getting this clarified!

But here is the abridged version for a quick understanding of the differences between the various configuration files that we use in a spring application.

  • Understand that the webapplicationcontext denotes the xml configuration file that is invoked by the DispatcherServlet within the spring enabled web application. This is the xxx-sevlet.xml file where you define the details of the handler mappings, view configuration, controller bean definitions and other web related beans. This also includes the definition of the locale and theme resolvers that you might use within your application. You can have a single or multiple web application contexts within your spring enabled web application.
  • The other application contexts that are used within the spring enabled web application are usually loaded by the contextLoaderListener/servlet as shown in the figure below. This can be a single file (applicationContext.xml) or multiple applicationcontexts with names based on the modularization that you make within the application. these application contexts are very different from the web application contexts. They contain the details of the datasources, daos, services, other component beans and the details of the transaction managers used within your application.
  • Note that the webapplicationcontext used within any application would have access to all beans defined within the application contexts that are loaded by the ContextLoaderListener.
                        
  • When you configure the transaction manager, it is important to understand the fact that the Txmanager will search for @Transactional type annotations in all the beans defined within the same application context only! So, this means that you cannot define the TxManager in the applicationContext and have your services and dao beans defined in the webapplicationcontext of your application for this would result in org.hibernate.HibernateException: No Hibernate Session bound to thread. Before you go ahead, ensure that the above differences are very clear and configure your application accordingly!
Technorati Tags: , , , ,

Apr 28, 2010

How To Use Transaction Manager with @Transactional without getting 'org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here' Exception?

Its you readers who post comments on my blog often induce me to post more information and additional write ups here!I sincerely thank you for that induction you create in me! Based on the information requested, I thought of posting an article here that would help many of you (like me) who end up with the very famous "org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here".

If you are looking at the procedure to incorporate the TxManager in your spring application by making use of @Transactional annotation along with org.springframework.orm.hibernate3.HibernateTransactionManager and , here is the right information that you can make use of! This would not only help you to get out of 'org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here' exception but would also help you in understanding the rudiments involved with the transaction very easily.

Here are the basic steps that you can make use of. Let us say that you have an applicationContect.xml(This is the application context that is loaded by the contextLoaderListener/contextLoaderServlet of your application). Let us say that you have a webdispatcherservlet's webapplication context named as application-servlet.xml.

In this case, please follow the steps given below to incorporate the transactions with ease. In my opinion, it is always recommended that you have your service layer transactional . So i intend introducing the @Transactional annotations at the services in the following example!
  1. First and foremost, define the TxManager bean within the applicationContext.xml as shown below. Remember that this context is the place where you should define the component scan for the services and daos present within your application.
  2. <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="defaultSessionFactory" />
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" />
  3. Note that if you define the bean id of your TxManager as transactionManager, the tx:annotation driven tag can be as given below. It literally means that you need not define the name of your transaction manager in the tx:annotation-driven tag. If you have this bean's id as something else other than "transactionManager", you need to have the the additional attribute "transaction-manager" to the tx:annotation-driven tag.
  4. <tx:annotation-driven /><br />
  5. Next,define the xmlns for the tx tag as given below in the same applicationContext.xml
  6. xmlns:tx="http://www.springframework.org/schema/tx"<br />
  7. Further, you need to add the schema location for the Tx tag as shown below in the same applicationContext.xml
  8. http://www.springframework.org/schema/tx <br />http://www.springframework.org/schema/tx/spring-tx-3.0.xsd<br />
  9. Next, go to your daoImpl file say sampleDaoImpl.java and define the sessionFactory as shown below
  10. @Repository("SampleDAO")<br />public class SampleDaoImpl implements SampleDao {<br /><br />    @Autowired<br />    @Qualifier("appSessionFactory")<br />    private SessionFactory sessionFactory;<br />
  11. Remember that you have to use the sessionFactory injected in your daoimpl as shown below
  12. sessionFactory.getCurrentSession().saveOrUpdate(hibernateObject);<br />
    or
    sessionFactory.getCurrentSession().createSQLQuery("<your query here>")<br />
  13. Next, go to your service impl layer. Let us say that you have your service implementation file named as SampleServiceImpl.java. Here, you will have to introduce the @Transactional annotations. Be careful and ensure that you make the transaction read only for the find and get queries while you can make the transaction writeable in methods that updates, saves or deletes the objects in db as follows. Here, you can make the @Transactional annotation at class level as read only. When you have an update method that writes to the db, you can annotate that method with @Transactional(readOnly=false) for this would override the class level annotation incorporated as readonly!
  14. @Service("sampleServiceImpl")<br />@Transactional(readOnly = true)<br />public class SampleServiceImpl implements SampleService {<br />@Autowired<br />@Qualifier("sampleDAO")<br />private SampleDAO sampleDAO;<br />public sampleObject getObject(int id)<br />{<br />return sampleDao.getObject(id);<br />}<br />@Transactional(readOnly = false)<br />public void update(SampleObject sampleObj) <br />{<br />sampleDAO.saveOrUpdate(sampleObj);<br />}<br />}<br />
  15. That is it!!!Your application would have included the TxManager successfully! Your db calls would be then managed by the Spring defined TxManager without any problems from here!
While this depicts a very simple implementation, you can go ahead and change the properties for the @Transctional annotation further to modify the propagation and isolation levels wherever necessary! You can also implement multiple transactional managers if need be by using @Transactional("TxManager1") and @Transactional("TxManager2") and by defining the corresponding TxManagers in your appplicationContext.xml with ease!!! Hope this helps you to circumvent the famous "org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"! Whatsoever, keep me posted and stay tuned!

If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!