Tuesday, September 29, 2015

Spring + Hibernate + Wildfly: Finding the right match

While setting up a new project, I had to do a bunch of trial-and-error, in order to get the WAR package deployable on the application server. These are my findings thus far:
  • Application Server: Wildfly 9.0.1.Final (formerly known as JBoss AS7)
  • Application Framework: Spring 4.2.1.RELEASE
    • spring-context
    • spring-webmvc
    • spring-orm
  • ORM Framework: Hibernate 4.3.11.Final
    • hibernate-core
    • hibernate-c3p0
    • hibernate-ehcache
Here are some of the problems I'd encountered, that I had to tackle as they appeared:
  1.  java.lang.IllegalStateException: Could not locate SessionFactory in JNDI
    • sessionFactoryName
      • Ensure your hibernate.cfg.xml has these properties
        • <session-factory name="mySessionFactory">
        • hibernate.jndi.url
        • hibernate.jndi.sessionFactoryName
  2. org.dom4j.DocumentFactory cannot be cast to org.dom4j.DocumentFactory
    • Wildfly Administration Console > Configuration
    • Subsystems > EE > View
    • EE Subsystem > Global Modules
    • Add
      • Name: org.dom4j
      • Slot: main (prepopulated by default)
    • Save
    • Restart Wildfly
    • What is not needed to be done:
      • Adding of "Dependencies: org.dom4j export" into MANIFEST
      • Manual removal/auto exclusion of dom4j JAR during Maven build
      • Adding META-INF/jboss-deployment-structure.xml
  3. JNDI/JDBC configuration
    • The naming conventions can get rather confusing at times, but here's what worked in Wildfly:
      • JndiObjectFactoryBean > jndiName = java:/jdbc/myDataSource
      • Wildfly Admin Console > Configuration
        • Subsystems > Datasources > View
        • Configure your datasource 
        • Ensure the JNDI name matches "java:/jdbc/myDataSource"
        • Note that Wildfly requires the "java:/" prefix
      • Edit: I have concluded that this is in fact no required as long the datasource name matches across your servlet-context.xml and the server configuration. Include this snippet in your web.xml
        • <resource-ref>
              <res-ref-name>jdbc/msbDataSource</res-ref-name>
              <res-type>javax.sql.DataSource</res-type>
              <res-auth>Container</res-auth>
          </resource-ref>
  4. org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]
    • This led me to this
    • In short, I had to configure the hibernate.cfg.xml to factor in settings for c3p0 as indicated
    • Meanwhile, I also noticed that my Hibernate versions were all over the place;
    • Adventurously, I experimented with Hibernate 5, or more specifically org.springframework.orm.hibernate5.HibernateTransactionManager to which came the complain from Wildfly: NoSuchMethodError ConnectionProviderInitiator.extractIsolation
    • This was when I decided to take a step back and 
      • reverted from Hibernate 5 to Hibernate 4;
      • and added dependency and configuration for c3p0;
    • Edit: I have isolated the cause of this occurrence during the Eclipsed Embedded Jetty deployment to be due to the presence of the "hibernate.connection.datasource" property in my hibernate.cfg.xml that seemingly requires the c3p0 set of properties. In short, don't bother including hibernate.connection.datasource since you will either already have it configured in the application server (e.g. Wildfly) or the jetty-env.xml file.
  5. Configuration for application context path 
    • This one was fairly straightforward:
    •  Create WEB-INF/jboss-web.xml with the following:
      <?xml version="1.0" encoding="UTF-8"?>
      <jboss-web>
         <context-root>/myapp</context-root>
      </jboss-web>
My exploration continues...