Spring dependency injection – @Configurable

Some time ago I was asked the question whether it is possible to inject dependencies into objects that are not created by Spring. Hmm, sweet. Let’s see if we can do it 🙂

In the EJB world, there is no way to inject dependencies into a bean created with the new operator – as I have already pointed out in an earlier post. In a default Spring setup, an @Autowired class instantiated with the new keyword will behave just like in an enterprise application: all the dependencies will be left untouched; they will not be injected but left with their default values (a.k.a. null). This, usually will end in a NullPointerException like in the example below:

public class CarSalon {
    //...
	public void testDrive() {
		Car car = new Car();
		car.startCar();
	}
}

@Component
public class Car {
	@Autowired
	private Engine engine;
	@Autowired
	private Transmission transmission;

	public void startCar() {
		transmission.setGear(1);
		engine.engineOn();
		System.out.println("Car started");
	}
}

@Component
public class Engine {
//...
}

@Component
public class Transmission {
//...
}

Yep, running this code will fail with a NullPointerException. However, unlike in JavaEE, in Spring there is an awesome way to inject dependencies into objects created with the new keyword: the @Configurable annotation.

In order to make the example above run, you should add the @Configurable annotation to the Car class like this:

@Configurable(preConstruction = true)
@Component
public class Car {

	@Autowired
	private Engine engine;
	@Autowired
	private Transmission transmission;

	public void startCar() {
		transmission.setGear(1);
		engine.engineOn();

		System.out.println("Car started");
	}
}


@Configurable(preConstruction = true) what an annotation! It tells Spring to inject dependencies into the object before the constructor is run. But wait a bit, this will not work just like that, out of the box. You still need to do several more things:

  1. Add the following jars to your classpath (Spring will use aspect orientation in order to work around default behavior, and make your object eligible for dependency injection): aspectj-x.x.x.jar, aspectjrt.jar, aspectjveawer-x.x.x.jar
  2. Add a Spring-based java agent to your run configuration like this: -javaagent:”PATH\spring-instrument-x.x.x.jar”

Aaaand pretty much that’s it. The code should now be running and printing “Car started”.

Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

13 thoughts on “Spring dependency injection – @Configurable”

    1. If you happen to use Eclipse, then you’ll find a tiny black rectangle next to your run/debug buttons. Press that and select “Run configurations…” In the Run configurations window, select the “Arguments” tab. Enter the argument above into the JVM arguments box. (remember that PATH is the path to your Spring framework directory).

      Press run, and it should be all right.

      1. Am trying execute this code: but getting many error: i think i have written the code correctly but am unable to add the jar correctly..please explain me how to add jars correctly in eclipse/
        MainClass:
        package narayana16.java.main;

        import narayana16.java.model.Square;
        import narayana16.java.service.ShapeService;

        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;

        public class ExecuteMain {

        public static void main(String args[]){
        ApplicationContext ctx = new ClassPathXmlApplicationContext(“spring.xml”);
        ShapeService service = (ShapeService)ctx.getBean(“shapeservice”);
        //System.out.println(service.s);
        Square square = new Square();
        square.testDrive();

        }
        }

        Circle:model
        package narayana16.java.model;

        public class Circle {
        private String name;

        public String getName() {
        return name;
        }

        public void setName(String name) {
        this.name = name;
        }
        public String checkService() {
        System.out.println(“Checking service.. namo narayana…”);
        return “saikumar”;
        }

        }

        Square class:
        package narayana16.java.model;

        import narayana16.java.service.ShapeService;

        public class Square {
        public void testDrive() {
        System.out.println(“Before testDrive”);
        ShapeService shapeService = new ShapeService();
        shapeService.printShape();
        }
        }
        ShapeService Class:

        package narayana16.java.service;

        import narayana16.java.model.Circle;

        import org.springframework.beans.factory.annotation.Configurable;
        import org.springframework.stereotype.Component;

        @Configurable(preConstruction = true)
        @Component

        public class ShapeService {

        private Circle circle;

        public Circle getCircle() {
        return circle;
        }

        public void setCircle(Circle circle) {
        this.circle = circle;
        }
        public void printShape(){
        circle.setName(“narayana configuration”);
        System.out.println(“IN shape Service”);
        }
        }
        Xml file:

          1. sir meant to say: am unable to add jars to get the functionality of load-time-weaving,(for this i added all aspectj jars to build path but it is not working). and i didn’t how to add -javaagent:”xx.jar”
            please help me sir. please.. i have been trying this since morning..

  1. Sir can you please help am getting this error:
    ocation:
    narayana/plianto/service/Car.()V @23: ifnull
    Reason:
    Expected stackmap frame at this location.
    Bytecode:
    0000000: 2ab7 000c b200 652a 2ab8 003b 4db2 0035
    0000010: 2a2a b800 3b4c 2ac6 0028 2ab6 004b 124d
    0000020: b600 5b99 001c 2ab6 004b 124d b600 53c0
    0000030: 004d b800 5799 000a b800 412a b600 4700
    0000040: 2ac6 003f 2ab6 004b 124d b600 5b99 0033
    0000050: 2ac6 0021 2ab6 004b 124d b600 5b99 0015
    0000060: 2ab6 004b 124d b600 53c0 004d b800 579a
    0000070: 0011 2bb8 0062 9900 0ab8 0041 2ab6 005e
    0000080: 00a7 0003 2ab6 004b 124d b600 53c0 004d
    0000090: b800 579a 0011 2cb8 0062 9900 0ab8 0041
    00000a0: 2ab6 005e b1

    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2532)
    at java.lang.Class.getDeclaredConstructors(Class.java:1901)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:234)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1040)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1013)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
    at narayana.plianto.main.MainExecution.main(MainExecution.java:15)

    please sir please sir please sir

  2. what does it mean when somebody ask you to make a class configurable ?

    in my case i have an existing class as below and i was asked to make it configurable. if i simply add the annotation @Configurable to this class would that suffice ?

    abstract public class aGenerated extends aaaa implements Serializable
    {

    @NotNull
    private ATU aTU;

    private boolean mv= false;

    public aGenerated (someEnum type) throws someException
    {
    super(type);
    aTU= ATU .parse(“some:hard:coded:value”);
    }

    public ATU getATU()
    {
    return aTU;
    }

    public void setATU (ATU aTU)
    {
    this.aTU= aTU;
    }

    public Boolean getMV()
    {
    return mv;
    }

    public void setMV(Boolean mv)
    {
    this.mv= mv;
    }

    1. I guess it should do something with that hardcoded string. If it really has to do with Spring than simply adding that annotation would not be enough. You also have to do the other things too.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s