Set Up Spring and Hibernate Configuration

OK, we do still need some XML configuration for this project.  In our web.xml file, we identified a Spring configuration file that will reside in /src/main/resources/spring/dispatch-servlet.xml.  Let’s go over that file now.

/src/main/resources/spring/dispatch-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <context:annotation-config />

    <context:component-scan base-package="com.technologicaloddity.departments"/>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
      <property name="url"><value>jdbc:mysql://localhost:3306/departments</value></property>
      <property name="username"><value>root</value></property>
      <property name="password"><value></value></property>
      <property name="initialSize">
          <value>2</value>
      </property>
      <property name="maxActive">
          <value>5</value>
      </property>
      <property name="maxIdle">
          <value>2</value>
      </property>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" destroy-method="destroy">
        <property name="annotatedClasses">
            <list>
                <value>com.technologicaloddity.departments.model.Employee</value>
                <value>com.technologicaloddity.departments.model.Department</value>
            </list>
        </property>
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>    

<!-- TRANSACTION MANAGER -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

<!-- ANNOTATION DRIVEN TRANSACTIONS -->
    <tx:annotation-driven transaction-manager="transactionManager" />

</beans>

Here is the line-by-line break down:

  • Lines 1-10: This is the Spring XML namespace declaration. We’ve included the default Spring namespace (beans), the aop (aspect oriented programming) namespce, the tx (transaction) namespace, and the context namespace.
  • Line 12: The annotation-config line tells Spring that we are going to use annotations.
  • Line 14: Component-scan tells Spring where to look for annotated components of our webapp.  In our case, it is package “com.technologicaloddity.departments” and all of the subpackages.
  • Lines 16-27: This is a standard Spring view resolver.  The resolver here is a common one: given view name “foo”, look for the actual view file in “WEB-INF/jsp/foo.jsp”.
  • Lines 29-43: The datasource bean tells Spring how to connect to our MySQL instance. There should be any surprises here if you are used to JDBC.  There is a driver name, the username and password, a JDBC URL to our departments database (from above) and an initial, max, and idle connection pool size.  The Pool is managed by dbcp’s BasicDataSource from our Maven Dependencies above. (Note: If you are using a database other than MySQL, this is section and the Hibernate dialect below should be the only changes you need to make.)
  • Lines 45-59: This defines a Hibernate Session Factory. You can think of this as the place that Hibernate holds objects that it manages while they are in use.  Since we are using annotations to define entities in our project, we are using a special kind of Session Factory called an “AnnotationSessionFactoryBean”.  As you may have guessed this allows us to use annotations for configuration.  Next is a list of our annotated classes, of which we have two: Employee and Department.  Then we need to tell Hibernate which datasource we want to use.  We choose the datasource bean we created directly above.  Finally, we want to set two Hibernate properties: hibernate.dialect, which helps Hibernate optimize SQL for your database vendor (MySQL in our case), and hibernate.hbm2ddl.auto = update, which allows Hibernate to create (and update) the database schema for our objects.  What does that mean in English? Yes, Hibernate will automatically create tables and their schemas on MySQL for you.  No SQL files required.  How cool is that?  There are other Hibernate properties out there that you can set.  Look on the hibernate.org site for details on all the options (there are LOTS)
  • Lines 61-64: The Transaction Manager is needed to track the start and end of database transactions.  Spring comes with its own transaction manager specifically for Hibernate, which we are using here.
  • Line 67: Here we tell Spring that we are going to manage Transactions through annotations (and we will have a @Transactional annotation in this project, so we need this).

For completeness, there is one more configuration file.  In the web.xml file, we defined a Log4J configuration file, which will be located at /src/main/webapp/WEB-INF/log4j.properties.  We will just use a simple “log to the console” configuration for this project.

/src/main/webapp/WEB-INF/log4j.properties

# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
log4j.rootLogger=ALL, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyMMdd HH:mm:ss}|%-5p|%40.40c|%X{user}|%m%n

log4j.logger.org.apache=INFO
log4j.logger.org.springframework=INFO

Pages: 1 2 3 4 5 6

20 Responses to “Spring and Hibernate with Annotations”

  1. Excellent tutorial! Very high quality, it all works beautifully, and very well explained. Thanks for putting it all together. I’ve tried some other similar tutorials before this but none worked. I was using Spring STS as my dev env, and it was fine, with a little change in the initial project setup.

    Only very minor comment is that jsp directory is not usually inside WEB-INF, but alonside it in webapp directory. As I said, this is very minor, viewed against a small mountain of very well designed/executed code.

    All the best
    Noel

  2. Wow! Great Tutorial. I’m just in the process of absorbing everything now. The “step by step” code explanation is great for beginners like me. This has got to be the best maven+spring+hibernate tutorial I have come across yet (and I must have seen them all)

    • Also, it wasn’t working for me at first. I was getting errors like:

      annotations are not supported in -source 1.3
      (use -source 5 or higher to enable annotations)

      I found that Maven’s default java compiler version is 1.3, and even if you don’t have it installed, you’ll still get the above errors unless you explicitly change this by adding the following code within in pom.xml:

      org.apache.maven.plugins
      maven-compiler-plugin
      2.3.2

      1.5
      1.5

  3. Great tutorial and I learned a lot from this

    I made some changes (Oracle / combined jdbc.properties into the Spring config file etc) and it all works fine

    Then I tried to add some unit tests, but changed the MappedModelDao to implement an interface (extracted through Eclipse) – as explained in
    http://zenoconsulting.wikidot.com/blog:8#toc9

    As soon as I did this, and rebuilt the war, it failed to start in Tomcat with the following exception:

    SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘deletionController’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.technologicaloddity.departments.dao.DepartmentDao com.technologicaloddity.departments.controller.DeletionController.departmentDao; nested exception is java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1055)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:289)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:286)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:188)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:558)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416)
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5204)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5199)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.technologicaloddity.departments.dao.DepartmentDao com.technologicaloddity.departments.controller.DeletionController.departmentDao; nested exception is java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:504)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:280)
    … 21 more
    Caused by: java.lang.IllegalArgumentException: Can not set com.technologicaloddity.departments.dao.DepartmentDao field com.technologicaloddity.departments.controller.DeletionController.departmentDao to $Proxy21
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
    at java.lang.reflect.Field.set(Field.java:657)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:500)
    … 23 more

    Also, I got a similar exception when trying to run a simple JUnit test in Eclipse
    My Spring knowledge is limited, so any help as to what the problem might be would be appreciated
    Thanks

  4. it works with postgres with quite minimal changes, just add the dependency for the jdbc connector for postgres to pom.xml and change jdbc driver class(dispatch-servlet.xml) to postgres(org.postgresql.Driver) and the db url(to something like jdbc:postgresql://localhost:5432/database ).

    great tutorial, better than most other spring and hibernate tutorials on the net! simple working approach that doesn’t need table creation by hand(so simpler to adapt to postgresql).

  5. Sunil Bhambani says:

    Hi,

    This is probably one of the best tutorial that I came across.

    Just one thing, why there is no service layer added in the code or shown. Most of the enterprise applications do have a Service Layer for interacting with DB, I guess.

    Thanks & Regards
    Sunil

  6. Sunil Bhambani says:

    One more thing, I have to include the servlet dependency in pom file otherwise the project was not getting run and giving error as “Cannot find class file for javax/servlet/ServletContext”.

    Regards
    Sunil

  7. U truly created a number of outstanding stuff within ur article, “Spring and Hibernate with Annotations | Technological
    Oddity”. I may possibly be coming to ur site soon.
    Thanks a lot ,Steve

  8. Now that I’ve just devoted six hours on your website reading your posts, I’m hooked on your blog.
    I bookmarked it as well so that I can keep up with it on a regular basis.
    Have a look at my web site too and tell me what you think.

  9. Wonderful website. A lot of useful information here. I’m sending it to a few buddies ans also sharing in delicious. And obviously, thanks on your sweat!

  10. Heya i am for the first time here. I came across this board and I find It really useful & it helped me out a lot.
    I hope to give something back and aid others like you helped
    me.

  11. Great post however I was wanting to know if you could write a litte more on this subject?
    I’d be very thankful if you could elaborate a little bit more.
    Appreciate it!

  12. This is very interesting, You are a very skilled blogger. I have joined your
    rss feed and look forward to seeking more of your fantastic
    post. Also, I’ve shared your sitee in my social networks!

  13. please can you tell me more about the database you have created for this project

    • Lakhan,

      I’m using a MySQL database. The database is automatically created by Hibernate, since “hibernate.hbm2ddl.auto = update” is in the hibernate.properties. So there is no SQL to show. If you have other questions, feel free to ask.

Leave a Reply

Your email address will not be published. Required fields are marked *