user1364861
user1364861

Reputation: 321

Spring 4 @Autowire not binding correctly?

I m trying to Autowire a bean to a implementation but it returns a null pointer Exception.

package org.com.api;

public interface Multiply {
    public int multipler(int a, int b);
}

package org.com.core;
import org.com.api.Multiply;

public class MultiplyImpA implements Multiply {
    public int multipler(int a, int b){
        return a*b;
    }
}

package org.com.core;
import org.com.api.Multiply;
public class MultiplyImpB implements Multiply {
    public int multipler(int a, int b){
        int total = 0;
        for(int i = 1; i <=b; i++){
            total += a;
        }
        return total;
    }
}

package org.com.Service;
import org.com.api.Multiply;
public Calculator {
    @Autowire
    private Multiply multiply;
    public int calcMultiply(int a, int b){
        return multiply.multipler(a,b);
    }
}

In my applicationContext.xml I have added the following

<bean id="multiply" class="org.com.core.MultiplyImpA" scope="prototype"/>

Now in runtime I get a NullPointerExpection. multiply is null.

for testing purpose I tried this. It works, I understand here I m explicitly getting the Bean. So this means the autowire didnt work ? is there something I m missing ?

Multiply m = (Multiply)factory.getBean("multiply");
System.out.println(m.multiplier(2,4);

Upvotes: 1

Views: 388

Answers (2)

fateddy
fateddy

Reputation: 7157

Seems you have a typo in your bean xml.

Instead of

<bean id="multiply" class="package org.com.core.MultiplyImpA" scope="prototype"/>

it should be (using the full qualified classname only)

<bean id="multiply" class="org.com.core.MultiplyImpA" scope="prototype"/>

EDIT:

Possible error could be that the Calculator class is not managed by spring. Instantiating the class using the new operator would fail because there is no way that spring would get a reference to inject the collaborator:

Calculator calculator = new Calculator();
calculator.calcMultiply(1, 2); // would throw a NPE because the `Multiply` instance (in your case `MultiplyImpA`) has not been injected.

So instead instantiate the Calculator class using spring:

<bean id="calculator" class="org.com.service.Calculator"/>
<bean id="multiply" class="org.com.core.MultiplyImpA"/> 

Retrieve it through the application-context:

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
Calculator calculator = ctx.getBean(Calculator.class);

Spring would then manage the dependencies by scanning the @Autowired annotation, looking at the field type and trying to find a qualified bean from the application context.

Upvotes: 0

minion
minion

Reputation: 4353

Autowiring resolves by type, since there are two different impl, you need to use qualifier to narrow it down. SO try the below.

public Calculator {
@Autowire
@Qualifier("multiply")
private Multiply multiply ;
public int calcMultiply(int a, int b){
    return multiply.multipler(a,b);
}
}

Upvotes: 1

Related Questions