Thursday, November 27, 2014

Spring Framework + Hibernate Integration = Best Practices


1.       Common things to remember :
     a) Don’t use version numbers with the Spring schema namespaces (Spring automatically picks the highest version available from the project dependencies (jars)).
     b) To implement thread safety use constructor injection.
     c) Use bean id attribute to identify bean(s).

2.      Classpath Prefix : -
     For applying uniformity throughout the application we just follow a convention as clsspath while importing the XML files.
e.g. classpath*:prefix
This provides consistency and clarity to the location of the resource.

3.       Configuration Files Naming Convention :-
Start all files with the same name such as applicationConfig*.xml & be consistent with Spring XML configuration files.

e.g. For example: applicationConfig-bootstrap.xml, applicationConfig-database.xml, applicationConfig-security.xml, etc.

4.   Bean Naming Conventions :-
           This is the same philosophy as for Java code. Using clear, descriptive, and consistent name conventions across the project is very helpful for developers to understand the XML configurations. For bean ID, for example, we can follow the Java class field name convention.  The bean ID for an instance of OrderServiceDAO would be orderServiceDAO. For large projects, we can add the package name as the prefix of the bean ID.

5.      Avoid using autowiring :-
      Spring can autowire dependencies through introspection of the bean classes so that we did not       have to explicitly specify the bean properties or constructor arguments. Bean properties can be autowired either by property names or matching types. Constructor arguments can be autowired by matching types. We can even specify the autodetect autowiring mode, which lets Spring choose an appropriate mechanism. As an example, consider the following:
   
<bean id="orderService" class="com.lizjason.spring.OrderService"    autowire="byName"/>

6.   Use shortcut forms :-
           The shortcut form is less verbose, since it moves property values and references from child elements into attributes. For example, the following:
 <bean id="orderService" class="com.lizjason.spring.OrderService">                                                               <property name="companyName"><value>lizjason</value></property>
          <constructor-arg>
              <ref bean="orderDAO">
          </constructor-arg>
</bean>

Can be rewritten in the shortcut form as:

<bean id="orderService" class="com.lizjason.spring.OrderService">
         <property name="companyName" value="lizjason"/>
        <constructor-arg ref="orderDAO"/>
</bean>
The shortcut form has been available since version 1.2. Note that there is no shortcut form for
                    <ref local="...">.

                    The shortcut form not only saves our some typing, but also makes the XML configuration files less cluttered. It can noticeably improve readability when many beans are defined in a  configuration file.

7.   Prefer type over index for constructor argument matching
              Spring allows us to use a zero-based index to solve the ambiguity problem when a constructor has more than one arguments of the same type, or value tags are used.

For example, instead of:
<bean id="billingService" class="com.lizjason.spring.BillingService">
        <constructor-arg index="0" value="lizjason"/>
        <constructor-arg index="1" value="100"/>
</bean>
It is better to use the type attribute like this:
<bean id="billingService" class="com.lizjason.spring.BillingService">
        <constructor-arg type="java.lang.String" value="lizjason"/>
        <constructor-arg type="int" value="100"/>
</bean>
Using index is somewhat less verbose, but it is more error-prone and hard to read compared to using the type attribute. We should only use index when there is an ambiguity problem in the constructor arguments.

8.      Reuse bean definitions, if possible :-
        Spring offers an inheritance-like mechanism to reduce the duplication of configuration information and make the XML configuration simpler. A child bean definition can inherit configuration information from its parent bean, which essentially serves as a template for the child beans. This is a must-use feature for large projects. All we need to do is to specify abstract=true for the parent bean, and the parent reference in the child bean.

For example:
           <bean id="abstractService" abstract="true" class="com.lizjason.spring.AbstractService">                           <property name="companyName" value="lizjason"/>
          </bean>

           <bean id="shippingService" parent="abstractService"  class="com.lizjason.spring.ShippingService">
                 <property name="shippedBy" value="lizjason"/>
          </bean>

The shippingService bean inherits the value lizjason for the companyName property from the abstractService bean. Note that if we do not specify a class or factory method for a bean definition, the bean is implicitly abstract.

9.      Prefer assembling bean definitions through ApplicationContext over imports :-
      Like imports in Ant scripts, Spring import elements are useful for assembling modularized bean definitions.

For example:
           <beans>
               <import resource="billingServices.xml"/>
              <import resource="shippingServices.xml"/>
              <bean id="orderService" class="com.lizjason.spring.OrderService"/>
           <beans>

However, instead of pre-assembling them in the XML configurations using imports, it is more    flexible to configure them through the ApplicationContext. Using ApplicationContext also makes       the XML configurations easy to manage. We can pass an array of bean definitions to the         ApplicationContext constructor as follows:

String[] serviceResources = {"orderServices.xml", "billingServices.xml",  "shippingServices.xml"};
ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(serviceResources);

10.  Use ids as bean identifiers :-
    We can specify either an id or name as the bean identifier. Using ids will not increase readability, but it can leverage the XML parser to validate the bean references. If ids cannot be used due to XML IDREF constraints, we can use names as the bean identifiers. The issue with XML IDREF constraints is that the id must begin with a letter (or one of a few punctuation characters defined in the XML specification) followed by letters, digits, hyphens, underscores, colons, or full stops. In reality, it is very rare to run into the XML IDREF constraint problem.

11.  Add a header comment to each configuration file :-
           It is preferred to use descriptive ids and names instead of inline comments in the XML configuration files. In addition, it is helpful to add a configuration file header, which summarizes the beans defined in the file. Alternatively, we can add descriptions to the description element.

        For example:
         <beans>
            <description>
                 This file defines billing service related beans and it depends on baseServices.xml, which       provides service bean templates...
            </description>
                   ...
          </beans>

         One advantage of using the description element is that it is easy to for tools to pick up the description from this element.

      12.   Prefer setter injection over constructor injection :-
          DI provides developers the ability to “wire together” bean relationships in configuration instead of coding the relationships.
         Spring provides three types of dependency injection: constructor injection, setter injection, and method injection. Typically we only use the first two types.

          <bean id="orderService" class="com.lizjason.spring.OrderService">
              <constructor-arg ref="orderDAO"/>
          </bean>

           <bean id="billingService" class="com.lizjason.spring.BillingService">
                <property name="billingDAO" ref="billingDAO">
           </bean>

       In the above example, orderService bean uses constructor injection, while the BillingService bean uses setter injection. Constructor injection can ensure that a bean cannot be constructed in an invalid state, but setter injection is more flexible and manageable, especially when the class has multiple properties and some of them are optional.
Spring-Hibernate Integration

Introduction:

         Spring simplifies hibernate application(s). Springs Hibernate integration uses the same generic transaction infrastructure & DAO exception hierarchy that it uses for JDBC, JDO, iBatis & Toplink. We are just mentioning some of the best practices we can use.

  1.  Hibernate is an Object/Relational Mapping framework. It maps java objects/ properties with the relational database table/ columns. It focuses on object modeling.
  2. While using Hibernate on its own need to build the SessionFactory & manage it manually.
  3. Spring provides several factory beans to create a Hibernate SessionFactory as a singleton in IOC container. This factory can be shared between multiple beans via Dependency Injection (DI).

Configuring Hibernate Session Factory:

A.      HibernateTemplate :-

1. One of the Responsibilities of HibernateTemplate is to manage Hibernate Sessions. This involves opening and closing sessions as well as ensuring one session per transaction.
2. Spring defined HibernateTemplate classes to provide template methods for different types of Hibernate Operations.
3.  HibernateTemplate is a thread-safe, so we can declare single instance of it in the bean configuration file for Hibernate & inject this instance to all DAO’s.
4.  HibernateTemplate instance requires sessionFactory property to be set.
5.  Even though HibernateTemplate is still around, it’s no longer considered the best way of working with Hibernate.

B.      HibernateDaoSupport : -(org.springframework.orm.hibernate3.support.HibernateDaoSupport)

1.  Need to extend HibernateDaoSupport to access Hibernate Data.
2. This allows to throw checked exception from DAO which is not allowed while using the HibernateTemplate callback approach.
3. Provides HibernateTemplate instance to use template based methods.

C.      Contextual sessions  :-

1.       This is introduced in Hibernate3
2.       A way in which Hibernate will manages one session per transaction.
3.       No need for HibernateTemplate to ensure behavior.
4.       This keeps DAO classes free of Spring specific code.

It is now best practice to use the Hibernate API directly instead of the HibernateTemplate, which will effectively decouple the DAO layer implementation from Spring entirely.

org.hibernate.Session is the main interface for working with Hibernate. The Session interface provides basic data access functionality such as the ability to save, update, delete, and load objects from the database.

The standard way to get a reference to a Hibernate Session object is through an implementation of Hibernate’s SessionFactory interface. Among other things, SessionFactory is responsible for opening, closing, and managing Hibernate Sessions. To get a Hibernate SessionFactory is through one of Spring’s Hibernate session factory beans. These session factory beans are implementations of Spring’s FactoryBean interface that produce a Hibernate SessionFactory when wired into any property of type SessionFactory. This makes it possible to configure our Hibernate session factory along the other beans in our application’s Spring context.

Persistent domain objects :-

1.       XML Mapping files :-

If we choose XML Mapping files then to define our object-to-database mapping in XML, we’ll need to configure LocalSessionFactoryBean in Spring.

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">                        <property name="dataSource" ref="dataSource" />                        <property name="mappingResources">                                    <list>                             <value>Spitter.hbm.xml </value>                                                </list>                         </property>                         <property name="hibernateProperties">                        <props>                                 <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>                            <prop key="hibernate.show_sql">true</prop>                                <prop key="hibernate.hbm2ddl.auto">create</prop>                         </props>                         </property> </bean><!--  This is Database Configuration --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">                        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>                        <property name="url" value="jdbc:mysql://localhost:3306/smart"/>                        <property name="username" value="root"/>                        <property name="password" value="root"/></bean>

LocalSessionFactoryBean is configuring with three properties – dataSource, mappingResources & hibernateProperties.
-          dataSource property is wired with a reference to a DataSource bean
-          mappingResources property lists one or more Hibernate mapping files that define the persistence strategy for the application.
-          hibernateProperties is where we configure the minutia of how Hibernate should operate. In this case, we’re saying that Hibernate will be working with a Microsoft SQL Server database and should use the MSSQLDialect to construct SQL accordingly.

2.       Annotations :-

While Annotation-oriented persistence, we need to use AnnotationSessionFactoryBean instead of LocalSessionFactoryBean.

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
     <propertyname="dataSource"ref="dataSource"/>   
     <propertyname="packagesToScan" value="com.habuma.spitter.domain" />
            <property name="hibernateProperties">
                        <props>
                                 <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop>
                            <prop key="hibernate.show_sql">true</prop>
                                <prop key="hibernate.hbm2ddl.auto">create</prop>
                         </props>
            </property>
</bean>

In above snippet instead of listing Hibernate mapping files, we can use the packagesToScan property to tell Spring to scan one or more packages looking for domain classes that are annotated for persistence with Hibernate. This includes classes that are annotated with JPA’s @Entity or @MappedSuperclass and Hibernate’s own @Entity annotation.
AnnotationSessionFactoryBean’s packagesToScan property takes an array of Strings specifying the packages to look for persistent classes in.

<property name="packagesToScan">
         <list>
             <value>com.habuma.spitter.domain</value>
         </list>
</property>

Also we can explicitly list out all of our application's persistent classes by specifying a list of fully qualified class names in the annotatedClasses property.

<property name="annotatedClasses">
            <list>
                   <value>com.habuma.spitter.domain.Spitter</value>
                   <value>com.habuma.spitter.domain.Spittle</value>
          </list>
</property>

The annotatedClasses property is fine for hand-picking a few domain classes. But packagesToScan is more appropriate if we have a lot of domain classes and don’t want to list them all or if we want the freedom to add or remove domain classes without revisiting the Spring configuration.

Hibernate DAO :-
            Without contextual sessions, Spring’s Hibernate templates would handle the task of ensuring one session per transaction. But now there’s no need for a template class, we can manage this by wiring a  Hibernate Session directly into DAO classes.

package com.habuma.spitter.persistence;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.habuma.spitter.domain.Spitter;
import com.habuma.spitter.domain.Spittle;


@Repository
public class HibernateSpitterDao  implements  SpitterDao  {
private SessionFactory  sessionFactory;
@Autowired
public HibernateSpitterDao(SessionFactory  sessionFactory){
            this.sessionFactory=sessionFactory;
}
Private Session currentSession(){
            return sessionFactory.getCurrentSession();
}
public void addSpitter(Spitterspitter){
            currentSession().save(spitter);
}
public Spitter getSpitterById(longid){
            return  (Spitter)currentSession().get(Spitter.class,id);
}
public void saveSpitter(Spitterspitter){
            currentSession().update(spitter);
}
}

In above example we used @Autowired annotation to have Spring automatically inject a SessionFactory into HibernateSpitterDao's sessionFactory property.
In currentSession() method, we use that SessionFactory to get the current transaction’s session.
In above example we annotated class with @Repository is springs stereotype annotation, scanned by <context:component-scan>.  This means that we won’t have to explicitly declare a HibernateSpitterDao bean, as long as we configure <context:component-scan> like so:

<context:component-scan base-package="com.habuma.spitter.persistence" />

Second thing of @Repository is, it reduces the use of  XML configuration.
To add exception translation to a template-less Hibernate DAO, we just need to add a PersistenceExceptionTranslationPostProcessor bean to the Spring application context:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

PersistenceExceptionTranslationPostProcessor is a bean post processor which adds an advisor to any bean that’s annotated with @Repository so that any platform- specific exceptions are caught and then rethrown as one of Spring’s unchecked data access exceptions.

13.  Logging :-

Generally never follow following way’s for logging,

System.out, System.err

We should always use SLF4J, Logback. Need to prohibit Apache/Jakarta Commons Logging (JCL) or Java Util Logging (JUL).

Classes that use logging should include the following config for SLF4J (not log4j, not jcl, not jul, not logback):                                               

                                           import org.slf4j.Logger;
                                import org.slf4j.LoggerFactory;

                                public class MyClass {
                                private static final Logger logger =  LoggerFactory.getLogger(MyClass.class);
                                ....
                                }

In the example below, SLF4J provides jars to route JCL and JUL logging through jcl-over-slf4j and jul-to-slf4j. Spring uses JCL, so we need to use jcl-over-slf4j to handle Spring specific logged messages.

                <properties>
                                ....
                                <logback.version>1.0.6</logback.version>
                                ...
                                <slf4j.version>1.6.6</slf4j.version>
                                ...
                </properties>
   
                ...
   
                <dependencies>
                ...
                <dependency>
                                <groupId>org.slf4j</groupId>
                                <artifactId>jcl-over-slf4j</artifactId>
                </dependency>
                <dependency>
                                <groupId>org.slf4j</groupId>
                                <artifactId>jul-to-slf4j</artifactId>
                </dependency>
                <dependency>
                                <groupId>ch.qos.logback</groupId>
                                <artifactId>logback-classic</artifactId>
                </dependency>
                ....
                </dependencies>
   
                ...
   
                <dependencyManagement>
                                <dependencies>
                                ...
                                <!-- Logging with SLF4J & LogBack -->
                                <dependency>
                                                <groupId>org.slf4j</groupId>
                                                <artifactId>jcl-over-slf4j</artifactId>
                                                <version>${slf4j.version}</version>
                                </dependency>
                <dependency>
                                <groupId>org.slf4j</groupId>
                                <artifactId>slf4j-api</artifactId>
                                <version>${slf4j.version}</version>
                </dependency>
                <dependency>
                                <groupId>org.slf4j</groupId>
                                <artifactId>jul-to-slf4j</artifactId>
                                <version>${slf4j.version}</version>
                </dependency>
                <dependency>
                                <groupId>ch.qos.logback</groupId>
                                <artifactId>logback-classic</artifactId>
                                <version>${logback.version}</version>
                </dependency>
                <dependency>
                                <groupId>ch.qos.logback</groupId>
                                <artifactId>logback-core</artifactId>
                                <version>${logback.version}</version>
                </dependency>
                <dependency>
                                <groupId>ch.qos.logback</groupId>
                                <artifactId>logback-access</artifactId>
                                <version>${logback.version}</version>
                </dependency>
                ...
                </dependencies>
                </dependencyManagement>

14.   Useful Maven Commands :- 

     a) Displays Dependency Updates :
                                > mvn versions:display-dependency-updates

     b) Displays Plugin Updates :
            > mvn versions:display-plugin-updates

     c) Displays Dependency Tree :
            > mvn dependency:tree -Ddetail

     d) Displays Dependency List :
            > mvn dependency:list

     e) Displays Effective POM :
            > mvn help:effective-pom
    
     f) Displays Project Settings :
           > mvn help:effective-settings
    
      g) Display System and Environment Variables :
             > mvn help:system
      
       h) Display Build Class Path :
             > mvn dependency:build-classpath

15.   Externalize Properties :-
  We may have different configuration values for different environments e.g. SIT, UAT, PROD etc. One of the common configurations is therefore the data source. This is most likely also the easiest to overcome, as often it is loaded from JNDI. If JNDI is not an option, there are always properties to the rescue.

There are two types of configurations,

1.       Environment specific properties :- e.g. URL’s & Database names 

These are usually injected into Spring XML files using the PropertyPlaceholderConfigurer class and the associated ${} notation.

<bean id='propertyConfigurer' class=' org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'> 
    <property name='locations'> 
        <list> 
           <value>db.properties</value> 
        </list> 
    </property> 
</bean>

2.       Environment specific bean classes :- e.g Data Sources, how we connecting to database.
      Deployment configuration requires setting environmental parameters, such as database connection properties. Since XML can be brittle, it is best to externalize settings into property files. This makes it easier for the deployment team to change resource configuration with less risk.

Spring 3.1 comes with bean definition profiles. This allows for setting a profile in our beans configuration and enables one or more of those profiles.

To apply these profiles for our data source is :-

A.  Configuration for a standalone datasource :
      <beans profile="dev">
            <jdbc:embedded-database id="dataSource" />
      </beans>

B.  Configuration for a JNDI datasource :
<beans profile="production">
     <jee:jndi-lookup id="dataSource" jndi-name="jdbc/datasource" />
</beans>

 To enable a certain profile we can set the spring.profiles.active init param on the Spring servlet in our web.xml. Now this really only helps to distinguish development and production environments. To take more fine grained control over the active profiles we can use system property spring.profiles.active.

By defining system property spring.profiles.active Spring allows us to create different beans depending on active profile name using XML configuration or @Profile annotation.
e.g. Following are some environment config files,

config_dev.properties
config_production.properties

Configuring Spring property placeholder : In order to load properties files in Spring we use 

<context:property-placeholder /> or @PropertySource annotation.

<context:property-placeholder location='classpath:config_${spring.profiles.active}.properties' /> 

Configuring Tomcat : We need instruct Tomcat which profile should be active. For this need to define System property as,
-Dspring.profiles.active=our-active-profile
To define such property we approach a good way as, create a setenv.sh / setenv.bat in Tomcat’s bin directory & will be loaded automatically during running catalina.bat/sh or run.bat/sh.
              JAVA_OPTS='$JAVA_OPTS -Dspring.profiles.active=dev'

No comments: