context:property-placeholder how to reference the property bean - spring

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>

Related

Configure JMX with Spring implementation of ehcache?

I'm trying to follow the articles here & here to implement JMX for ehCache. My app uses the Spring implementation however & the config entries below get this exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'managementService' defined in class
path resource [trs.application.finance.businessactivites.xml]:
Unsatisfied dependency expressed through constructor argument with
index 0 of type [net.sf.ehcache.CacheManager]: Could not convert
constructor argument value of type
[org.springframework.cache.ehcache.EhCacheCacheManager] to required
type [net.sf.ehcache.CacheManager]: Failed to convert value of type
'org.springframework.cache.ehcache.EhCacheCacheManager' to required
type 'net.sf.ehcache.CacheManager'; nested exception is
java.lang.IllegalStateException: Cannot convert value of type
[org.springframework.cache.ehcache.EhCacheCacheManager] to required
type [net.sf.ehcache.CacheManager]: no matching editors or conversion
strategy found
Does spring have an implementation of net.sf.ehcache.management.ManagementService I can use? If so how do I configure it so I can have JMX support for ehcache in my app.
Note, the "managementService" & "mbeanServer" beans are what I added to try & get ehcache to register with jmx. "myCacheManager" already exists in my spring config & seems to work fine, as far ehcache alone goes.
<bean id="managementService" class="net.sf.ehcache.management.ManagementService"
init-method="init"
destroy-method="dispose">
<constructor-arg ref="myCacheManager"/>
<constructor-arg ref="mbeanServer"/>
<constructor-arg index="2" value="true"/>
<constructor-arg index="3" value="true"/>
<constructor-arg index="4" value="true"/>
<constructor-arg index="5" value="true"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
<bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
</property>
</bean>
The problem is the way you wire your beans.
You do not want to use myCacheManager in the managementService, you really want to use the bean returned and passed as the cacheManager of myCacheManager.
So I suggest moving the following:
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
to a top level bean so that it can be injected in managementService.

spring replace bean name in config file with value from property file

I have a bean config file as follows
<bean id="myFactory" class="com.public.Factory">
<property name="dataSourceAdaptor" ref="${value.from.property file}Adaptor" />
</bean>
How do i achieve this.
I added the following to top of the config file
<util:properties id="myProperties" location="classpath:app.properties"/>
and then tried to refer to the value using ${} but i get an error stating ${value.from.property file}Adaptor is not a valid bean
I cannot put the whole name (xyzAdaptor) in the property file as the value in the property file is an institution and there are multiple adaptors for each institution.
for example xzyDisplayAdaptor, xyzProductAdaptor, xyzDatasourceAdaptor
The xyz client can change to say abc client and i want to be able to change the value in property file to abc and all the abc related beans will be injected.
The util:properties tag is used to create an instance of java.util.Properties. I think what you need is a PropertyPlaceholderConfigurer.
e.g.,
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" scope="singleton">
<property name="searchSystemEnvironment" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:app.properties</value>
</list>
</property>
</bean>
Try this with Spel:
<util:properties id="myProperties" location="classpath:app.properties"/>
<bean id="myFactory" class="com.public.Factory">
<property name="dataSourceAdaptor" ref="#{'${value.from.property file}'+'Adaptor'}" />
</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...

<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.

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

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>

Resources