My Octopress Blog

A blogging framework for hackers.

Upgrading Grails 1.3.x to Use Hibernate 3.3.2

While using Hibernate Envers, I ran into an issue that was fixed in Hibernate 3.3.2. Unfortunately, Grails is using Hibernate 3.3.1. Luckily, it’s fairly straightforward to exclude and declare a new dependency in your BuildConfig.groovy:


inherits("global") {
excludes 'hibernate'
}
dependencies {
compile ('org.hibernate:hibernate-core:3.3.2.GA'){
excludes 'ehcache', 'xml-apis', 'commons-logging'
}
}
Update: turns out it’s not as straightforward as I thought. The above will work fine with ‘grails run-app’ but the 3.3.1 version will still be in the War file: http://www.lucasward.net/2011/03/excluding-jars-from-grails-generated.html You can fix that by adding the following to your BuildConfig.groovy:


grails.war.resources = { stagingDir ->
delete(file:"${stagingDir}/WEB-INF/lib/hibernate-core-3.3.1.GA.jar")
}


Unfortunately, in the 3.3.2 release, ““org.hibernate.dialect.DialectFactory” was moved to “org.hibernate.dialect.resolve.DialectFactory”. Which was part of the following issue: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2933

This is apparently an issue many have been seeing: http://grails.1312388.n4.nabble.com/update-hibernate-version-td3002449.html

While it may seem crazy that the Hibernate team moved something to a new package in a point release. I’m pretty sure they consider this class to be internal and not part of their API. The issue the change was made in was to expose to users a way to resolve their own dialects programmatically. Which, if you look at where the Grails Hibernate plugin is creating the offending spring bean, is the same thing Grails is doing:


if (ds && ds.dialect) {
if (ds.dialect instanceof Class) {
hibProps."hibernate.dialect" = ds.dialect.name
}
else {
hibProps."hibernate.dialect" = ds.dialect.toString()
}
}
else {
dialectDetector(HibernateDialectDetectorFactoryBean) {
dataSource = ref("dataSource")
vendorNameDialectMappings = vendorToDialect
}
hibProps."hibernate.dialect" = dialectDetector
}


The above is taken from HibernatePluginSupport.groovy, line 128. (At least in Grails 1.3.6) Essentially they’ve written a Spring bean to programmatically determine the dialect by calling the DialectFactory themselves. You can bypass this issue completely by specifying your dialect, rather than having it detected. If you’re using mysql, it looks something like:


dataSource {
driverClassName = "com.mysql.jdbc.Driver"
dialect = "org.hibernate.dialect.MySQLDialect"
}

Comments

Lucas Ward
I'll see if I can dig for the issue I found that was causing issues in Envers. I also wrote a plugin as well that I haven't had a time to post. I'll be pushing it to github within the next couple of days.
stephen westfall
Can you provide any details on the Envers issue that triggered this upgrade? I'm trying to use Envers on a Grails project and having issues.