Search code examples
hibernatespring-mvcspring-java-config

Spring XML Config to Java Config


In my current app, I have done xml configurations on Spring Servlet and Hibernate; and it works as I want. However, look at the xml files, I don't really understand and it is quiet a challenging for future developing. Hence, I want to translate it to Java Configuration. But again, looks at my configuration xml files and follow the information of this guide make me so confused. So would anyone help me to bootstrap my application?

This is my root-context.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"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

servlet-contenxt.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    /*Omit some code here*/   >


<context:component-scan base-package="com.core.domain" />
<context:component-scan base-package="com.core.dao.generic" />
<context:component-scan base-package="com.core.dto" />
<context:component-scan base-package="com.web.page" />

<mvc:annotation-driven />
<mvc:default-servlet-handler/>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/views/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

<bean id="sessionFactory" scope="singleton"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>

<bean id="multipartResolver" 
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id ="transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>   

This is my hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/database</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.connection.password">password</property>
        <property name="connection.pool_size">1</property>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>   
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
        <property name="show_sql">true</property>

        <property name="hibernate.jdbc.batch_size">50</property>

        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">600</property>
        <property name="hibernate.c3p0.timeout">1800</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">1800</property>


        <property name="hbm2ddl.auto">update</property>


        <!-- Resources mapping --> 
        <mapping class="com.common.domain.Account"/>
    </session-factory>
</hibernate-configuration>

Right now, I only able to get rip of some config in web.xml with the following javaConfig bootstrap. The bootstrap still have to read the servlet-context.xml and I try to translate it to java code but unable to do so yet.

public class Bootstrap implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container)
            throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(RootContextConfiguration.class);
        container.addListener(new ContextLoaderListener(rootContext));


        XmlWebApplicationContext servletContext = new XmlWebApplicationContext();
        servletContext.setConfigLocation("classpath:servlet-context.xml");

         ServletRegistration.Dynamic dispatcher = container.addServlet(
                            "SpringDispatcher", new DispatcherServlet(servletContext));

         dispatcher.setLoadOnStartup(1);
         dispatcher.addMapping("/");
    }

and for Hibernate Persistence Config:

public class PersistenceConfig {

    @Autowired
    private Environment env;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        System.out.println("Create SessionFactory");
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(restDataSource());
        sessionFactory.setPackagesToScan(new String[] {
                    "com.common.domain.Account"
        });
        sessionFactory.setHibernateProperties(hibernateProperties());

        return sessionFactory;
    }

    @Bean
    public DataSource restDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("org.postgresql.Driver"));
       dataSource.setUrl(env.getProperty("jdbc:postgresql://localhost:5432/app"));
       dataSource.setUsername(env.getProperty("username"));
       dataSource.setPassword(env.getProperty("password"));
        return dataSource;
    }

    /**
     * Setting up the hibernate transaction Manager
     * @param sessionFactory
     * @return
     */
     @Bean
     @Autowired
     public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
          HibernateTransactionManager txManager = new HibernateTransactionManager();
          txManager.setSessionFactory(sessionFactory);

          return txManager;
       }

       @Bean
       public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
          return new PersistenceExceptionTranslationPostProcessor();
       }


     Properties hibernateProperties() {
          return new Properties() {
             {
                setProperty("hibernate.dialect", env.getProperty("org.hibernate.dialect.PostgreSQLDialect"));
                setProperty("hibernate.globally_quoted_identifiers", "true");
             }
          };
       }
}

Solution

  • There are many ways of creating config files in Spring, pure XML, pure Java, or a combination of both. Assuming you want to do everything in Java, you have to let go of the web.xml and servlet-context.xml files completely. Do note, however, that there are some entries in web.xml that, AFAIK, cannot be converted into Java code.

    First, you need an initializer. The Bootstrap class you made that extends WebApplicationInitializer is one way to do it.

    Now, to convert the servlet-context.xml into Java, you should have a class (doesn't matter what name) that would look something like this:

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"com.core.domain", "com.core.dao.generic" /* OTHER PACKAGES CONTAINING @Controller */})
    @Transactional
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
    
      @Bean
      public ViewResolver jspViewResolver() {
        InternalResourceViewResolver jspViewResolver = new InternalResourceViewResolver();
        jspViewResolver.setPrefix("/WEB-INF/views/");
        jspViewResolver.setSuffix(".jsp");
        return jspViewResolver;
      }
    
      @Bean
      @Scope(value = "singleton")     /* Actually, default is singleton */
      public SessionFactory sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setConfigLocation("classpath:hibernate.cfg.xml");
        return sessionFactory.getObject();
      }
    
      @Bean
      public MultipartResolver multipartResolver() {
        return new CommonsMultipartResolver();
      }
    
      @Bean   /* This should be present when using @Transactional (see annotations above) */
      public TransactionManager tx() {
        HibernateTransactionManager tx = new HibernateTransactionManager();
        tx.setSessionFactory(this.sessionFactory());
        return tx();
      }
    
      @Override
      public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
      }
    }
    

    This would be the equivalent Java code of your servlet-context.xml. Make sure you pass this to the Initializer so that Beans can be initialized and used properly. This means you need to change the type of servletContext and pass in WebMvcConfig.class instead.

    Hope this helps.