Bootstrap a Web Application with Spring 4

I usually post about Spring stuff on Google+ - you can follow me there:

Table of Contents

1. Overview

The tutorial illustrates how to Bootstrap a Web Application with Spring and also discusses how to make the jump from XML to Java without having to completely migrate the entire XML configuration.

2. The Maven pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://maven.apache.org/POM/4.0.0 
      http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org</groupId>
   <artifactId>rest</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>

   <dependencies>

      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>${spring.version}</version>
         <exclusions>
            <exclusion>
               <artifactId>commons-logging</artifactId>
               <groupId>commons-logging</groupId>
            </exclusion>
         </exclusions>
      </dependency>
      
   </dependencies>

   <build>
      <finalName>rest</finalName>

      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
               <source>1.6</source>
               <target>1.6</target>
               <encoding>UTF-8</encoding>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <properties>
      <spring.version>4.0.5.RELEASE</spring.version>
   </properties>

</project>

2.1. The cglib dependency before Spring 3.2

You may wonder why cglib is a dependency – it turns out there is a valid reason to include it – the entire configuration cannot function without it. If removed, Spring will throw:

Caused by: java.lang.IllegalStateException: CGLIB is required to process @Configuration classes. Either add CGLIB to the classpath or remove the following @Configuration bean definitions

The reason this happens is explained by the way Spring deals with @Configuration classes. These classes are effectively beans, and because of this they need to be aware of the Context, and respect scope and other bean semantics. This is achieved by dynamically creating a cglib proxy with this awareness for each @Configuration class, hence the cglib dependency.

Also, because of this, there are a few restrictions for Configuration annotated classes:

  • Configuration classes should not be final
  • They should have a constructor with no arguments

2.2. The cglib dependency in Spring 3.2 and beyond

Starting with Spring 3.2, it is no longer necessary to add cglib as an explicit dependency. This is because Spring is in now inlining cglib – which will ensure that all class based proxying functionality will work out of the box with Spring 3.2.

The new cglib code is placed under the Spring package: org.springframework.cglib (replacing the original net.sf.cglib). The reason for the package change is to avoid conflicts with any cglib versions already existing on the classpath.

Also, the new cglib 3.0 is now used, upgraded from the older 2.2 dependency (see this JIRA issue for more details).

Finally, now that Spring 4.0 is out in the wild, changes like this one (removing the cglib dependency) are to be expected with Java 8 just around the corner – you can watch this Spring Jira to keep track of the Spring support, and the Java 8 Resources page to keep tabs on the that.

3. The Java based Web Configuration

@Configuration
@ImportResource( { "classpath*:/rest_config.xml" } )
@ComponentScan( basePackages = "org.rest" )
@PropertySource({ "classpath:rest.properties", "classpath:web.properties" })
public class AppConfig{

   @Bean
   public static PropertySourcesPlaceholderConfigurer properties() {
      return new PropertySourcesPlaceholderConfigurer();
   }
}

First, the @Configuration annotation – this is the main artifact used by the Java based Spring configuration; it is itself meta-annotated with @Component, which makes the annotated classes standard beans and as such, also candidates for component scanning. The main purpose of @Configuration classes is to be sources of bean definitions for the Spring IoC Container. For a more detailed description, see the official docs.

Then, @ImportResource is used to import the existing XML based Spring configuration. This may be configuration which is still being migrated from XML to Java, or simply legacy configuration that you wish to keep. Either way, importing it into the Container is essential for a successful migration, allowing small steps without to much risk. The equivalent XML annotation that is replaced is:

<import resource=”classpath*:/rest_config.xml” />

Moving on to @ComponentScan – this configures the component scanning directive, effectively replacing the XML:

<context:component-scan base-package="org.rest" />

As of Spring 3.1, the @Configuration are excluded from classpath scanning by default – see this JIRA issue. Before Spring 3.1 though, these classes should have been excluded explicitly:

excludeFilters = { @ComponentScan.Filter( Configuration.class ) }

The @Configuration classes should not be autodiscovered because they are already specified and used by the Container – allowing them to be rediscovered and introduced into the Spring context will result in the following error:

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name ‘webConfig’ for bean class [org.rest.spring.AppConfig] conflicts with existing, non-compatible bean definition of same name and class [org.rest.spring.AppConfig]

And finally, using the @Bean annotation to configure the properties support – PropertySourcesPlaceholderConfigurer is initialized in a @Bean annotated method, indicating it will produce a Spring bean managed by the Container. This new configuration has replaced the following XML:

<context:property-placeholder
location="classpath:persistence.properties, classpath:web.properties"
ignore-unresolvable="true"/>

For a more in depth discussion on why it was necessary to manually register the PropertySourcesPlaceholderConfigurer bean, see the Properties with Spring Tutorial.

3.1. The web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="
       http://java.sun.com/xml/ns/javaee"
       xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
       http://java.sun.com/xml/ns/javaee 
       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="rest" version="3.0">

   <context-param>
      <param-name>contextClass</param-name>
      <param-value>
         org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
   </context-param>
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>org.rest.spring.root</param-value>
   </context-param>
   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>

   <servlet>
      <servlet-name>rest</servlet-name>
      <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <init-param>
         <param-name>contextClass</param-name>
         <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
         </param-value>
      </init-param>
      <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>org.rest.spring.rest</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
      <servlet-name>rest</servlet-name>
      <url-pattern>/api/*</url-pattern>
   </servlet-mapping>

   <welcome-file-list>
      <welcome-file />
   </welcome-file-list>

</web-app>

First, the root context is defined and configured to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext. The newer AnnotationConfigWebApplicationContext accepts @Configuration annotated classes as input for the Container configuration and is needed in order to set up the Java based context.

Unlike XmlWebApplicationContext, it assumes no default configuration class locations, so the “contextConfigLocation” init-param for the Servlet must be set. This will point to the java package where the @Configuration classes are located; the fully qualified name(s) of the classes are also supported.

Next, the DispatcherServlet is configured to use the same kind of context, with the only difference that it’s loading configuration classes out of a different package.

Other than this, the web.xml doesn’t really change from a XML to a Java based configuration.

4. Conclusion

The presented approach allows for a smooth migration of the Spring configuration from XML to Java, mixing the old and the new. This is important for older projects, which may have a lot of XML based configuration that cannot be migrated all at once.

This way, in a migration, the XML beans can be ported in small increments.

In the next article on REST with Spring, I cover setting up MVC in the project, configuration of the HTTP status codes, payload marshalling and content negotiation.

The implementation of this Bootstrap a Spring Web App Tutorial can be downloaded as a working sample project.

This is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Spring stuff on Google+ - you can follow me there:

 

>> GET THE EBOOKS <<
Get the eBooks and Learn to Build a Simple App
×
Build a Simple but Working App with Spring

,

  • http://twitter.com/rasch23 Ralph Schaer

    Hi

    You could use @PropertySource to simplify the configuration and get rid of the PropertyPlaceholderConfigurer Bean.

    @Configuration
    @ComponentScan( basePackages = “org.rest”,excludeFilters = { @ComponentScan.Filter( Configuration.class ) } )
    @PropertySource({ “persistence.properties”, “restfull.properties” })
    public class ApplicationConfig{
    }

    In the class PersistenceConfig you have two options to read the property values.
    1. Inject the Environment Bean and read the values with getProperty(key)

    @Configuration
    @EnableTransactionManagement
    public class PersistenceConfig{

    @Autowired
    private Environment environment;

    @Bean
    public BasicDataSource restDataSource(){
    String driverClass = this.environment.getProperty(“driverClassName”)
    }
    }

    2. Use @Value

    @Configuration
    @EnableTransactionManagement
    public class PersistenceConfig{

    @Value(“#{environment.driverClassName}”)
    private String driverClassName;

    }

    • http://slava-semushin.blogspot.com/ Slava Semushin

      2Ralph Schaer: approach with @PropertySource and @Value doesn’t works for me and fails with following error:

      >Caused by:
      org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property ‘showSql’ cannot be found on object of type ‘org.springframework.beans.factory.config.BeanExpressionContext’

      With context:property-placeholder all works fine..

  • http://michalorman.pl Michal Orman

    Shouldn’t properties() method be marked as static? I receive warning if do not mark method as static. It is also described in Javadoc for @Bean.

    • Eugen

      Yes, because PropertyPlaceholderConfigurer is a BeanFactoryPostProcessor, the method should be static. Nice catch, I updated the code snippet accordingly, thanks.

    • http://www.baeldung.com/ Eugen Paraschiv

      I updated the article – thanks.

  • Chris Beams

    Hi Eugen,

    Note that as of Spring 3.1 RC2, use of excludeFilters=@Filter(Configuration.class) is no longer necessary. See https://jira.springsource.org/browse/SPR-8808.

    Would you mind updating your examples to depend on RC2 and eliminating this bit from the @ComponentScan definition?

    Thanks for a great series of posts!

    • http://www.baeldung.com/ Eugen Paraschiv

      Thank you for letting me know (as well as for the actual work). The update is now included in the article.

  • Pingback: Transaction configuration with JPA and Spring 3.1()

  • Amol Khanolkar

    Can you tell me some advantages of using java based configurations over XML based and when to choose which one?

    • Torben Vesterager

      Simple – you have one file for configuration and functionality – instead of jumping between 2

    • http://www.baeldung.com/ Eugen Paraschiv

      Type safety is a big one, and ease of use is a close second.

      • Stephane

        And you can use a debugger if needed.

  • Stephane

    It’d be nice to also include a showcase on how to replace the web.xml file by a class implementing the WebApplicationInitializer interface.

    • http://www.baeldung.com/ Eugen Paraschiv

      I am planning to discuss that in an upcoming article.

      • Stephane

        I could in fact do it, and it wasn’t that hard. The only thing that I could not cut is how to move the elements of the log4j config into a Java config. Google was dry on this one. Maybe your next article would shed some light on this :-) Thanks again.

        • Stephane

          It’s funny, my comment was automatically closed by a tag.

  • Anuj Patel

    Thanks ! It really helps to clear concepts and will help while doing actual Implementation

  • Antonel Ernest Pazargic

    Thank you for the good intro in setting up a spring based web application.

    IMHO groovy application context configuration will get traction in the near future, just as gradle does over the maven.

    It would be great if you are considering to migrate the example project to groovy context config.

    Thank you.

    • http://www.baeldung.com/ Eugen Paraschiv

      It’s definitely an idea that I’m considering for some of my next articles. Thanks for the suggestion – I’ll also remember to follow up here once I do. Cheers,
      Eugen.

  • James Heggs

    Many thanks for sharing this – I was having a problem utilising properties in my annotation based unit test.

    Managed to resolve it after seeing your PropertySourcesPlaceholderConfigurer example

    • http://www.baeldung.com/ Eugen Paraschiv

      Happy to help. Cheers,
      Eugen.

  • Sam

    Hi, i downloaded the source code, could you please show me how to run it. Thanks.

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Sam – it’s a Maven project, so you can import it into the IDE of your choice. It’s also an Eclipse project, so – in case you’re using Eclipse, you can simply import it as a normal project. And you can of course build it from command line with Maven if you need to. Hope that helps. Cheers,
      Eugen.

  • Alexandru Matei

    Eugen, can you please explain the necessity for

    commons-logging
    commons-logging

    in spring-webmvc dependency ?

    Why is that necessary in Spring 4?

    • http://www.baeldung.com/ Eugen Paraschiv

      The reason you need to exlucde commons-logging is that – unfortunately – it’s the default in Spring, so it’s pulled in as a dependency (yes, even in Spring 4.1); so – first step is to exclude it, and then you’ll need to use a bridge to map it to something else (jcl-over-slf4j). Cheers,
      Eugen.

      • Alexandru Matei

        I notice indeed in my target folder compiled with Maven + Spring 4.1.0 appears
        commons-logging-1.1.1.jar

        You mean that this commons-logging-1.1.1.jar added as a dependency side effect by Maven is too old ?

        • http://www.baeldung.com/ Eugen Paraschiv

          It’s old as well (2007) but that’s not the main issue – it has other disadvantages. slf4j backed by logback is just a much better solution.

          • Alexandru Matei

            All right, thank you Eugen.

            Although is a bit off topic, please allow a short comment

            I had a hard time (for me as beginner) to run a
            Spring Web MVC + Spring security application.

            I had to set manually:

            xml-apis
            xml-apis
            1.4.01

            /dependency>

            When building using Maven, it is pulling in the xml-apis jar 1.0.b2 which apparently is not compatible ?!

            So without this workaround, my Spring web application is not loaded at all in the application server (GlassFish 4.1 in my case)

            There are other people on the web discussing this problem in various situations.

          • http://www.baeldung.com/ Eugen Paraschiv

            I never did deploy it in GlassFish, but yes, I found the discussions threads. One suggestion is to open a JIRA with Hibernate to upgrade the dependency (it’s pulled in by hibernate-entitymanager). In the meantime, I updated the project – thanks for the suggestion. Cheers,
            Eugen.

  • Dale Ogilvie

    What about using the Spring IO platform for your bootstrap? http://platform.spring.io/platform/

    This is convenient to manage dependency versions.

    • http://www.baeldung.com/ Eugen Paraschiv

      That’s a good way to go, but it’s still very new. Using something that new is unfortunately not a viable option for a lot of projects, which is why I think going the standard route is still very useful. Also – understanding the standard route well before doing anything else that will “help” is also a good idea. That being said – I like the platform – it does make things easier. Cheers,
      Eugen.