5

I'm having trouble injecting JNDI values from my Tomcat into spring java config using the @Value annotation whereas I have no trouble retreiving the values via the Environment class. We are using Java 1.7.0_17, Spring 4.0.3, and Tomcat 7.0.52 .

I have in my context.xml the following variables defined:

<Environment name="USER_NAME" value="initech" type="java.lang.String" />
<Environment name="USER_PASSWORD" value="1n3+3ch!" type="java.lang.String" />

In my Java configuration file I have the following code working:

@Bean
public Foo foo( Environment env ){
    return new Foo( env.getProperty("USER_NAME"), env.getProperty("USER_PASSWORD") );
}

When I look into the server log I see:

12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [servletConfigInitParams]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [servletContextInitParams]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [jndiProperties]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.springframework.jndi.JndiTemplate -> Looking up JNDI object with name [java:comp/env/USER_NAME]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.jndi.JndiLocatorDelegate -> Located object with JNDI name [java:comp/env/USER_NAME]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.jndi.JndiPropertySource -> JNDI lookup for name [USER_NAME] returned: [initech]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Found key 'USER_NAME' in [jndiProperties] with type [String] and value 'initech'

However, I would like to use @Value annotation to make the code cleaner if at all possible; something along the lines of

@Bean
public Foo foo(
        @Value( "#{USER_NAME}" ) String userName,
        @Value( "#{USER_PASSWORD}" ) String userPassword
    ){

    return new Foo( userName, userPassword );
}

but this code results in the error:

nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oauthTokenRequestClient' defined in class path resource [com/initech/set/gw/api/config/GatewayRepositoryConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.net.URI]: : Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)

I have tried "#{systemEnvironment.USER_NAME}, "#{systemProperties.USER_NAME}, "#{jndiProperties.USER_NAME}, and "#{java:comp/env/USER_NAME} as well: yet, none of them work.

PS- I've tried to simplify the question so if one of these should have worked let me know because I may have made an error in my posting.

Sled
  • 18,541
  • 27
  • 119
  • 168
  • 1
    possible duplicate of [Java Spring: How to use \`@Value\` annotation to inject an \`Environment\` property?](http://stackoverflow.com/questions/14617181/java-spring-how-to-use-value-annotation-to-inject-an-environment-property) – Morfic Jun 10 '14 at 17:24
  • @Morfic yeah, it pretty much is. Must have missed it since I was searching for "JNDI" and not "Environment". This question should still help people like myself in the future if it doesn't get deleted. – Sled Jun 10 '14 at 17:51

4 Answers4

6

I solved it using the selected answer from the question Java Spring: How to use @Value annotation to inject an Environment property?.

So my code looks like:

@Bean
public Foo foo(
        @Value( "#{environment.USER_NAME}" ) String userName,
        @Value( "#{environment.USER_PASSWORD}" ) String userPassword
    ){

    return new Foo( userName, userPassword );
}

I'm assuming from the content of the most upvoted answer (ie "assuming that you have a PropertySourcesPlaceHolderConfigurer registered") to that quesiton that this means we are lacking a configured PropertySourcesPlaceHolderConfigurer.

Community
  • 1
  • 1
Sled
  • 18,541
  • 27
  • 119
  • 168
1

If you are using Spring 4 you should change

  @Value( "#{USER_PASSWORD}" ) String userPassword

To

@Value( "${USER_PASSWORD}" ) String userPassword

Try that and see what happens.

Bryce Easley
  • 4,811
  • 2
  • 20
  • 22
  • 1
    `@Value("#{environment.USER_NAME}")` worked for me whereas `@Value("${USER_NAME}")` did not. The types I'm actually using are `URI` and with `@Value("${USER_NAME}")` I get an exception from the `URI` constructor that "$" is an invalid character which suggest it took the literal value when using the `$`. – Sled Jun 10 '14 at 17:50
  • 1
    When using `${…}` placeholders you have to register a `PropertySourcesPlaceholderConfiguere` else it will not work. This registration has to be done with a `public static` method which is annotated with `@Bean`. See the accepted answer to this question http://stackoverflow.com/questions/15395123/value-annotation-not-being-properly-set – M. Deinum Jun 10 '14 at 18:44
1

For Spring 3.1+ (tested on 4.2.5.RELEASE), you can use @Value like this:

@Value("${property.name}")
private String jndiProperty;

But you also need to define a PropertySourcesPlaceholderConfigurer bean in a static method and configure a JndiPropertySource (I have this in an @Configuration class):

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(ConfigurableEnvironment env) {
    PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();

    JndiPropertySource jndiPropertySource = new JndiPropertySource("java:comp");
    env.getPropertySources().addFirst(jndiPropertySource);

    return placeholderConfigurer;
}

Note the use of addFirst() which ensures property values from JNDI take precedence in case of a clash with other property sources, which may or may not be desired, in which case one can use other methods like addLast() etc.

rohitvats
  • 1,811
  • 13
  • 11
-2

This is the correct syntex

  @Value("${PASSWORD}")

Have a look at this example:

http://www.programsji.com/spring/readpropertyfile

programsji.com
  • 217
  • 1
  • 6
  • 1
    But it's not coming from a property file but from a JNDI value from the `context.xml` of my container _and_ I have already tried that and it didn't work. – Sled Jun 10 '14 at 18:04