tintin
tintin

Reputation: 5867

Injecting bean with no default constructor in controller

Can we inject a Service bean with no default constructor into a controller?

I have the following controller

@Controller
public class ArticleController {
    @Autowired
    private WithConstructorService withConstructorService;
    ...
}

And my service is:

@Service
public class WithConstructorServiceImpl implements WithConstructorService {
    String name;
    String address;

    public WithConstructorServiceImpl(String name, String address) {
        super();
        this.name = name;
        this.address = address;
    }
}

I'm getting the exception

SEVERE: Servlet /springheat threw load() exception
java.lang.NoSuchMethodException:  WithConstructorServiceImpl.<init>()

update:

I'm making a guess here but can we do some AOP magic and still use annotated constructor arg service method?

Upvotes: 4

Views: 3771

Answers (3)

JB Nizet
JB Nizet

Reputation: 691973

You can do that, but since Spring must instantiate the bean, you must tell him which values to pass to the constructor.

First possibility: autowire the two arguments:

@Autowired
public WithConstructorServiceImpl(@Qualifier("theNameBean") String name, 
                                  @Qualifier("theAdressBean") String address) {

In this case, you'll have to declare two beans of type String in the context.xml file, with the appropriate name.

Second possibility: declare the bean itself in the context.xml file and tell Spring which arguments it must pass to the constructor.

See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-collaborators

Upvotes: 2

Kevin
Kevin

Reputation: 25269

If you're using spring 3 you can use the @Value annotation to wire the name and address fields, and then they don't need to be set thru the constructor. Or, don't use the @Service annotation and instead declare your bean in xml with appropriate <constructor-arg> tags.

Either way, the spring container needs to know where to get the values for name and address, or it can't construct your WithConstructorServiceImpl.

Upvotes: 2

danny.lesnik
danny.lesnik

Reputation: 18639

No, you can't. Because when the bean is injected it creates the bean itself using the default constructor and only after it all its properties are injected.

What you can do is just to create setters for name and address and then add it to the injected bean.

Upvotes: 0

Related Questions