Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNDI Property Placeholder Configurer [SPR-3030] #7716

Closed
spring-issuemaster opened this issue Jan 12, 2007 · 10 comments
Closed

JNDI Property Placeholder Configurer [SPR-3030] #7716

spring-issuemaster opened this issue Jan 12, 2007 · 10 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Jan 12, 2007

Arthur opened SPR-3030 and commented

When creating beans such as a JNDITemplate it is often desireable to have a container supply the provider URL and other configuration options via Environment entries. I find it is generally not a great idea swap applicationContext files using a build script because it adds another layer of complexitity to the build process. Therefore I prefer having different deployment descriptors on different test/production servers with different Environment settings. The real benefit comes with the ability for certain containers to update these Environment entries during runtime such as if a provider URL becomes inaccessible. I propose a JNDI Property Placehold Configurer which will do java:comp/env/ lookups to fill in the appropriate property values.

Example usage would be as follows:

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<constructor-arg index="0">
<props>
<prop key="java.naming.factory.initial">${java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${java.naming.provider.url}</prop>
<prop key="java.naming.factory.url.pkgs">${java.naming.factory.url.pkgs}</prop>
</props>
</constructor-arg>
</bean>
I will attach a working version I have been using for several months now.


Attachments:

Issue Links:

  • #5690 Configurer that resolves placeholders as environment entries ("is duplicated by")
  • #12693 Register JndiPropertySource by default in StandardPortletEnvironment

10 votes, 6 watchers

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 12, 2007

Arthur commented

A working implementation which looks for values under the "java:comp/env/" namespace.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 22, 2007

Dave Syer commented

It might be simpler to provide a JndiPropertiesFactoryBean that scans java:/comp/env/ (by default) and constructs a set of java.util.Properties. This could then be plugged into the normal PropertyPlaceholderConfigurer, or indeed anywhere else that properties can be used.

N.B. the implementation could use JndiTemplate to avoid having to do the resource management of the InitialContext.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 23, 2007

Arthur commented

Good idea. I will work on an implementation and submit the source. Your development team can use it as a starting point or roll its own version.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 26, 2007

Arthur commented

Here is my implementation of the recommended solution. If no jndiName is specified, the default container prefix is used (given by JndiLocatorSupport) as the base path to scan for String properties. You can set a maximum depth in the JNDI directory hierarchy to scan for properties. There is also an override policy for conflicting CompositeNames - either the deepest or shallowest composite name will win a spot in the Properties map.

Feel free to use this as a starting point.

Testing:
I tested this implementation using Tomcat 5.5.x. I deployed one of my spring based web applications. My context contained the following ResourceLinks to global Environment entries.

<ResourceLink global="jdbc/ds1" name="jdbc/fis" type="javax.sql.DataSource" />
<ResourceLink name="java.naming.factory.initial" global="globalJbossInitialContextFactory" type="java.lang.String" />
<ResourceLink name="java.naming.provider.url" global="globalJbossProviderUrl" type="java.lang.String" />
<ResourceLink name="java.naming.factory.url.pkgs" global="globalJbossUrlPkgPrefixes" type="java.lang.String" />

My applicationContext contained the following bean definitions - notice that the JndiTemplate picks up the provider URL from the container now and we do not have to maintain separate applicationContext's for each provider url.

<bean id="jndiProperties" class="org.springframework.jndi.JndiPropertiesFactoryBean" />
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<constructor-arg index="0" ref="jndiProperties" />
</bean>

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 13, 2009

Laurie Chan commented

I pushed Arthur's implementation a little further to add JNDI awareness to a normal PropertyPlaceHolderConfigurer (ie can soure placeHolder values from JNDI as well as property files, System properties etc)

and intercepted the setLocations() and setLocation() methods to allow placeHolders in the location names (because the useCase that started me looking was exactly this: wanting to specify the location of my propertyPlaceHolderConfiguer and other config files in JNDI)

Hopefully the code will be attached just after this comment....

An example JNDI setting:

<Environment 
  name="configDirectory"
  type="java.lang.String"
  value="\path\to\my\config-directory\for-this-environment" />
<bean
    id="propertyPlaceholderConfigurer"    class="org.springframework.beans.factory.config.JndiAwarePropertyPlaceholderConfigurer"
    init-method="initialize">
    <property
      name="locations">
      <list>
        <value>file:${configDirectory}/../common.properties
        </value>
        <value>file:${configDirectory}/application.properties
        </value>
      </list>
    </property>
  </bean>
@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 2, 2010

nicolas de loof commented

nice contribution

I'd suggest to implement InitializingBean to avoid the init-method="initialize"

I'm using a combination of JndiAwarePropertyPlaceholderConfigurer + JndiPropertiesFactoryBean to use my JNDI env-entry as

  • configurable path for PlaceHolder locations
  • placeholder for other beans that require configurable path (typically, building commons-configuration bean) :
<bean
  class="org.springframework.beans.factory.config.JndiAwarePropertyPlaceholderConfigurer"
  init-method="initialize"
  p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE"
  p:jndiPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE"
  p:ignoreResourceNotFound="true">
  <property name="locations">
    <list>
      <value>classpath:default.properties</value>
      <value>file:///${app.home}/local.properties
      </value>
    </list>
  </property>
  <property name="properties">
    <bean class="org.springframework.jndi.JndiPropertiesFactoryBean" />
  </property>
</bean>
 <bean id="configuration"
  class="org.apache.commons.configuration.CompositeConfiguration">
  <constructor-arg type="java.util.Collection">
    <list>
      <bean class="org.apache.commons.configuration.PropertiesConfiguration">
        <constructor-arg type="java.net.URL" value="file:///${app.home}/local.properties"/>
      </bean>
    </list>
  </constructor-arg>    
</bean>
@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 23, 2010

Stephane Toussaint commented

I work slightly differently on my projects :
I don't expect my customer to update for instance the Tomcat Context.xml in order to add a new Environment entry in order to add/override placeHolder values.
Instead, I add in the very same context an entry which provides the path to a properties file :

<Context ...>
    ...
    <Environment type="java.lang.String" name="my.properties" value="/.../user.properties"/>
    ...
</Context>

Then I implements a JndiResourceResolver which does the lookup and return the Resource

<bean class="my.JndiResourceResolver">
    <property name="jndiName" value="java:comp/env/my.properties"/>
</bean>

AFAIC, I'd like to have something like this directly integrated by Spring. A sort of

<context:property-placeholder location="classpath:default.properties, jndi-java:comp/env/my.properties" />

Maybe it is another way to achieve what this issue expects ?

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 17, 2011

Yuri Ch commented

Try this solution. It works for me:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath:file_a.properties</value>
<value>classpath:file_b.properties</value>
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/JndiPropertyNameReferringToTheFileLocation" />
<property name="resourceRef" value="false" />
<property name="defaultObject" value="/default/file/location" />
</bean>
</constructor-arg>
</bean>
</list>
</property>
</bean>

.... and JNDI context ...
<Environment description="Environment specific property"
name="JndiPropertyNameReferringToTheFileLocation"
type="java.lang.String"
value="/etc/my-application/config.properties"/>

voila!

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 11, 2011

Chris Beams commented

Much of the functionality described by this issue should be handled by the new PropertySource abstraction released with Spring 3.1 M1. In particular, I'd like to hear feedback from those still interested in this issue about JndiPropertySource. It is an initial and basic implementation right now; I'd like to hear exactly what folks need to round it out.

For an introduction to the new property management mechanism, take a look at http://blog.springsource.com/2011/02/15/spring-3-1-m1-unified-property-management. Feel free to comment here; I'll leave the issue open until we release 3.1 M2 (probably a few weeks from now).

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 26, 2011

Chris Beams commented

Resolving as Won't Fix - superseded by functionality in JndiPropertySource and PropertySourcesPlaceholderConfigurer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.