Enterprise Spring Framework Best Practices – Part 3 – XML Config

Enterprise Spring Best Practices Series
In part 3, Spring XML Configuration.

The best thing about Spring is that there are several way to solve a problem, the worst thing about Spring is that there are several ways to solve a problem!

One of the greatest challenges when using Spring is choosing the best way to implement solutions. As most of us developers do, we hit Google or grab books on Spring, which can get us moving in the right direction. Many times we find conflicting configurations between implementation approaches. For Spring newcomers, this can be challenging and cause grievous mental confusion down the road.


Sections




Spring Namespaces


No version numbers in schema references

Instead of:

<?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">
...
</beans>

USE This Config:

<?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">
...
</beans>

WHY?
Spring automatically picks the highest version available from the project dependencies (jars). As a project evolves, the Spring version will be updated, we won’t have to maintain all the XML config files to see the new features.



One Bootstrap XML File



There are many examples of using multiple XML configuration files. An application usually has several XML configuration files, but there should only be ONE bootstrap file. This bootstrap file should use the <import resource=""/> to include other config files.



Classpath Prefix



Always use classpath: prefix
When importing resources, XML config, properties, etc. Always use the classpath: or classpath*: prefix.
This provides consistency and clarity to the location of the resource. Not every feature of Spring behaves the same, classpath: guarantees consistency.
The classpath is determined by the build tool and IDE. Usually this is src/main/java for java code, src/main/resources for non-java dependencies and for tests, src/test/java for java code and src/test/resources for non-java resources.

Example:

<import 
  resource="classpath:/META-INF/spring/applicationContext-security.xml"/>



Bean Naming



The Spring Context is the container for the application’s beans. Each bean is uniquely identified by its name. The xml attribute “id” is most commonly used to define the bean’s name. The “id” attribute is great because it is, by XML Law, unique per file.

<bean id="accountService"
  class="com.gordondickens.services.AccountService/>

However, if we want to use special symbols in the name or provide aliases to the name, we can use the Spring provided “name” attribute.

<bean name="accountService,services/account" 
  class="com.gordondickens.services.AccountService/>

Spring 3.1 added the profile feature, providing the ability to configure beans by category or region.
With 3.1, Spring overloads the XML “id” attribute allowing multiple beans with the same “id” in an XML file by profile.

<?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 profiles="dev,qa">
    <bean id="dataSource" class="..."/>
    <bean id="messagingProvider" class="..."/>
  </beans>
  
  <beans profiles="prod">
    <bean id="dataSource" class="..."/>
    <bean id="messagingProvider" class="..."/>
  </beans>
</beans>

For more detail on Spring 3.1 profiles, see my blog Spring 3.1 Environment Profiles



Dependency Injection



Dependency Injection is one of the basic tenets of the Spring Framework. DI provides developers the ability to “wire together” bean relationships in configuration instead of coding the relationships.

The two ways to perform di are either by Constructor injection or Setter Injection.

In Enterprise Spring Best Practices – Part 2 – Application Architecture, describes the layered application approach. In this layered approach, we can expect to inject beans together between layers.
For example, wiring from the bottom up:

  1. DataSource, the common JDBC class for database connectivity, is injected into our persistence beans
  2. The persistence beans are injected into our service beans
  3. The service beans are injected into our controller beans

Constructor Injection

Constructor injection is performed using the <bean/> node <constructor-arg.
Thread safety, is a strong case for using constructors. Making beans immutable, is the cheapest thread-safety we can code.

In the following example, we see configuration of an in-memory HSQLDB database with an “id” of “dataSource”. The bean AccountRepositoryImpl bean is injected with this implementation when Spring starts.

<bean id="accountRepository"
  class="com.gordondickens.repository.internal.AccountRepositoryImpl">
  <constructor-arg ref="dataSource"/>
</bean>

<!-- Spring's In-Memory DB Config, using HSQLDB -->
<!-- Note the HSQLDB driver must be in the project dependencies -->
<jdbc:embedded-database
  id="dataSource" type="HSQL">
  <jdbc:script
    location="classpath:/mySchema.sql"/>
  <jdbc:script
    location="classpath:/mySampleData.sql"/>
</jdbc:embedded-database>

Setter Injection

Setter injection, provides the capability of injecting beans via a setter method. Traditionally, this has been the preferred choice for many developers, because the configuration is easier to read.

<bean id="accountRepository"
      class="com.gordondickens.repository.internal.AccountRepositoryImpl">
  <property name="dataSource" ref="dataSource"/>
</bean>



Third Party Beans



Any Java class can be used in the Spring framework. Infrastructure beans, such as ActiveMQ’s ConnectionFactory or Oracle’s OracleDataSource is possible.

Third party beans, where we don’t have the source, or do not wish to tamper with the source, the choice for DI is made for us.



Externalize Properties



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 provides a PropertyPlaceholderConfigurer for that purpose.

Property Replacement Config

<context:property-placeholder
  location="classpath*:META-INF/spring/*.properties"/>

<bean id="dataSource"
  class="org.apache.commons.dbcp.BasicDataSource"
  destroy-method="close">
  <property name="driverClassName"
    value="${database.driverClassName}"/>
  <property name="url"
    value="${database.url}"/>
  <property name="username"
    value="${database.username}"/>
  <property name="password"
    value="${database.password}"/>
</bean>

Properties File

database.driverClassName=org.hsqldb.jdbcDriver
database.url=jdbc\:hsqldb\:mem\:mydb
database.username=sa
database.password=



Logging Beans



Following up on Enterprise Spring Best Practices – Part 1 – Project Configuration logging configuration.

Java Util Logging

To Enable handling of java.util.logging classes with SLF4J. Register the following in your Spring configuration:

<!-- Enable handling of java.util.logging through SLF4J -->
<bean id="slf4JBridgeHandler" class="org.slf4j.bridge.SLF4JBridgeHandler"
  init-method="removeHandlersForRootLogger"/>
<bean class="org.slf4j.bridge.SLF4JBridgeHandler"
  init-method="install"
  depends-on="slf4JBridgeHandler"/>

System.out and System.err

To Enable handling of System.out and System.err messages. Register the following in your Spring configuration:

NOTE: This is NOT recommended for ongoing development, but for migrating poor code to use logging.

<!-- System.out.println & System.err.println handling through SLF4J -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetClass" value="uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J"/>
  <property name="staticMethod"
      value="uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4J.sendSystemOutAndErrToSLF4J"/>
  <property name="arguments">
    <list>
      <!-- Set log level for System.out -->
      <util:constant 
        static-field="uk.org.lidalia.sysoutslf4j.context.LogLevel.DEBUG"/>
      <!-- Set log level for System.err -->
      <util:constant
        static-field="uk.org.lidalia.sysoutslf4j.context.LogLevel.ERROR"/>
    </list>
  </property>
</bean>

Maven Dependency for SysOutOverSLF4J

<dependency>
  <groupId>uk.org.lidalia</groupId>
  <artifactId>sysout-over-slf4j</artifactId>
  <version>1.0.2</version>
</dependency>



Best Practices


  • DO NOT use version numbers with the Spring schema namespaces
  • Always use classpath:/ prefix for consist resource referencing
  • Always use a single XML config file to bootstrap the application or tests
  • Use the XML “id” attribute to identify a bean
  • Use Constructor injection to promote thread safety
  • Use Properties for configurable resources
  • DO NOT use the SysOutOverSLF4J for anything other than migration



Further Reading




Social Me



Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com


About Gordon

Technology enthusiast primarily focused on Java and Open Source projects. Spring Certified Professional and Trainer. http://twitter.com/gdickens http://linkedin.com/in/gordondickens http://github.com/gordonad
This entry was posted in Java Util Logging, SLF4J, Spring and tagged , , , , , , , . Bookmark the permalink.

8 Responses to Enterprise Spring Framework Best Practices – Part 3 – XML Config

  1. Pingback: Enterprise Spring Best Practices – Part 1 – Project Config | Technophile Blog

  2. Pingback: Enterprise Spring Best Practices – Part 2 – Application Architecture | Technophile Blog

  3. Jim Liston says:

    Enjoying the articles, Gordon. Keep ‘em coming!

  4. Ashok Jha says:

    Thank you @Gardon the the information about Best Practices for Spring Configurations.

  5. ihadanny says:

    Concise and educating.
    Can you share your best practice for the properties file read by PropertyPlacholderConfig? Specifically, how do you use a different set of properties per deployment env?

  6. Java Geek says:

    must read for any Java developer.

  7. Firdous Amir says:

    Great points, Gordon. Thanks for sharing.

  8. Firdous Amir says:

    Perhaps you can share more advice on complex/multi-application spring environment, including remoting, security etc. There are too many info scattered around, but you definetly put things together. Will look forward for more.

Leave a Reply

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


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>