Spring transactions After two days of debugging our codes on transaction handling, I’m writing this post to share my experience so others don’t have to undergo the same pain and torture. However, this post assumes that you’ve setup your Spring transactions - either via AOP or annotations. If you haven’t done so, here are some good references:

  1. Spring Framework - Transaction Management
  2. On Java - Wire Hibernate Transactions in Spring

So, once you’ve setup or tried to setup transactions and failed - here are some tips how to debug your transaction management.

Enable logging. In log4j.properties, add log4j.logger.org.springframework.orm.jpa=DEBUG to enable logging of JPA transactions. This will allow you to trace the activities behind the Spring transaction processes. The logs provide detailed information about new, reused and active transactions, transaction modes, transaction commits and more. This is the best way to understand how transaction behaves on your application and gives you an insight how to fix your transactional problems.

Check your database and dialect. Dialects affect transaction handling so be sure to use the appropriate dialect for your database. Note that there are 2 dialects to define - JPA Dialect and Hibernate Dialect. JPA dialect is defined in the EntityManagerFactory while Hibernate is defined in Hibernate properties.

JPADialect is defined in EntityManagerFactory as shown below:


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="persistenceUnitName">
<value>hibernateConfig</value>
</property>
</bean>

While Hibernate Dialect is defined via persistence.xml.

Watch out for listeners, they could mess up your transactions. A couple of examples about listeners (especially ApplicationListener) found online doesn’t consider transaction handling. Most of them performs data updates within the listener. This should not be the case because in doing so, you could be creating a transaction on the listener which forces all other operations to reuse that transaction. The better way of doing it is to call a service or business layer to perform transactional operations. This way, transaction is created only when the service is invoked.

Declare your transaction as readOnly whenever possible. Read-only transactions run faster so enable this on non-writing functions - (e.g. load, read, find, etc). Also, this avoid transaction commits on binded-data. One specific scenario is when Spring validation throws an error and data is still saved despite the validation error, this means that the data was loaded on a non-readOnly transaction and Spring transaction is committing it.

Reduce your transactional method calls. Put all your business logic function calls in one method marked with @Transactional and avoid calling other methods with their own transaction declarations. For example, if your transactions are declared on service layer, avoid calling another service method because this will trigger transactional checks which unnecessarily slows down the system. Call the DAO method directly instead. This way all your operation are contained in a single transaction declaration.

Understand propagation. Transaction propagation is hard to understand because the effects cannot be easily seen in your application… until you start performance tuning or having problems on saved data. Take note that if your transaction propagation is default, it will try to reuse existing transactions. This means that you could lose your transaction settings (e.g. readOnly), because new transaction was not created instead an existing was reused.

Has anyone ever tried looking at OSWorkflow recently? It is unfortunate that this OpenSymphony project has been shelved. However, I found value in this lightweight workflow tool — for one, being lightweight makes it simple and easy to work with, plus, integration with Spring and Hibernate is readily available.

However, since OSWorkflow stopped development, there had been no support for JPA-based applications anymore. Fortunate for those interested in making JPA work on OSWorkflow via Spring, I was able to tweak some of the OSWorkflow classes and integrate it with JPA Session.

The primary problem in integrating OSWorkflow with JPA is the Session. The original session used by OSWorkflow (SpringHibernateOSWorkflowStore) is a sessionFactory injected via Spring. Since JPA uses EntityManager, the sessionFactory and EntityManager are on different transactions.

The solution is to extend AbstractHibernateWorkflowStore and use session from EntityManager. Here’s the code:

public class JPAHibernateWorkflowStore extends AbstractHibernateWorkflowStore {
    @PersistenceContext
    private EntityManager em;

	@Override
	protected Object execute(InternalCallback action) throws StoreException {
        try {
    		return action.doInHibernate((Session)em.getDelegate());
        } catch (StoreException e) {
            throw new RuntimeException(e);
        }
	}

	public void init(Map arg0) throws StoreException {
		// TODO Auto-generated method stub
	}

	/**
	 * @param em the em to set
	 */
	public void setEntityManager(EntityManager em) {
		this.em = em;
	}
}

Afterwards, use JPAHibernateWorkflowStore instead of SpringHibernateWorkflowStore as your workflow store. You will also need to copy HibernateCurrentStep.hbm.xml, HibernateHistoryStep.hbm.xml and HibernateWorkflowEntry.hbm.xml (under com.opensymphony.workflow.spi.hibernate3) to META-INF (along with persistence.xml). This will ensure that hbm mappings are recognized by the EntityManager.

Well, that’s basically it. If you are having a hard time following my instructions, try getting the standard SpringHibernateWorkflowStore to work first. Afterwards, change implementation to JPA-based approach.

Ciao!



We had fun at J2EE training today, JM talked about YUI, prototype, Script.aculo.us and Dojo. These javascript toolkits surely know their way around the javascript quirks that’s been perstering lots of developers with browser incompatibilities. I agree that these toolkits help a lot in making more stable javascript codes.

Some pictures taken from the training:

Some of our observations are:

  1. Lots of these toolkits do the same functionality (e.g. String utilities, Ajax calls, Animations). Is there any standard body that is defining the new sets of javascript features? So we all live in one common world of javascript coding? Or is it a battle of the best platform?
  2. Seems like we’re going back to the world of client-server days. As rich-interface becomes popular, will thin-clients begin to disappear? And what’s with Flex, Silverlight, JavaFX?
  3. When prototype popularized Object-Oriented approach, they made a good point about the power of Javascript… but still, the flexibility of javascript codes make it difficult to standardize. It’s more of a developer’s conscious effort to create cleaner code.

One neat thing I learned about prototype is that it has a method “Try.these{…}” where all the statements within will be evaluated until one actually works. Sounds useful when making your javascript methods work across multiple browser.

Today is the first day of our J2EE training. Everybody’s excited to become the first batch of the 3 months extensive training program. The training will cover open-source Java frameworks such as Spring, Struts, Hibernate, iBatis, etc. We will also cover newer technologies such as YUI, DWR. It’s going to be a tough but fun training for everyone. At the end of this training, we’ll get everyone at speed with the latest technologies on Java.

I’m happy that everyone in the team share the same passion on software development. With a little kick here and there, I’m sure we’ll get the core team in sync towards building creative software applications.

To give a preview of what’s up with Day 1, here’s a podcast on the introductory session. Unfortunatey, the audio isn’t good as I’ve placed the Macbook at the end of the room. I’ll try my Jabra tomorrow, see how that goes…

Although, the workstation didn’t arrive, the trainees were quite busy setting up the network. :)

Here’s a tip in Spring if you want certain URLs to redirect to specific JSP… For example:

http://www.ideyatech.com/magic/login.jspx -> acegi_login.jsp

http://www.ideyatech.com/magic/logout.jspx -> acegi_logout.jsp

Since Spring does not allow mapping directly to a jsp page. You need to create a controller to return the appropriate view. Alternatively, you can use URLFilenameViewController but then you’ll be limited to “prefix” and “postfix” append only. What if you wanted the mapping to be explicit as shown in example above?

My solution is to create a generic controller that will do the mapping. To do this, I’ve created a ViewMapController which behaves in almost exact the same manner with URLFilenameViewController except that mapping is explicitly specified with the filename.

In the example below, I’ve mapped /login.jspx to /jsp/acegi-login.jsp and /denied.jspx to /jsp/access-denied.jsp
STEP 1: Declare your mapping with SimpleUrlHandlerMapping

SimpleURLHandlerMapping

STEP 2: Declare your viewMapController with the view mapping. Declare your viewMapController with the view mapping.

SimpleURLHandlerMapping

STEP 3: Create the class ViewMapController.

public class ViewMapController extends AbstractController {
private Map viewMap;
private String defaultView;

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String uri = request.getRequestURI();
String key;
String viewName;

int idx = uri.lastIndexOf(”/”);
if (idx > 0)
key = uri.substring(idx+1);
else
key = uri;
if (viewMap.containsKey(key))
viewName = viewMap.get(key);
else
viewName = defaultView;
return new ModelAndView(viewName);
}

public void setViewMap(Map viewMap) {
this.viewMap = viewMap;
}

public void setDefaultView(String defaultView) {
this.defaultView = defaultView;
}
}

Note: the view will be resolved using your viewResolver. In this case, in order to resolve acegi-login to \jsp\acegi-login.jsp, I’ve declared the viewResolver as:

viewResolver

That’s all folks. You now have a more flexible way to map URLs directly to your JSP pages.

I’ve seen several implementations of ACEGI on enterprise applications. However, I’ve never setup one myself until earlier today… At first, I was quite frustrated with the spring configuration as none seems to work. After looking at several articles online, I get more frustrated as everyone talks about different syntax.

So, I’ve thought of writing down some documentation on how to make ACEGI work seamless with Spring and Hibernate but then I’ll just be adding more confusion to all available articles on the net. So instead of writing step-by-step instructions, I’ll just give out pointers on how to make your learning experience easier.

Rule #1: Follow the Petclinic examples provided from the build - with the exact build number! It seems that there are name changes in ACEGI on different releases. This means that you could be reading an article about ver. 0.8 which is not applicable on ver.1.0, etc. There are differences even on minor releases (1.0.2 to 1.0.4). So stick with the tutorial that comes with build and copy the spring-config from the tutorial as is.

Rule #2: Understand the security framework. Spend a few hours studying the ACEGI configuration. This will save you time later. I tried implementing ACEGI right away and whenever I get lost, I have to dig around and learn the concepts. I believe that its much easier to read and understand first before beating yourself out… I find this article very helpful: http://www.tfo-eservices.eu/wb_tutorials/pages/spring-acegi-tutorial.php But don’t take the configurations from this tutorial as some have changed since 1.0.2 to 1.0.4. Just learn the concepts and again - USE THE PETCLININC EXAMPLE FROM THE BUILD.

Rule #3: Get ACEGI working using InMemoryDaoImpl. Divide your work by focusing on getting the security features working before integrating this with your user DB or AuthenticationService. This way you can isolate your issue to ACEGI settings only. Note: The PETCLINIC example uses MD5PasswordEncoder for password, you need to disable this by removing PasswordEncoder property in your DaoAuthenticationProvider.

Rule #4: Do not wrap settings on ACEGI properties. ACEGI settings are sensitive on newlines, it will not recognize the text if configurations are wrapped. You cannot remove append the lines nor create newlines… if configuration text is long, leave it as is otherwise, ACEGI will not recognize it. While this may seem obvious, I got caught with this problem when I used auto-format in Eclipse.

Well… This is all I have for now…. good luck learning ACEGI!