Friday, July 27, 2007

How to Properly Iterate a Collection in Java

There are multiple ways to iterate a collection in Java among many other things but that doesn't mean all are equally elegant or easy on the eyes. Just as some ways to skin a cat are messier than others (Not that I have ever skinned a cat or any other animal for that matter). Anyhoo I'm making this post in hopes of at least few developers starting on Java will see it before starting to write code in a commercial project.

I came across a code base of a project that was developed mostly by a bunch of junior developers and most of the code that iterates a collection was in the following format

List administrators = getAdministrators();

if (administrators.size() > 0) {
Iterator administratorsItr = administrators.iterator();
Administrator administrator = null;
while (administratorsItr.hasNext()) {
administrator = (Administrator) administratorsItr.next();
//rest of the code block removed
}
}
}

Just looking at that piece of code made my head spin :). The worst part was that this is the style most of the junior developers had adopted and could be seen all over the code base.

Just for the record I would have written it in the following way (actually would have let the IDE write it for me)

List administrators = getAdministrators();

for (Iterator iter = administrators.iterator(); iter.hasNext();) {
Administrator administrator = (Administrator) iter.next();
//rest of the code block removed
}

The above two code blocks achieve the same thing, the difference been, first is 9 lines long and the second is 4 lines. Most importantly you can figure out whats going on easily by looking at the second code block.

The worst part is IDEs like IntelliJ IDEA will write it for you. All you have to do is type itco and press ctrl + space keys just after the List administrators = ... line.

I don't know if there is something similar on Eclipse but you can import all these nifty IDEA Live Templates into Eclipse. Just head over to this page where you can find the xml file and instructions on how to import the file.

Don' forget to click the +1 button below if this post was helpful.

Tuesday, July 17, 2007

Achieve Automatic Transaction Rollback with MockStrutsTestCase and Spring

Spring provides a convenience base class (AbstractTransactionalDataSourceSpringContextTests which extends the TestCase class from Junit) to automatically rollback any updates made to the database at the end of a test method. This works great when integration testing Service and DAO beans but it wont help when integration testing the Struts layer with MockStrutsTestCase.

Spring does not provide a class such as AbstractTransactionalDataSourceSpringContextTests that extends from the MockStrutsTestCase. This might be due to practical issues with the way Spring context initialization works when using MockStrutsTestCase. I tried achieving the transaction rollback in the same way as was done in the AbstractTransactionalDataSourceSpringContextTests class but it didn't work out as the application code started a new transaction and commited as usual without using the transaction I started in my own subclass of MockStrutsTestCase.

Another option left for me was to go down to the Transaction Manager level and achieve the rollbacks there. The application uses Hibernate at the DAO level and it was using HibernateTransactionManager as the transaction manager implementation when running test cases . Therefore I had to write a new class extending from HibernateTransactionManager which overrides the doCommit() method. The overridden method will call doRollback() method in the super class. This would rollback the current running transaction even if the declarative transaction handling code in Spring calls doCommit on the transaction manager.


package com.xyz.txn;

import org.springframework.orm.hibernate3.HibernateTransactionManager;

public class HibernateRollbackTxnManager extends HibernateTransactionManager {

/*
* doCommit method that calls the doRollback method of the super class.
*
*/
protected void doCommit(DefaultTransactionStatus txnStatus) {
super.doRollback(txnStatus);
}
}

Finally override the default transaction manager in your test spring bean configuration with the rollback only implementation.

<bean id="txnManager" class="com.com.xyz.txn.HibernateRollbackTxnManager">
<property name="sessionFactory"><ref local="sessionFactory"></property>
</bean>


The same strategy would work with other transaction managers such as DataSourceTransactionManager too.

Don' forget to click the +1 button below if this post was helpful.