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 application and 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>