2012-07-31 19 views
5

Necesito tener una configuración de desarrollo y producción para nuestro proyecto de primavera. Entiendo que puede usar perfiles para la primavera, pero eso no es algo que podamos hacer.Spring loading application.properties basado en la definición de contexto de servlet de tomcat

Lo que quiero hacer es colocar en el entorno de desarrollo un archivo test-application.properties y en producción un archivo prod-application.properties. En la definición de contexto tomcat enviamos lo siguiente:

<Context> 
    <context-param> 
     <param-name>properties_location</param-name> 
     <param-value>file:C:\Users\Bill\test-application.properties</param-value> 
    </context-param> 
</Context> 

Y podemos cambiar el valor de los servidores de producción. En la configuración de la primavera tenemos algo como esto:

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> 
    <property name="locations"> 
     <list> 
      <value>${properties_location}</value> 
     </list> 
    </property> 
    <property name="ignoreUnresolvablePlaceholders" value="false" /> 
</bean> 

Pero seguimos teniendo errores como:

org.springframework.beans.factory.BeanInitializationException: Podría no cargar propiedades; la excepción jerarquizada es java.io.FileNotFoundException: No se pudo abrir recurso ServletContext [/ $ {} properties_location]

Cualquier ideas sobre cómo resolver?

Respuesta

8

Una característica de PropertyPlaceholder es que puede definir múltiples ubicaciones de recursos. Así, por ejemplo, se puede definir your-production-config.properties junto con archivo: C:/Users/$ {} user.name /test-application.properties

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations"> 
     <list> 
      <value>classpath:your-production-config.properties</value> 
      <value>file:C:/Users/${user.name}/test-application.properties</value> 
     </list> 
    </property> 
    <property name="ignoreUnresolvablePlaceholders" value="true"/> 
    <property name="ignoreResourceNotFound" value="true"/> 
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>   
</bean> 

para la producción que necesita para colocar la configuración de prod en classpath en algún lugar (realmente no es importante donde exactamente, solo classpath) - para env local puede usar convension como este archivo: C:/Users/$ {user.name} /test-application.properties

+0

Hice lo mismo pero olvidé ignorarResourceNotFound. Ahora trabaja. ¡Gracias por la respuesta! – checklist

+0

Además, como indica SYSTEM_PROPERTIES_MODE_OVERRIDE, cualquier propiedad especificada con una -D en la llamada java anulará lo que se encuentre en el archivo de propiedades, por lo que 'java -Duser.name = ted ...' tendrá prioridad. Con ignoreResourceNotFound, los archivos de propiedades también pueden estar ausentes sin lanzar una excepción. –

0

uso:

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> 
    <property name="locations"> 
     <list> 
      <value>C:/Users/Bill/test-application.properties</value> 
     </list> 
    </property> 
    <property name="ignoreUnresolvablePlaceholders" value="false" /> 
</bean> 

Retire a continuación el código de web.xml

<Context> 
    <context-param> 
     <param-name>properties_location</param-name> 
     <param-value>file:C:\Users\Bill\test-application.properties</param-value> 
    </context-param> 
</Context> 
+0

Todo mi punto es tener la ubicación del archivo de propiedades fuera del archivo guerra por lo que no se puede poner en la definición de frijol. Gracias – checklist

1

terminé resolverlo por no usar contexto params. En cambio, hemos definido

<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> 
    <property name="locations"> 
     <list> 
      <value>classpath:application.properties</value> 
      <value>file:C:\Users\Bill\prod-application.properties</value> 
     </list> 
    </property> 
    <property name="ignoreUnresolvablePlaceholders" value="true" /> 
    <property name="ignoreResourceNotFound" value="true"/> 
</bean> 

De esta manera se intenta cargar ambos archivos. En los servidores de prueba no tenemos el archivo prod, por lo que no está cargado. En el servidor de prod, el archivo prod-application.properties existe y anula la prueba que está en el classpath. Engorroso, pero funciona!

+0

Aunque esto funciona, hubiera sido bueno si la primavera tuviera una mejor solución. Estoy seguro de que hay muchas personas que implementan aplicaciones para Tomcat y quieren externalizar los accesorios. – checklist

1

Personalmente, trate de evitar especificar ubicaciones. Creo que lo mejor para ti es usar JNDI para lograr esto.

En tomcat/conf/server.xml

<Resource name="jdbc/prod" auth="Container" 
      type="javax.sql.DataSource" driverClassName="${database.driverClassName}" 
      url="${database.url}" 
      username="${database.username}" password="${database.password}" 
      maxActive="20" maxIdle="10" 
      maxWait="-1"/> 

y catalina.properties En Tomcat (Si se utiliza Oracle XE cambiar de otro modo que en consecuencia):

database.driverClassName=oracle.jdbc.driver.OracleDriver 
database.url=jdbc:oracle:thin:@//localhost:1521/XE 
database.username=user 
database.password=password 

En su solicitud de creación del archivo de propiedades tu classpath llamada jdbc.propiedades y ponen siguientes (Si se utiliza Oracle XE otra manera cambiar en consecuencia)

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver 
jdbc.url=jdbc:oracle:thin:user/[email protected]//localhost:1521/XE 

Luego, en la primavera applicationContext.xml

<context:property-placeholder location="classpath:jdbc.properties" /> 

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
    <property name="jndiName" value="java:comp/env/jdbc/prod" /> 
    <property name="defaultObject" ref="dataSourceFallback" /> 
</bean> 
<bean id="dataSourceFallback" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="poolPreparedStatements"> 
     <value>true</value> 
    </property> 
    <property name="maxActive"> 
     <value>4</value> 
    </property> 
    <property name="maxIdle"> 
     <value>1</value> 
    </property> 
</bean> 
2
<context:property-placeholder location="file:${catalina.home}/conf/myFirst.properties" ignore-unresolvable="true" /> 
<context:property-placeholder location="classpath:second.properties" ignore-unresolvable="true" /> 

lo hago como la de arriba. La variable catalina.home permite que el archivo de propiedades se recubra en el directorio conf de tomcat.

0

si está utilizando CUServidor y server.xml para configurar recursos como bases de datos, colas, etc se puede utilizar los com.springsource.tcserver.properties.SystemProperties

Delcare este escucha en server.xml, como a continuación

<Listener className="com.springsource.tcserver.properties.SystemProperties" 
      file.1="${catalina.base}/conf/password.properties" 
      file.2="${catalina.base}/conf/server.properties" 
      immutable="false" 
      trigger="now"/> 

ya se puede externalizar las propiedades de los dos archivos y password.properties server.properties.

Cuestiones relacionadas