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 :)

Search
Tags
Categories