Configuration:
Spring 2.5, Junit 4, Log4j
The log4j file location is specified from a system property
${log.location}
At runtime, system property set with -D java option. All is well.
Problem / What I Need:
At unit test time, system property not set, and file location not resolved.
App uses Spring, would like to simply configure Spring to set the system property.
More Info:
Requirement is for configuration only. Can't introduce new Java code, or entries into IDE. Ideally, one of Spring's property configuration implementations could handle this--I just haven't been able to find the right combination.
This idea is close, but needs to add Java code:
Spring SystemPropertyInitializingBean
Any help out there? Any ideas are appreciated.
Spring Boot does that itself in its LoggingSystem where various logging. * properties are mapped to System properties. Note that you'll probably want to set the system properties as early as possible, probably as soon as the Environment is prepared.
Environment-Specific Properties File. If we need to target different environments, there's a built-in mechanism for that in Boot. We can simply define an application-environment. properties file in the src/main/resources directory, and then set a Spring profile with the same environment name.
There was a request in the comments for a Spring 3 example on how to do this.
<bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject" value="#{@systemProperties}" /> <property name="targetMethod" value="putAll" /> <property name="arguments"> <!-- The new Properties --> <util:properties> <prop key="java.security.auth.login.config">/super/secret/jaas.conf</prop> </util:properties> </property> </bean>
You can achieve that with the combination of two MethodInvokingFactoryBeans
Create an inner bean that accesses System.getProperties and an outer bean that invokes putAll on the properties acquired by the inner bean:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject"> <!-- System.getProperties() --> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetClass" value="java.lang.System" /> <property name="targetMethod" value="getProperties" /> </bean> </property> <property name="targetMethod" value="putAll" /> <property name="arguments"> <!-- The new Properties --> <util:properties> <prop key="my.key">myvalue</prop> <prop key="my.key2">myvalue2</prop> <prop key="my.key3">myvalue3</prop> </util:properties> </property> </bean>
(You could of course use just one bean and target System.setProperties(), but then you'd be replacing existing properties which is not a good idea.
Anyway, here's my little test method:
public static void main(final String[] args) { new ClassPathXmlApplicationContext("classpath:beans.xml"); System.out.println("my.key: "+System.getProperty("my.key")); System.out.println("my.key2: "+System.getProperty("my.key2")); System.out.println("my.key3: "+System.getProperty("my.key3")); // to test that we're not overwriting existing properties System.out.println("java.io.tmpdir: "+System.getProperty("java.io.tmpdir")); }
And here's the output:
my.key: myvalue my.key2: myvalue2 my.key3: myvalue3 java.io.tmpdir: C:\DOKUME~1\SEANFL~1\LOKALE~1\Temp\
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With