Spring Examples for Practice

Spring Application Framework has been in action for quite a long time, and programmers have developed several conventions, Usage patterns, and idioms during that time period.

In this example, we will try to explain some of them and give examples to Illustrate how to apply them in your projects.

Let’s begin.

Most of the bean definitions in Spring ApplicationContext are singleton scope, and again they are mostly sole bean definitions of their classes in the application. Developers therefore, give them names same as with their class or interface names in order to easily match with bean definitions with their classes. That way, it becomes easier to go from beans to their classes or vice versa.

public class SecurityServiceImpl implements SecurityService {

@Override
public String getCurrentUser() {
        //...
    }
}

<bean id="securityService" class="com.example.service.SecurityServiceImpl">
...
</bean>

If you place xml configuration files under root class path, and create a jar then, Spring might fail to discover those xml bean.

Configuration files within jar file, if they are loaded with wildcards like below.

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/beans-*.xml</param-value>
    </context-param>
</web-app>

If you give common prefixes or suffixes to xml bean configuration files in the application, like beans-service.xml, beans-dao.xml, beans-security.xml, beans-config.xml and so on, then it becomes easier to load those xml configuration files while creating Spring Container using wildcards as follows.

<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/appcontext/beans-*.xml</param-value>
    </context-param>
</web-app>

Spring XML based configuration offers element to include bean definitions within another xml file. However, you should use element wisely. If you use it within several different places in your xml configuration files, it becomes difficult to grasp big picture of the system configuration and get confused about bean definition overrides as well.

Instead, either prefer loading xml configuration files by making use of wild cards as explained in the previous tip, or create a separate xml configuration file, whose Sole purpose is just to contain elements.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans 
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/appcontext/beans-controller.xml"/>
<import resource="classpath:/appcontext/beans-service.xml"/>
<import resource="classpath:/appcontext/beans-dao.xml"/>
</beans>

Mixing auto wiring with explicit setter or constructor injection in xml bean definitions might cause confusion and make it harder to grasp the big picture in the application. Therefore, either make use of auto wiring in all of your bean definitions throughout the application, or stick with the explicit dependency injection definitions.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans 
https://www.springframework.org/schema/beans/spring-beans.xsd" 
default-autowire="byType">
...
</beans>

Instead of placing hard coded values in bean definitions, place property placeholder variables in place of actual values. That way, it will be easier to customize system configuration according to the target runtime environment without requiring any modifications in the bean configurations.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/beans 
https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context 
https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${dataSource.driverClassName}"/>
        <property name="url" value="${dataSource.url}"/>
        <property name="username" value="${dataSource.username}"/>
        <property name="password" value="${dataSource.password}"/>
    </bean>
    <context: property-placeholder location="classpath:application.properties"/>
</beans>

Namespaces are introduced into Spring in order to simplify complex bean configurations, and enable Spring features in a more natural way. You need to add namespace XSD into xml configuration files in order to make use of namespace elements available in Spring modules as follows.

spring namespace xsd versions

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

Spring introduces new namespace elements in each new version, and if you place Spring version number in namespace XSD, you will be missing new features introduced in the upcoming Spring releases.

If you exclude version number in the XSD, its current version is enabled, and whenever you upgrade Spring version in the project, latest namespace elements of Spring modules will be available without any other extra effort.

Unless you place resource type prefix in your resource paths, type of the Spring ApplicationContext determines the location from where those resource paths will be resolved.

<context:property-placeholder location="application.properties"/>

For example, in the above configuration application.properties file, placed into classpath will be looked up from classpath when.

ApplicationContext is created during Spring integration tests, and it will be loaded without any problem. However, when it comes to load it during bootstrap of the web application, Spring WebApplicationContext will attempt to resolve it from context root instead of classpath, and therefore will fail. Hence, it is almost always better to place your resources somewhere under classpath and place classpath: prefix in front of their paths.

<context: property-placeholder location="classpath: application.properties"/>

Spring supports field level injection in addition to setter and constructor injection methods. However, you will need those setters when you attempt to unit test those classes. Hence, it is still important to create setter methods even though you place.

@Autowired on top your attributes.
@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    public void setSecurityDao(SecurityDao securityDao) {
        this.securityDao = securityDao;
    }
}

Creating a separate service layer and service classes almost always pays off in the long term even though service methods merely delegate their responsibilities to their DAO counterparts.

In the beginning, your system might look like so simple and a separate service layer might look useless.

However, it is still useful to create a separate service layer as many of Spring features like transaction management, method level security, and method level caching or service method parameter validations best suit to that service layer. If you start with a separate service layer from the beginning, it will be simply a matter of applying related annotations to enable those features in the application.

@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    public void setSecurityDao(SecurityDao securityDao) {
        this.securityDao = securityDao;
    }
    @Transactional (readOnly=true)
    @Override
    public User findUserByUsername(String username) {
        return securityDao.findUserByUsername();
    }
}

Spring annotation based configuration offers several annotations, like @Controller, @Service , @Repository and so on. They all inherit from @Component annotation as well. Although it is possible to create beans with only using @Component annotation, you will be missing some functionality which becomes available on your beans when they are defined with appropriate stereo type annotations.

For example, @Repository annotation helps handling of Hibernate or JPA specific exceptions and converting them into Spring specific DataAccessExceptions. @Controller annotation signals to DispatcherServlet that, it contains handler methods with @RequestMapping annotation. Although @Service annotation doesn’t make all of the public methods transactional in a service bean - like session beans in EJBs, it is just a matter of defining an annotation which brings those @Service and @Transactional annotations together, or write an aspect to achieve similar behavior.

@Controller
public class SecurityController {
    private SecurityService securityService;
    @Autowired
    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }
    //...
}
@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    //...
}
@Repository
public class HibernateSecurityDao implements SecurityDao {
    private SessionFactory sessionFactory;
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    //...
}

You should place Spring annotations only over classes, their fields or methods, not on interfaces or methods declared within them, as Java doesn’t allow annotations placed on interfaces to be inherited by the implementing classes.

Default rollback behavior for @Transactional annotation is to commit when a checked exception is thrown from within a transactional method, instead of rollback, as opposed to its counterpart, unchecked exceptions, which cause rollback by default.

However, most of the time developers need rollback behavior for checked exceptions as well. Therefore, they override default rollback behavior, whenever they throw checked exceptions and want to cause rollback.

Instead of repeating this step each time for your transactional service methods, it will be much safer to throw unchecked exceptions from within those service methods.

@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    @Override
    public User findUserByUsername(String username) {
        User user = securityDao.findUserByUsername ();
        if(user == null) throw new UserNotFoundException(
                    "User not found :" +  - username);
    return user;
    }
    //...
}

The place to demarcate transactions in a Spring enabled application is service layer, nowhere else. You should only mark @Service beans as @Transactional or their public methods.

@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    @Override
    @Transactional(readOnly=true)
    public User findUserByUsername(String username) {
        //...
    }
    @Override
    @Transactional
    public void createUser(User user) {
        //...
    }
    @Override
    @Transactional
    public void updateUser(User user) {
        //...
    }
    @Override
    @Transactional
    public void deleteUser(User user) {
        //...
    }
}

You can still place @Transactional with propagation=Propagation. MANDATORY over DAO classes so that they wouldn’t be accessed without an active transaction at all.

In order to be able to use Hibernate contextual session capability, you need to start a transaction even for select operations. Therefore, you even mark your finder methods with @Transactional annotation in service beans. However, at the end of the finder method, transaction is committed, and Hibernate session flush will be triggered via that commit.

Hibernate flush is an expensive operation, which traverses all those entities existing in the Hibernate Session, and try to detect dirty entities within it.

Such a dirty checking step obviously becomes unnecessary when we only perform select queries. Turning flush mode to manual prevents automatic flushing at the end of the transaction commit, and this will bring us a slight performance improvement, in addition to preventing unintended data modifications in the application.

@Service
public class SecurityServiceImpl implements SecurityService {
    @Autowired
    private SecurityDao securityDao;
    @Override
    @Transactional(readOnly=true)
    public User findUserByUsername(String username) {
        //...
    }
    //...
}

Do not use DriverManagerDataSource

DriverManagerDataSource class is mostly used one to exemplify dataSource bean configurations throughout Spring related examples. However, DriverManagerDataSource causes a new physical connection to be opened each time you ask for an SQL Connection from it, as it doesn’t have a pooling mechanism.

It is suitable only for development or testing environments. You should not use it in production environment. Instead you should either access dataSource bean configured within your application server via JNDI, or include an open source connection pooling library, like C3PO, Apache Commons DBCP or Hikari, and get connections through that connection pool.

<jee:jndi-lookup jndi-name="java:comp/env/jdbc/myDS" id="dataSource"/<

Either use NamedParameterJdbcTemplate or JdbcTemplate for your JDBC operations

Spring Data Access module provides two high level helper classes, JdbcTemplate and NamedParameterJdbcTemplate. You should use either one of them to perform any of your JDBC operations, instead of getting dataSource bean and opening up JDBC connections manually.

Those template method based classes handle most of the repetitious code blocks internally, and relieves us from managing JDBC connections by ourselves. They also simplify combining ORM operations with native JDBC ones in the same transaction.

@Repository
public class JdbcSecurityDao implements SecurityDao {
    private JdbcTemplate jdbcTemplate;
    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>

Use SessionFactory and EntityManager directly in your DAO beans

Before introduction of contextual session capability of Hibernate, Spring had provided HibernateTemplate helper class, similar to JdbcTemplate to simplify ORM operations inside DAO classes. The other class provided by Spring was HibernateDaoSupport for DAO classes to extend from for similar purposes.

However, with the introduction of contextual session capability, working with Hibernate has been greatly simplified, and reduced to injecting SessionFactory into DAO beans, and calling getCurrentSession() to access transactional current Session to perform persistence operations. Therefore, prefer that type of usage within your DAO beans instead of cluttering them with an additional helper or base class.

@Repository
public class HibernateSecurityDao implements SecurityDao {
    private SessionFactory sessionFactory;
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    public User findUserByUsername(String username) {
        return sessionFactory.getCurrentSession()
        .createQuery("from User u where u.username = :username")
        .setParameter("username", username).uniqueResult();
    }
}