using a <jee:jndi-lookup string inside an instance of PropertyPlaceholderConfigurer - spring

Environment: Windows server 2003, Spring 3.0, Tomcat 6
How can I reference a JNDI property inside a PropertyPlaceholderConfigurer?
Specifically, I'm using JNDI to look up a java.lang.String that represents a path to
a property file needed by my webapp
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<array>
<value>how to use mypropsfile1 here ??</value>
<value>how to use mypropsfile2 here ??</value>
</array>
</property>
</bean>
My "jee:jndi-lookup"s are working AFAIK. My problem seems to be how to reference JNDI resources
inside the tag pair
Thanks in advance!
Mark

Your approach may not work Mark, this is because PropertyPlaceHolderConfigurer is a BeanFactoryPostProcessor and gets invoked at the point when the bean definitions are created, whereas the jndi lookup happens post this stage.
I saw an older Spring forum discussion item, which has a recommendation for an approach of using a jndi lookup based properties file, which may suit your needs:

I believe you will have to do something like this . I haven't tested it but basically the setLocations method in PropertyPlaceholderConfigurer takes in an array of Resource(In our case UrlResource - http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/core/io/UrlResource.html) which in turn has a constructor with the file path .
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" default-value="file:///C:/defaultPath" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="mypropsfile1,mypropsfile2">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="mypropsfile1"/></constructor-arg>
</bean>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="myPropsFile2"/></constructor-arg>
</bean>
</list>
</property>
</bean>
I am not sure if there is a tag called in spring . Check this http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-introduction

I do this in Spring 3 using a map as follows:
<jee:jndi-lookup id="myJndiLookup" jndi-name="com.techtrip.spring.config.myJndiLookup"></jee:jndi-lookup>
<bean id="somethingWithMap" class="com.techtrip.foo.SomethingWithMap">
<property name="propMap">
<map>
<entry key="myJndiLookup" value-ref="myJndiLookup" />
</map>
</property>
</bean>
This works fine in most cases. You may run into trouble if you use AOP or something that wraps the bean in a Proxy class even if you set eager init correctly. A solution in that case is to directly access the somethingWithMap bean from the app context when needed using:
applicationContext.getBeansOfType(type, includeNonSingletons, allowEagerInit);
*Note that this will return a Map<String, T> where you can access the bean by name.

Not exactly for a single JNDI property, this is using a Properties reference instead, obtained through JNDI:
<!-- Lookup Properties reference through JNDI -->
<jee:jndi-lookup id="config-properties" jndi-name="resources/resource-name" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="config-properties">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<!-- Once the reference is obtained from JNDI, it can be used like any other reference -->
<property name="properties" ref="config-properties"></property>
</bean>

Related

Reading JNDI name from external properties file in Spring

I am developing a Spring web application where I am using JMS as well as some datasource connection.
Now Instead of hardcoding the JNDI names of DataSource/Jms Connection Factory,I want to read them from a external properties file.
I used the following configuration::
<bean id="myProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath*:myFile"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
`<jee:jndi-lookup` id="dataSource" jndi-name="${DS_JNDI}" expected-type="javax.sql.DataSource"/>
But during deployment time it is throwing an error in weblogic:::
javax.naming.NameNotFoundException: Unable to resolve '${DS_JNDI}'. Resolved ''; remaining name '${DS_JNDI}'
Is it like that I cannot put a property file entry when using <jee:jndi-lookup>???
you should remove the star after classpath, and add properties of file extension
<bean id="myProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:myFile.properties"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:myFile.properties</value>
</list>
</property>
</bean>
This is the correct solution of the problem.I think from Spring5.x onwards it has stopped appending ".properties" extension.

context:property-placeholder how to reference the property bean

We have this existing property loader configuration in our spring context
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<util:list>
<value>hedging-service.properties</value>
</util:list>
</property>
</bean>
<!--Hedging properties bean that can be injected into other beans-->
<util:properties id="hedgingProperties" location="classpath:hedging-service.properties"/>
and there is a bean which references the hedgingProperties bean
<bean id="mailProcessor"
class="a.b.c.MailProcessor">
<property name="properties" ref="hedgingProperties"/>
...
</bean>
I'm refactoring the context to load from multiple property files and also avoid the duplicate definition of the properties. My first attempt is to use this bean in place of the two above
<context:property-placeholder location="classpath:hedging-service-core.properties,classpath:hedging-service.properties,classpath:icon.properties"/>
but how can I retain the alias or reference to the hedgingProperties bean when I use the context:property-placeholder?
The answer is a mixture context:property-placeholder and util:properties
<util:properties id="hedgingProperties" location="classpath:hedging-service.properties"/>
<context:property-placeholder properties-ref="hedgingProperties" />
<bean id="mailProcessor" class="a.b.c.MailProcessor">
<property name="properties" ref="hedgingProperties"/>
...
</bean>

Several PropertyPlaceholderConfigurers with spring

I have a strange problem with my spring bean definition. My application is a multi-module thing.
At the moment I have a project named core-lib which has a spring.xml file defining a PropertyPlaceholderConfigurer like this:
<bean id="corePropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="10" />
<property name="locations">
<list>
<!-- default properties files containing ALL possible properties -->
<value>classpath:default.connection.properties</value>
<value>classpath:default.mq.properties</value>
<!-- installation specific, optional properties file containing overridden properties -->
<value>classpath:connection.properties</value>
<value>classpath:mq.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
Second I have a depending project which has its own spring.xml file including the one from the core-lib project. Moreover it defines a second PropertyPlaceholderConfigurer like this:
<!-- import configuration from service layer -->
<import resource="classpath:spring.xml"/>
<bean id="commPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="20" />
<property name="locations">
<list>
<!-- properties files containing ALL possible properties -->
<value>classpath:processing.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
Now I have the behavior that a bean defined in this second spring PlaceholderConfigurer can't be instantiated due to missing properties:
BeanDefinitionStoreException: Invalid bean definition with name 'commServer' defined in class path resource [comm-server.spring.xml]: Could not resolve placeholder 'comm.server.CommServer.port'
If I set a breakpoint in the PropertyPlaceholderConfigurer class it only get's triggered for the first bean instance and never for the second. Has anyone had a similar setup and can give me some advice?
Thanks,
Sebastian
There is a more comfortable way by defining a new placeholder prefix and suffix:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:configuration.properties</value>
</property>
<property name="placeholderPrefix" value="myprefix{" />
<property name="placeholderSuffix" value="}" />
</bean>
Found here: http://javalibs.blogspot.co.at/2008/04/java-spring-framework-multiple.html
OK I resolved that myself, although I do not understand why this is working so strange.
I have defined a different prefix in the second placeholder (?{ instead of ${) and now its working. I had expected that this would work without any special prefixes...

using JNDI lookup of properties to determine spring import

I am trying to import a properties file to determine which import I need.
I have looked at the following and they don't seem to have the exact answer:
http://blog.springsource.com/2011/02/15/spring-3-1-m1-unified-property-management/
http://stackoverflow.com/questions/1520055/import-spring-config-file-based-on-property-in-properties-file
they are close but not exactly what I'm looking for.
<beans:bean id="propertiesResource" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiName="java:comp/env/url/resource/avcs" p:defaultObject="classpath:avcs.properties"/>
<beans:bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<beans:property name="location" ref="propertiesResource"/>
</beans:bean>
<context:property-placeholder properties-ref="propertiesResource" system-properties-mode="ENVIRONMENT"/>
<beans:import resource="applicationContext.${application.context.import}.xml"/>
So I need to use the JNDI look-up to get the file and then load the properties then import the specific application context.
If I were to use the property-placeholder with just a class path resource then all would be well I believe but in this situation I need to do the JNDI look up first, and it seem the orfer of precedence puts the import before the JNDI.
Any chance anyone out there has an answer for me?
I have a few other ideas but I just wanted to see if there was anyone that might already have tackled this.
Thanks in advance.
I believe you will have to do something like this . I haven't tested it but basically the setLocations method in PropertyPlaceholderConfigurer takes in an array of Resource(In our case UrlResource - http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/core/io/UrlResource.html) which in turn has a constructor with the file path .
<jee:jndi-lookup id="mypropsfile1" jndi-name="myPropsFile1" default-value="file:///C:/defaultPath" resource-ref="true"/>
<jee:jndi-lookup id="mypropsfile2" jndi-name="myPropsFile2" resource-ref="true"/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="mypropsfile1,mypropsfile2">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="mypropsfile1"/></constructor-arg>
</bean>
<bean class="org.springframework.core.io.UrlResource">
<constructor-arg><ref bean="myPropsFile2"/></constructor-arg>
</bean>
</list>
</property>
</bean>
Check for this discussion here . The depends-on will help set the dependencies for a particular bean .

<jee:jndi-lookup default-value and the use of classpath

I am really stuck on this one... Help! :)
I am using j2ee:jndi lookup for a property file. The following works fine:
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true" />
</constructor-arg>
</bean>
However, I want to handle the case where the jndi lookup fails but will fall back on a default file located in WEB-INF/classes folder. If I use the default-value as below, the webapp throws an exception complaining that it cannot find the file "classpath:myprops.properties"
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties" />
</constructor-arg>
</bean>
However, if I hard-code a specific path for default-value, then it works fine, but that is unacceptable as a final solution.
Thus, my issue is how to use "classpath:" so that it gets properly resolved?
This is the overall usage I'm employing:
<bean id="authServerProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true"/>
<property name="location">
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties" />
</constructor-arg>
</bean>
</property>
.....
</bean>
Let Spring use its built-in PropertyEditor support to decide on the type of resource, rather than supplying an explicit FileSystemResource bean as this won't work with classpath resources (it needs to be configured with a path on the file system). Instead you should use something like
<bean id="authServerProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="ignoreResourceNotFound" value="true"/>
<property name="location" ref="myProps" />
</bean>
<jee:jndi-lookup id="myProps" jndi-name="myProps" resource-ref="true"
default-value="classpath:myprops.properties"/>
Here we are setting the location to be a string value and allowing Spring to convert that to the appropriate resource type, so if you have
<env-entry>
<env-entry-name>myProps</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>file:///Users/something/myProps.properties</env-entry-value>
</env-entry>
in your web.xml, it will use a UrlResource with the given file URL, otherwise it will create a ClasspathResource to look for the file myprops.properties.

Resources