Bjorn Harvold opened SPR-14140 and commented

I created ticket #18525 pre v4.3.RC1.

I updated to 4.3.RC1 today and found that the placeholder still doesn't convert.

The below code fails:

public void logoutUser(@RequestHeader(name = "${auth.token.name}", required = true) String authToken) {
        if (log.isDebugEnabled()) {
            log.debug(String.format("Auth-Token: %s", authToken));
        }
        preAuthenticatedTokenCacheService.deleteExistingSessions(Collections.singletonList(authToken));
    }
2016-04-09 11:13:29,346 E DefaultExceptionHandler - Http Status: 400 : Missing request header '${auth.token.name}' for method parameter of type String
org.springframework.web.bind.ServletRequestBindingException: Missing request header '${auth.token.name}' for method parameter of type String

Please advise


Affects: 4.3 RC1

Issue Links: - #21745 Document default EmbeddedValueResolver support for property placeholders - #18203 Support SpEL next to placeholders in annotation attributes (e.g. @Scheduled) - #18525 @RequestHeader name/value does not accept placeholders - #13183 automatic registration of PSPC when @PropertySource is used - #14537 @Enable-style annotation is desired for automatic registration of PropertySourcesPlaceholderConfigurer

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/0f0aa46e4983d2c48e30db710d8e07fe3d649825, https://github.com/spring-projects/spring-framework/commit/cb9549655c078534db6cd2b7631640e44054e976

0 votes, 5 watchers

Comment From: spring-projects-issues

Juergen Hoeller commented

My guess is that you did not declare a PropertySourcesPlaceholderConfigurer a.k.a. <context:property-placeholder> in your application context. In that case, $... placeholders are not getting resolved at all, neither in bean definitions nor in annotation attribute values.

This can be rather unintuitive, in particular since #... style expressions are active by default. We should consider supporting placeholders in annotation attributes by default.

Comment From: spring-projects-issues

Juergen Hoeller commented

We're registering a default embedded value resolver for the default environment now, in case of none having been registered through post-processors (like PropertyPlaceholderConfigurer and PropertySourcesPlaceholderConfigurer do, with configurable placeholder syntax etc).

This will make it into 4.3 RC2. However, it would be great if you could confirm that a manually added PropertySourcesPlaceholderConfigurer solves the problem in your scenario...

Comment From: spring-projects-issues

Bjorn Harvold commented

This is how I'm registering my environment specific content:

@Configuration
@PropertySource(value = "classpath:server-local.properties")
public class AppLocalConfig {
}

So you are saying this won't work until 4.3RC2?

Comment From: spring-projects-issues

Sam Brannen commented

I updated to 4.3.RC1 today and found that the placeholder still doesn't convert.

You have always had to manually register a PropertySourcesPlaceholderConfigurer for this to work with @Configuration classes.

Here is an excerpt from the Javadoc for PropertySource:

In order to resolve ${...} placeholders in \ definitions or @Value annotations using properties from a PropertySource, one must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using in XML, but must be explicitly registered using a static @Bean method when using @Configuration classes. See the "Working with externalized values" section of @Configuration's javadoc and "a note on BeanFactoryPostProcessor-returning @Bean methods" of @Bean's javadoc for details and examples.

In other words, adding the following static bean to one of your @Configuration classes should solve your problem.

 @Bean
public static PropertySourcesPlaceholderConfigurer ppc() {
    // instantiate, configure and return ppc ...
}

Comment From: spring-projects-issues

Juergen Hoeller commented

Indeed, even a plain

@Bean
public static PropertySourcesPlaceholderConfigurer ppc() {
    return new PropertySourcesPlaceholderConfigurer();
}

should do the job.

The only thing that changes as of 4.3 RC2 is that standard placeholder resolution in annotation attributes will work even without such a placeholder configurer bean in your context.

Comment From: spring-projects-issues

Bjorn Harvold commented

Hi guys,

I added this code to see if it would change anything. I still get the same error.

@Configuration
@PropertySource(value = "classpath:server-local.properties")
public class AppLocalConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer ppc() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

Comment From: spring-projects-issues

Juergen Hoeller commented

Hmm, this should actually work against 4.3 RC1 that way...

Could you alternatively try against 4.3.0.BUILD-SNAPSHOT where that extra bean definition shouldn't even be necessary?

Comment From: spring-projects-issues

Bjorn Harvold commented

Hi Juergen,

We haven't configured our Maven repo to retrieve external snapshots. I'll put a footnote in my code and test this again with RC2. If it doesn't work in RC2, I'm probably doing something wrong on my end.

P.S. I do wonder if you guys ever sleep. The response time on my tickets is phenomenal!

Comment From: ipleten

If someone still wondering why this doesn't work in 2020 with ENV variables (and you still use Spring 4.3.X) check that spring-context-3.1.xsd is 3.1 and not 3.0.