3

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??

Dani
  • 3,744
  • 4
  • 27
  • 35
Jason
  • 13,563
  • 15
  • 74
  • 125
  • http://stackoverflow.com/questions/317687/how-can-i-inject-a-property-value-into-a-spring-bean-which-was-configured-using and http://springinpractice.com/2008/12/02/new-stuff-in-spring-30/ – NimChimpsky Apr 04 '13 at 16:02

2 Answers2

2

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);
}
kgautron
  • 7,915
  • 9
  • 39
  • 60
  • I tried @ PostContruct on the constructor, but that was an invalid annotation placement, so I created a setter method: @ PostConstruct @ Autowired public void set( @ Qualifier("${awesomeController}") AnotherController anotherController) { ... } But I'm getting the following error: java.lang.IllegalStateException: Lifecycle method annotation requires a no-arg method Can you explain in more detail? – Jason Apr 04 '13 at 13:50
1

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.

Dani
  • 3,744
  • 4
  • 27
  • 35
Jonathan
  • 20,053
  • 6
  • 63
  • 70