Jason
Jason

Reputation: 13986

SpringMVC: Variables in Annotations

I have the following controller defined:

@Controller
@RequestMapping("/test")
public class MyController extends AbstractController
{

    @Autowired
    public MyController(@Qualifier("anotherController") AnotherController anotherController))
    {
     ...
    }

}

I'm wondering if it's possible to use variables in the @Qualifier annotation, so that I can inject different controllers for different .properties files, e.g.:

@Controller
@RequestMapping("/test")
public class MyController extends AbstractController
{

    @Autowired
    public MyController(@Qualifier("${awesomeController}") AnotherController anotherController))
    {
     ...
    }

}

Whenever I try I get:

org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No matching bean of type [com.example.MyController] found for dependency: 
expected at least 1 bean which qualifies as autowire candidate for this 
dependency. Dependency annotations: 
{@org.springframework.beans.factory.annotation.Qualifier(value=${awesomeController})

I've included the following bean in my config.xml file:

<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:config/application.properties</value>
        </list>
    </property>
</bean>

But the bean doesn't work unless I declare the bean explicitly in the xml file.

How do I do this with annotations??

Upvotes: 3

Views: 2027

Answers (2)

Jonathan
Jonathan

Reputation: 20395

I'm not sure if what you're doing is possible but I can suggest a slightly different approach, but only if you're using Spring 3.1+. You could try using Spring Profiles.

Define the different controllers you want, one per profile:

<beans>
    <!-- Common bean definitions etc... -->

    <beans profile="a">
        <bean id="anotherController" class="...AnotherController" />
    </beans>

    <beans profile="b">
        <!-- Some other class/config here... -->
        <bean id="anotherController" class="...AnotherController"/>
    </beans>
</beans>

Your Controller would lose the @Qualifier and become something like:

@Autowired
public MyController(AnotherController anotherController) {
    ...
}

Then at runtime you can specify which controller bean you want to use by activating the corresponding profile using a system property, e.g.:

-Dspring.profiles.active="a"

or:

-Dspring.profiles.active="b"

It may be possible to set profiles based on a property file but you can find out more about Spring Profiles from this post on the Spring blog. I hope that helps somewhat.

Upvotes: 1

kgautron
kgautron

Reputation: 8293

First I think it is bad practice to make the dependency injection rely on configuration properties. You are probably going a wrong direction trying to do this.

However to answer your question: accessing placeHolder properties requires the dependency injection to be finished. To make sure it is, you can put your code that accesses the property inside a @PostContruct annotated method.

You will need to retrieve the bean manually from the applicationContext using getBean() method.

@Value("${awesomeController}")
private String myControllerName;

@PostConstruct
public void init(){
   AnotherController myController = (AnotherController) appContext.getBean(myControllerName);
}

Upvotes: 2

Related Questions