Spring 3, Maven and Annotation Based Configuration

August 22nd, 2010 by

There is still the urban myth that using Spring IoC container without thousands lines of XML code isn’t possible – so today we’re taking a look at annotation based configuration with Spring 3 and of course we’re using Maven..

 

Setup your project

  • Create a simple Maven project using
    mvn archetype:generate // or
    mvn archetype:create
  • Add a lot of dependencies and reference them to the Spring version defined as a property in your pom.xml. A good reference on Spring 3 and Maven artifacts can be found at Springsource.com
    <properties>
     <org.springframework.version>3.0.0.RELEASE</org.springframework.version>
     </properties>
     <dependencies>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-core</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-expression</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-beans</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aop</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context-support</artifactId>
     <version>${org.springframework.version}</version>
     </dependency>
     <dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>com.springsource.org.aspectj.runtime</artifactId>
     <version>1.6.8.RELEASE</version>
     </dependency>
     </dependencies>
  • We are going to run the sample application using the Exec-Maven-Plugin so add the following markup to your pom.xml
    <build>
     <plugins>
     <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>exec-maven-plugin</artifactId>
     <executions>
     <execution>
     <goals>
     <goal>java</goal>
     </goals>
     </execution>
     </executions>
     
     <configuration>
     <mainClass>com.hascode.tutorial.spring.Main</mainClass>
     </configuration>
     </plugin>
     </plugins>
     </build>
  • Last but not least we should adjust Maven’s compiler settings to use Java 5 because we’re going to use annotations
    <properties>
       [..]
       <maven.compiler.source>5</maven.compiler.source>
       <maven.compiler.target>5</maven.compiler.target>
     </properties>

Setting up Spring 3

  • Create a file named application-context.xml in the directory src/main/resources
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
     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/aop
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
     <context:annotation-config />
     <context:component-scan base-package="com.hascode.tutorial.spring" />
     <aop:aspectj-autoproxy />
    </beans>
  • That’s all .. the rest is accomplished using annotations ..

Create the application

  • The Configuration Interface – PersonConfig
    package com.hascode.tutorial.spring;
     
    public interface PersonConfig {
     
     public abstract String printName();
     
    }
  • The Implementation – PersonConfigImpl
    package com.hascode.tutorial.spring;
     
    import org.springframework.stereotype.Component;
     
    @Component
    public class PersonConfigImpl implements PersonConfig {
     /*
     * (non-Javadoc)
     * @see com.hascode.tutorial.spring.PersonConfig#printName()
     */
     public String printName() {
     return "Mr. X";
     }
    }
  • The Person Bean autowiring the needed PersonConfig class using the @autowired annotation
    package com.hascode.tutorial.spring;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
     
    @Component
    public class Person {
     private PersonConfig personConfig;
     
     @Autowired
     public void setPersonConfig(PersonConfig personConfig) {
     this.personConfig = personConfig;
     }
     
     public String getName() {
     return personConfig.printName();
     }
    }
  • The Main class that initializes the Spring Application Context
    package com.hascode.tutorial.spring;
     
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
     
    public class Main {
     public static void main(String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext(
     "application-context.xml");
     Person person = context.getBean(Person.class);
     System.out.println(person.getName());
     }
    }
  • Now run the applicationand enjoy ;)
    mvn clean compile exec:java

I don’t want no XML – Java Based Configuration

  • Use Guice – just kidding ..  first define a configuration class using the @Configuration annotation
    @Configuration
    public class ApplicationConfig {
     @Bean public TheBean theBean() {
     return new TheBeanImpl();
     }
    }
  • Replace the application loading from XML file to loading from annotations in your Main class
    ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
  • For detailed information take a look at the Spring documentation chapter 3.11 Java Based Container Configuration

Java EE 5 Common Annotations (JSR-250)

  • The following annotations from this standard are implemented:
    • @Resource: Has nearly the same meaning as @autowired
    • @PostConstruct and @PreDestroy: Lifecycle annotations used at object’s construction and destruction

Aspect Oriented Programming (AOP)

  • We’re just scratching the surface here – for deeper information take a look at the Spring documentation and the AspectJ Programming Guide
  • We’re creating a security interceptor that’s started when a method named getName is triggered using the @Aspect annotation
    package com.hascode.tutorial.spring;
     
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
     
    @Component
    @Aspect
    public class SecurityAspect {
     @Pointcut("execution(* getName(..))")
     public void triggerSecurity() {
     }
     
     @Before("triggerSecurity()")
     public void process(JoinPoint joinPoint) {
     System.out.println("Checking security for: "
     + joinPoint.getSignature().getName());
     }
    }
  • Enable the AspectJ autoproxy with this entry in your application-context.xml
    <aop:aspectj-autoproxy />
  • There is a helpful Maven plugin for the AspectJ part, the AspectJ Maven Plugin – add it to your pom.xml
    <dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjrt</artifactId>
     <version>1.6.8</version>
     </dependency>
     
    <build>
     <plugins>
     <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>aspectj-maven-plugin</artifactId>
     <version>1.3</version>
     <executions>
     <execution>
     <goals>
     <goal>compile</goal>       <!-- use this goal to weave all your main classes -->
     <goal>test-compile</goal>  <!-- use this goal to weave all your test classes -->
     </goals>
     </execution>
     </executions>
     </plugin>
     </plugins>
    </build>
  • Now compile and run the application with
    mvn run clean exec:java
  • This produced the following output
    Checking security for: getName
    Mr. X

Troubleshooting

  • “[ERROR] Syntax error, annotations are only available if source level is 5.0″ – the AspectJ Maven Plugin needs to know the source level – the default place it’s looking for this information is project.build.java.target – like this entry in your pom.xml
    <properties>
     <project.build.java.target>1.6</project.build.java.target>
    </properties>

Resources

Tags: , , , , , , , , ,

5 Responses to “Spring 3, Maven and Annotation Based Configuration”

  1. Gal Says:

    Thanks for the post!
    Highly informative.

    One comment though – I think that the schema location which specified in the file application-context.xml should have Spring 3 definitions if one will use Spring 3 (and not Spring 2.5 as mentioned).
    Example: use spring-beans-2.5.xsd instead of spring-beans-3.0.xsd

  2. mk Says:

    Thanks for the remark! I have updated the article :)

  3. Anvith Says:

    Good kick start for Spring support for annotations.

  4. btiernay Says:

    In order to simplify main management, I have created https://jira.springsource.org/browse/SPR-9044. If you like the proposed approach, please vote for it.

  5. gabe Says:

    Great post! The ‘troubleshooting’ proved very handy for me, I was facing the same error when compiling aspectj aspects from Maven and that did the trick to resolve the error :)

Leave a Reply

Please note, that no personal information like your IP address is stored and you're not required to enter you real name.

Comments must be approved before they are published, so please be patient after having posted a comment - it might take a short while.

Please leave these two fields as-is:
Search
Categories