Gaurav Aggarwal

4 Best Practices To Be Followed For A Spring Based Web Project

Hi Friends, I am gonna try and write some useful tips regarding a simple Spring based web project. Recently, I got a chance to develop a complete web project from scratch using Spring. And then came the time, when I thought..Ohhh A complete web app from scratch??? What are the things that I am gonna include into it and what not…which logging framework? What are the best practices in writing Spring configuration files? What’s gonna be the project structure? And the questions continued…The more I thought of it… the more puzzled I got.

So, I decided to note down all those questions at one place and tried to find the best answers for them. I have jotted down all the research that helped me a lot for writing my first Spring based web project.

  1. What should be the project structure?
    So this is what I came up with:

Production

  • src/main/java – Java Source code packages and classes
  • src/main/resources – NON-Java Resources, such as property files and Spring configuration

Test

  • src/test/java – Test Source code packages and classes
  • src/test/resources – NON-Java Resources, such as property files and Spring configuration

property files and Spring configuration

  1. What about logging??? Which logging framework? Do I actually require any framework..what if I use simple java.util.logging??? Hmm lots of questions…
  • No to System.out or System.err
  • No to Apache Commons Logging (JCL) aka Jakarta Commons Logging
  • No to Java Util Logging (JUL)
  • ALWAYS use SLF4J

Classes that need to log messages should include the following config for SLF4J (not log4j, not apache logging, not java util logging). See the sample below:

config for SLF4J

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.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>

  1. What about Spring Configuration Files?
    Be consistent with naming Spring xml configuration files. Start all files with the same name such as applicationContext*.xml. For example: applicationContext.xml, applicationContext-jpa.xml, applicationContext-security.xml, etc.

Config Directories

  • src/main/resources/META-INF/spring/applicationContext*.xml – Spring XML configuration directory
  • src/main/webapp/WEB-INF/spring/<appname>-servlet.xml – Spring MVC configuration directory

Some Important points to remember while writing configuration files:

  • Always good to provide header comment for each file you create.
    Example:
    <beans>
    <description>
    This configuration file will have all beans
    which will be used for initializing the application.
    </description>

    </beans>
  • Do not specify version numbers in Spring schema references.

In every configuration file, you must have seen the header where you specify the schema references for various spring modules. In schema references, we mention the xml namespace and as well as it’s version number.Do we actually need the versions??? NO.
Spring automatically picks the highest version available from the project dependencies. Just don’t provide the versions.
Example:

<?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:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                         http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Other bean definitions-->
</beans>

 

This should be written as:

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

<!-- Other bean definitions-->
</beans>
  • Always use classpath prefix

When importing resources, XML config, properties, etc. Always use the classpath: or classpath*: prefix. This will provide consistency and clarity to the location of the resource.
Example:
<context:property-placeholder location=”classpath*:META-INF/spring/*.properties”/>

This will automatically locate any and all property files you have within your classpath, provided they fall under the META-INF/spring directory. The located property files are parsed and their values can then be used within application context files in the form of ${propertyKey}
Do not hardcode xml property values in configuration files. Use property files instead. Example:

<bean class=”org.apache.commons.dbcp.BasicDataSource” destroy-method=”close” id=”dataSource”
p:driverClassName=”com.mysql.jdbc.Driver”
p:driverClassName=”${jdbc.driverClassName}”
p:username=”${jdbc.username}”
p:password=”${jdbc.password}”
p:testOnBorrow=”true”
p:testOnReturn=”true”
p:testWhileIdle=”true”
p:timeBetweenEvictionRunsMillis=”1800000″
p:numTestsPerEvictionRun=”3″
p:minEvictableIdleTimeMillis=”1800000″
p:maxIdle=”3000″
p:validationQuery=”SELECT 1″ />

/* file://jdbc.properties */

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=password

  1. What about unit testing???

Implementing Junit using Mockito framework

Sometimes, It is important to be able to perform some junit testing without the need of deploying the application server or connecting to other enterprise infrastructure and database. This is required to create mock calls to the application which does not have any effect on the database.

Preparation of testing with Mockito

To make Mockito available, we need to add following dependency in the pom.xml file.

 Preparation of testing with Mockito
The code source below depicts a JUnit test using Spring-test and Mockito framework.

  • @RunWith(MockitoJUnitRunner.class)
    It is used to Initialize mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary. Mocks will be initialized before each test method.
  • when(.(any())).thenAnswer() provides option to mock the method call and return result as per the requirement. This can be done to mock the database call.
  • given(dao.updateTableInfo()).willReturn(<Object>) This will mock the database call and you can return any object as per your requirement.

This will mock the database call