2

As explained here and here it is quite clear how to do it but still can't seem to make it work. I simply like to use the @Value annotation in order to inject a property to a spring bean. I created a basic spring MVC project with one controller and one bean.

Here is my application context:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:beans="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
   http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
   http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
   http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">


<!-- Root Context: defines shared resources visible to all other web components -->

<context:component-scan base-package="me.co.fatsecret" />

<!-- Properties -->

<bean id="props"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:fatProperties.properties" />
</bean>


</beans>

I have one bean called Configuration:

package me.co.fatsecret;

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

@Component
public class Configuration {

    /*--- Members ---*/

    @Value("${api_key}")
    protected String API_KEY;
    @Value("${api_secret}")
    protected String API_SECRET;
    @Value("${api_url}")
    protected String API_URL;

    /*--- Constructors ---*/

    public Configuration() {
    }

    /*--- Getters & Setters ---*/

    public String getAPI_KEY() {
    return API_KEY;
    }

    public void setAPI_KEY(String aPI_KEY) {
    API_KEY = aPI_KEY;
    }

    public String getAPI_SECRET() {
    return API_SECRET;
    }

    public void setAPI_SECRET(String aPI_SECRET) {
    API_SECRET = aPI_SECRET;
    }

    public String getAPI_URL() {
    return API_URL;
    }

    public void setAPI_URL(String aPI_URL) {
    API_URL = aPI_URL;
    }

}

Now I have only one controller, injected with this Configuration class and as I call this controller I see that the values in the Configuration class are not populated right.

My properties file is located under the resources folder (src/main/resources) and is a part of my classpath (done by default since this is a maven project). Here it is:

api_url=http://platform.fatsecret.com/js?
api_key=SomeKey
api_secret=SomeSecret

The file name is fatProperties.properties. As I debug my server when calling the controller I see that the content of the Configuration class is:

${api_key}
${api_secret}
${api_url}

This is the actual value of the Strings, wich means that the vales from the properties file are not getting injected for some reason.

Am I missing something here?

UPDATE1: I replaced the PropertyPlaceholderConfigurer bean with:

<context:property-placeholder location="classpath:fatProperties.properties"/>

Getting the same result

Community
  • 1
  • 1
forhas
  • 11,551
  • 21
  • 77
  • 111

3 Answers3

5

Ok, got it!

I'm using a spring MVC project, which means I have a separated context for my web layer (the controllers). The "Configuration" bean which hods the properties using the @Value annotation is injected to a controller. My property-placeholder is defined within my root-context hence it cannot be seen from my controller. To resolve the issue I simply added the property-placeholder definition to my DispatcherServlet context and it works like a charm :)

forhas
  • 11,551
  • 21
  • 77
  • 111
  • Actually, "seen" is somewhat misleading. According to http://forum.spring.io/forum/spring-projects/container/35724-web-context-beans-not-postprocessed-by-propertyplaceholderconfigurer-in-parent-ctx?p=323860#post323860 no BeanPostProcessors of parent contexts are applied to beans of child contexts. If you would do some manual placeholder replacement, you could nonetheless autowire and use the property-placeholder-configurer from your parent context. – philnate Jan 20 '16 at 14:15
4

Add this to your application context file:

<context:property-placeholder location="classpath:fatProperties.properties" />
nickdos
  • 8,348
  • 5
  • 30
  • 47
  • This looks like a good idea, but when using this instead of my property-placeholder I get the exact same result – forhas Aug 09 '12 at 09:26
  • Apart from that line, I have exactly the same setup and my @Value annotations work as they should. Maybe try turning on DEBUG level logging for org.springframework to look for clues. Good luck. – nickdos Aug 09 '12 at 23:38
  • Thanks nickdos. I thought it might has something to do with the spring MVC structure (2 different contexts). Does your case also include a spring MVC app? – forhas Aug 10 '12 at 17:27
1

Try

@Value("#{props['api_key']}")
private String apiKey;
  • 1
    Why should I try it? I don't want to use SpEL, I have no need. What is wrong with my definition? – forhas Aug 09 '12 at 09:23