2010-07-26 17 views
52

configuración:
Primavera 2.5, Junit 4, Log4J
La ubicación del archivo log4j se especifica desde una propiedad del sistemaEstablecer la propiedad Sistema Con la configuración de Spring Archivo

${log.location} 

En tiempo de ejecución, la propiedad del sistema configuradas con - Opción D java Todo está bien.

Problema/Lo que necesitamos:
A la hora de prueba de unidad, propiedad del sistema no fija, y la ubicación del archivo no se ha resuelto.
La aplicación utiliza Spring, desea configurar simplemente Spring en establecer la propiedad del sistema.

Más información:
El requisito es solo para la configuración. No se pueden introducir nuevos códigos Java o entradas en IDE. Idealmente, una de las implementaciones de configuración de propiedades de Spring podría manejar esto; simplemente no he podido encontrar la combinación correcta.

Esta idea está cerca, pero hay que añadir el código de Java:
Spring SystemPropertyInitializingBean

Cualquier ayuda por ahí? Cualquier idea es apreciada.

+0

pregunta relacionada con respuestas adicionales: http://stackoverflow.com/questions/11306951/how-to-set-environment-variable-or-system-property -in-spring-tests/41305482 – anre

Respuesta

54

Usted puede lograr que con la combinación de dos MethodInvokingFactoryBeans

Crear un bean de interior que accede System.getProperties y un bean exterior que invoca putAll de las propiedades adquiridas por el grano interior:

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

(Por supuesto, podría usar solo un frijol y destino System.setProperties(), pero luego estaría reemplazando propiedades existentes, lo que no es una buena idea.

De todos modos, aquí está mi pequeño método de prueba:

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")); 
} 

Y aquí está la salida:

my.key: myvalue 
my.key2: myvalue2 
my.key3: myvalue3 
java.io.tmpdir: C:\DOKUME~1\SEANFL~1\LOKALE~1\Temp\ 
+0

Gracias. Esto funciona.Problema restante: parece que log4j se inicializa dentro de otro bean que se carga antes de que estas nuevas propiedades del sistema se inicialicen. Ahora entiendo cómo forzar un pedido a la inicialización del frijol. – Steve

+1

Utilice el atributo de depende de Spring. Muchas gracias por esta respuesta ... es de oro macizo ... – HDave

+7

El resorte 3 simplifica esto al eliminar la necesidad del 2nd MethodInvokingFactoryBean. Usas SpEL y la línea del objeto objetivo se convierte en Patrick

88

Hubo una solicitud en los comentarios de un ejemplo de Primavera 3 sobre cómo hacer esto.

<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> 
+0

Agradable, gracias –

+1

Excelente. Gracias. – toolkit

+0

+1 Excelente. Cuando pienso en la cantidad de código que debería escribirse para hacer esto. A veces, Spring es magia. :-) –

10

Spring Batch tiene una clase SystemPropertyInitializer que puede ser utilizado para establecer una propiedad del sistema ligeramente más concisa, por ejemplo para forzar el registro de JBoss utilizar slf4j (con la primavera APP):

<bean id="setupJBossLoggingProperty" 
    class="org.springframework.batch.support.SystemPropertyInitializer" 
    p:keyName="org.jboss.logging.provider" p:defaultValue="slf4j"/> 

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    depends-on="setupJBossLoggingProperty" 

recuerde agregar el "depende sobre" atributo para obligar a la propiedad del sistema que primero debe ajustarse.

+0

No pude hacer que esto funcione al final. 'SystemPropertyInitializer' utiliza' afterPropertiesSet() 'que aparentemente no se llama hasta que se invoca' '. – Stewart

3

Para un enfoque conciso intento más:

<beans ... xmlns:p="http://www.springframework.org/schema/p" ...  
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" 
     p:targetObject="#{@systemProperties}" p:targetMethod="setProperty" 
     p:arguments="#{{'org.jboss.logging.provider','slf4j'}}"/> 
Cuestiones relacionadas