Deploying with Hibernate too
Posted by danielmeyer on July 24, 2008
Last time (for those new to this saga, we started some time ago working on this — and really even earlier), we had JMS messaging rollbacks seemingly working in the context of an XA transaction and we were adding in all the pieces for the Oracle/JDBC/Hibernate transaction too — everything I could think of initially, anyway. We were to the point of being ready to deploy to JBoss and see what happened. That’s what this post is about.
Referring to class by wrong name in Spring bean file
The first time I deployed with all the Oracle/Hibernate stuff in place in the configuration files, I got this:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.example.persistence.SimplePersonDAO] for bean with name ’simplePersonDAO’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]; nested exception is java.lang.ClassNotFoundException: com.example.persistence.SimplePersonDAO
This was because in my new Spring bean file containing the Hibernate stuff I was simply referring to the class under the wrong name — in the other project it was in a persistence package, but now it’s in a db package.
Can’t find Hibernate LocalSessionFactoryBean class
Correcting that, I redeployed and got this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’simplePersonDAO’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]: Cannot resolve reference to bean ’sessionFactory’ while setting bean property ’sessionFactory’; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.hibernate3.LocalSessionFactoryBean] for bean with name ’sessionFactory’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.LocalSessionFactoryBean
Related cause: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.hibernate3.LocalSessionFactoryBean] for bean with name ’sessionFactory’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.LocalSessionFactoryBean
(emphasis mine). Ah – looks like it’s time to add spring-orm to the pom file.
Missing translator
Redeploying, now we get:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’simplePersonDAO’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]: Cannot resolve reference to bean ’sessionFactory’ while setting bean property ’sessionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’sessionFactory’ defined in class path resource [com/example/db/spring-SimplePersonDAO.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/springframework/jdbc/support/SQLExceptionTranslator
Well, what do you know? Browsing our Artifactory, there is a spring-jdbc maven artifact. Let’s add that to the pom file. (I’m getting faster at this, but I do wonder how many more of these issues there will be!)
No JTA UserTransaction available, nor diagnosability mbean neither
No JTA UserTransaction is available, and no Diagnosability MBean either — yet somehow the world still turns… ;)
Oracle JDBC Diagnosability MBean
For the diagnosability mbean, it looks like the Oracle JDBC driver was really hoping it would be there:
16:11:44,567 ERROR [STDERR] Jul 24, 2008 4:11:44 PM oracle.jdbc.driver.OracleDriver registerMBeans
SEVERE: Error while registering Oracle JDBC Diagnosability MBean.
javax.management.MalformedObjectNameException: Invalid character ‘
‘ in value part of property
I bet the error is because I commented out the mbean element in the oracle-xa-ds.xml datasource configuration file. It doesn’t look fatal though, so let’s look on to the next error:
No JTA UserTransaction available
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘messageListener’ defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘txAdvice’: Cannot resolve reference to bean ‘transactionManager’ while setting bean property ‘transactionManager’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘transactionManager’: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No JTA UserTransaction available - specify either ‘userTransaction’ or ‘userTransactionName’ or ‘transactionManager’ or ‘transactionManagerName’
I think here, I’m getting into trouble because of the way I contributed my two Spring bean files. I contributed them as peers, roughly like this:
new ClassPathXmlApplicationContext(new String[] { "com/example/db/spring-SimplePersonDAO.xml", "applicationContext.xml" });
Now, the Javadoc for ClassPathXmlApplicationContext says this:
Note: In case of multiple config locations, later bean definitions will override ones defined in earlier loaded files. This can be leveraged to deliberately override certain bean definitions via an extra XML file.
So since the applicationContext.xm has a transactionManager bean that I want the spring-SimplePerson.xml beans file to see, I think at the least I need to reverse the order of those bean files in the array so that the parent one comes first. So now my code looks roughly like this:
new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml", "com/example/db/spring-SimplePersonDAO.xml" });
Explicitly specify the parent?
It’s possible I should make two calls to ClassPathXmlApplicationContext so I’m explicitly specifying that applicationContext.xml is the parent context, like this:
ClassPathXmlApplicationContext parentContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext childContext = new ClassPathXmlApplicationContext("com/example/db/spring-SimplePersonDAO.xml", parentContext);
But I think I want to try this simpler way first.
Still the JTA UserTransaction error
Hmm… still the same error. Guess that’s where we’ll start tomorrow, Lord willin’.