Upgrading Spring 3.x and Hibernate 3.x to Spring Platform 1.0.1 (Spring + hibernate 4.x)
I recent volunteered to upgrade our newest project to the latest version of Spring Platform. What Spring Platform gives you is dependency & plugin management across the whole Spring framework’s set of libraries.
Since we had fallen behind a little the upgrade did raise some funnies. Here are the things I ran into:
Maven:
Our pom files were still referencing:
hibernate.jar
ehcache.jar
These artefacts don’t exit on the latest version, so replaced those with hibernate-core.jar and ehcache-core.jar.
We also still use the hibernate tools + maven run plugin to reverse engineer our db object. This I needed to update to a release candidate:
1 | < hibernate-tools .version = "" >4.3.1.CR1</ hibernate-tools > |
Hibernate:
The code: “Hibernate.createBlob”… no longer exists
replaced with:
1 2 3 | private Blob createBlob( final byte [] bytes) { return NonContextualLobCreator.INSTANCE.wrap(NonContextualLobCreator.INSTANCE.createBlob(bytes)); } |
On the HibernateTemplate return types are now List; not element…So needed to add casts for the lists being returned.
1 | import org.hibernate.classic.Session; |
replaced with:
1 | import org.hibernate.Session; |
Reverse engineer works a little differently…
Assigns Long to numeric…
Added:
1 2 3 4 5 6 7 8 9 | < type-mapping > < sql-type jdbc-type = "NUMERIC" precision = "4" hibernate-type = "java.lang.Integer" /> < sql-type jdbc-type = "NUMERIC" precision = "6" hibernate-type = "java.lang.Integer" /> < sql-type jdbc-type = "NUMERIC" precision = "8" hibernate-type = "java.lang.Integer" /> < sql-type jdbc-type = "NUMERIC" precision = "10" hibernate-type = "java.lang.Long" /> < sql-type jdbc-type = "DECIMAL" precision = '4' scale = '0' hibernate-type = "java.lang.Integer" not-null = "true" /> < sql-type jdbc-type = "DECIMAL" precision = '6' scale = '0' hibernate-type = "java.lang.Integer" not-null = "true" /> < sql-type jdbc-type = "DATE" hibernate-type = "java.util.Date" /> </ type-mapping > |
Possible Errors:
- Caused by: org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]
Add a dependency for c3p0:
1 2 3 4 5 | < dependency > < groupid >org.hibernate</ groupId > < artifactid >hibernate-c3p0</ artifactId > < version >${hibernate.version}</ version > </ dependency > |
And configure the settings in the cfg.xml for it:
1 2 3 4 5 | < property name = "hibernate.c3p0.min_size" >5</ property > < property name = "hibernate.c3p0.max_size" >20</ property > < property name = "hibernate.c3p0.timeout" >300</ property > < property name = "hibernate.c3p0.max_statements" >50</ property > < property name = "hibernate.c3p0.idle_test_period" >3000</ property > |
- Caused by: java.lang.ClassNotFoundException: org.hibernate.engine.FilterDefinition
Probably still using a reference to hibernate3 factory / bean somewhere, change to hibernate4:
1 2 | org.springframework.orm.hibernate3.LocalSessionFactoryBean org.springframework.orm.hibernate3.HibernateTransactionManager |
- Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.hql.classic.ClassicQueryTranslatorFactory There is minor change in new APIs, so this can be resolved by replacing property value with:
1 | org.hibernate.hql.<b>internal< /b >.classic.ClassicQueryTranslatorFactory. |
Spring:
Amazingly some of our application context files still referenced the Spring DTD … replaced with XSD:
1 2 3 4 5 | <? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation="http://www.springframework.org/schema/beans |
In Spring configs added for c3p0:
1 2 3 4 5 | < prop key = "hibernate.c3p0.min_size" >5</ prop > < prop key = "hibernate.c3p0.max_size" >20</ prop > < prop key = "hibernate.c3p0.timeout" >300</ prop > < prop key = "hibernate.c3p0.max_statements" >50</ prop > < prop key = "hibernate.c3p0.idle_test_period" >3000</ prop > |
Spring removed the “local”=: so needed to just change that to “ref”=
Spring HibernateDaoSupport no longer has: “releaseSession(session);”, which is a good thing so was forced to update the code to work within a transaction.
Possible Errors:
- getFlushMode is not valid without active transaction; nested exception is org.hibernate.HibernateException: getFlushMode is not valid without active transaction
Removed from hibernate properties:
1 | < prop key = "hibernate.current_session_context_class" >thread</ prop > |
Supply a custom strategy for the scoping of the “current”Session . See Section 2.5, “Contextual sessions” for more information about the built-in strategies |
- org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove ‘readOnly’ marker from transaction definition.
Another option is :
1 2 3 4 | < bean id = "productHibernateTemplate" class = "org.springframework.orm.hibernate4.HibernateTemplate" > < property name = "sessionFactory" ref = "productSessionFactory" /> < property name = "checkWriteOperations" value = "false" /> </ bean > |
- java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig
Servlet version update:
1 2 3 4 5 | < dependency > < groupid >javax.servlet</ groupId > < artifactid >servlet-api</ artifactId > < version >3.0.1</ version > </ dependency > |
- Then deploying on weblogic javassist: $$_javassist_ cannot be cast to javassist.util.proxy.Proxy
The issue here was that there were different versions of javassist being brought into the ear. I all references removed from all our poms, so that the correct version gets pulled in from from Spring/Hibernate…
and then configured weblogic to prefer our version:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | <? xml version = "1.0" encoding = "UTF-8" ?> < weblogic-application > < application-param > < param-name >webapp.encoding.default</ param-name > < param-value >UTF-8</ param-value > </ application-param > < prefer-application-packages > < package-name >javax.jws.*</ package-name > < package-name >org.apache.xerces.*</ package-name > < package-name >org.apache.xalan.*</ package-name > < package-name >org.apache.commons.net.*</ package-name > < package-name >org.joda.*</ package-name > < package-name >javassist.*</ package-name > </ prefer-application-packages > </ weblogic-application > |
Reference: | Upgrading Spring 3.x and Hibernate 3.x to Spring Platform 1.0.1 (Spring + hibernate 4.x) from our JCG partner Brian Du Preez at the Zen in the art of IT blog. |
Hi,
I just did the same kind of migration, I also removed [hibernate.current_session_context_class] but not sure why, I had a try-change-try approach and noticed that {absent} property looks (now?) like a distinct value, different from what was default [thread]. Do you know something more about this ?
Thanks