spring - prod - Cómo establecer el perfil del entorno de la primavera activa 3.1 a través de un archivo de propiedades y no a través de una propiedad env o propiedad del sistema
spring profiles active prod (4)
En web.xml
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>profileName</param-value>
</context-param>
Uso de WebApplicationInitializer
Este enfoque se usa cuando no tiene un archivo web.xml
en el entorno Servlet 3.0 y está arrancando Spring completamente desde Java:
class SpringInitializer extends WebApplicationInitializer {
void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.getEnvironment().setActiveProfiles("profileName");
rootContext.register(SpringConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
}
}
Donde la clase SpringConfiguration
está anotada con @Configuration
.
Usamos la nueva característica de perfiles de entorno de la primavera 3.1. Actualmente establecemos el perfil activo configurando la variable de entorno spring.profiles.active = xxxxx en el servidor en el que implementamos la aplicación.
Creemos que esta es una solución subóptima ya que el archivo de guerra que queremos implementar solo debe tener un archivo de propiedades adicional que establece el entorno en el que se debe cargar el contexto de la aplicación de primavera para que la implementación no dependa de un conjunto de env var en el servidor.
Traté de descubrir cómo hacer eso y encontré:
ConfigurableEnvironment.setActiveProfiles()
que puedo usar para establecer programáticamente el perfil, pero aún no sé dónde y cuándo ejecutar este código. ¿En algún lugar donde el contexto de primavera se carga? ¿Puedo cargar el parámetro que quiero pasar al método desde un archivo de propiedades?
ACTUALIZACIÓN: acabo de encontrar en docs que podría implementar para configurar el perfil activo?
Aquí hay una variación del enfoque P13nApplicationContextInitializer. Sin embargo, esta vez obtenemos la ruta a las propiedades env de JNDI. En mi caso, establecí una variable de entorno global JNDI como coacorrect / spring-profile = file: /tmp/env.properties
- En tomcat / tomee server.xml agregue esto:
<Environment name="coacorrect/spring-profile" type="java.lang.String" value="/opt/WebSphere/props"/>
- Además, en tomcat / tomee, agregue a WAR META-INF / context.xml
<ResourceLink global="coacorrect/spring-profile" name="coacorrect/spring-profile" type="java.lang.String"/>
En cualquier contenedor, agregue el apropiado en web.xml
public class SpringProfileApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{ public static final Logger log = LoggerFactory.getLogger(SpringProfileApplicationContextInitializer.class); private static final String profileJNDIName="coacorrect/spring-profile"; private static final String failsafeProfile="remote-coac-dbserver"; @Override public void initialize(ConfigurableApplicationContext applicationContext) { ConfigurableEnvironment environment = applicationContext.getEnvironment(); try { InitialContext ic = new InitialContext(); Object r1 = ic.lookup(profileJNDIName); if (r1 == null) { // try the tomcat variant of JNDI lookups in case we are on tomcat/tomee r1 = ic.lookup("java:comp/env/"+profileJNDIName); } if (r1 == null) { log.error("Unable to locate JNDI environment variable {}", profileJNDIName); return; } String profilePath=(String)r1; log.debug("Found JNDI env variable {} = {}",r1); environment.getPropertySources().addFirst(new ResourcePropertySource(profilePath.trim())); log.debug("Loaded COAC dbprofile path. Profiles defined {} ", Arrays.asList(environment.getDefaultProfiles())); } catch (IOException e) { // it''s ok if the file is not there. we will just log that info. log.warn("Could not load spring-profile, defaulting to {} spring profile",failsafeProfile); environment.setDefaultProfiles(failsafeProfile); } catch (NamingException ne) { log.error("Could not locate JNDI variable {}, defaulting to {} spring profile.",profileJNDIName,failsafeProfile); environment.setDefaultProfiles(failsafeProfile); } }
}
La respuesta de Thomasz es válida siempre que el nombre del perfil se pueda proporcionar estáticamente en web.xml o uno use el nuevo tipo de configuración sin XML donde uno podría cargar programáticamente el perfil para establecerlo desde un archivo de propiedades.
Como todavía usamos la versión XML investigué más y encontré la siguiente buena solución en la que implementa su propio ApplicationContextInitializer
donde acaba de agregar un nuevo PropertySource con un archivo de propiedades a la lista de fuentes para buscar configuraciones de configuración específicas del entorno. en el siguiente ejemplo, se podría establecer la propiedad spring.profiles.active
en el archivo env.properties
.
public class P13nApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static Logger LOG = LoggerFactory.getLogger(P13nApplicationContextInitializer.class);
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
try {
environment.getPropertySources().addFirst(new ResourcePropertySource("classpath:env.properties"));
LOG.info("env.properties loaded");
} catch (IOException e) {
// it''s ok if the file is not there. we will just log that info.
LOG.info("didn''t find env.properties in classpath so not loading it in the AppContextInitialized");
}
}
}
Luego debe agregar ese inicializador como parámetro al ContextLoaderListener
of spring de la siguiente manera a su web.xml
:
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>somepackage.P13nApplicationContextInitializer</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
También puede aplicarlo a DispatcherServlet
:
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextInitializerClasses</param-name>
<param-value>somepackage.P13nApplicationContextInitializer</param-value>
</init-param>
</servlet>
Por alguna razón, solo una forma funciona para mí
public class ActiveProfileConfiguration implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.setProperty(AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME, "dev");
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
}
....
<listener>
<listener-class>somepackahe.ActiveProfileConfiguration</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>