Nous utilisons la nouvelle fonctionnalité de profils d'environnement du printemps 3.1. Nous définissons actuellement le profil actif en définissant la variable d'environnement spring.profiles.active = xxxxx sur le serveur sur lequel nous déployons l'application.
Nous pensons que c'est une solution sous-optimale car le fichier war que nous voulons déployer devrait simplement avoir un fichier de propriétés supplémentaire qui définit l'environnement dans lequel le contexte de l'application Spring doit se charger, de sorte que le déploiement ne dépend pas d'un ensemble de variables env sur le serveur.
J'ai essayé de comprendre comment faire cela et j'ai trouvé:
ConfigurableEnvironment.setActiveProfiles()
que je peux utiliser pour définir le profil par programme, mais je ne sais toujours pas où et quand exécuter ce code. Quelque part où le contexte printanier se charge? Puis-je charger le paramètre que je souhaite transmettre à la méthode à partir d'un fichier de propriétés?
MISE À JOUR: Je viens de trouver à docs que je pourrais être en mesure de mettre en œuvre pour définir le profil actif?
La réponse de Thomasz est valable tant que le nom du profil peut être fourni statiquement dans le web.xml ou que l'on utilise le nouveau type de configuration sans XML où l'on pourrait charger par programme le profil à définir à partir d'un fichier de propriétés.
Comme nous utilisons toujours la version XML, j'ai étudié plus en détail et trouvé la bonne solution suivante où vous implémentez votre propre ApplicationContextInitializer
où vous ajoutez simplement un nouveau PropertySource avec un fichier de propriétés à la liste des sources pour rechercher des paramètres de configuration spécifiques à l'environnement . dans l'exemple ci-dessous, on pourrait définir le spring.profiles.active
propriété dans le env.properties
fichier.
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");
}
}
}
Vous devez ensuite ajouter cet initialiseur comme paramètre au ContextLoaderListener
du ressort comme suit à votre 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>
Vous pouvez également l'appliquer à 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>
web.xml
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>profileName</param-value>
</context-param>
WebApplicationInitializer
Cette approche est utilisée lorsque vous n'avez pas de web.xml
fichier dans l'environnement Servlet 3.0 et amorce complètement Spring à partir de 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));
}
}
Où SpringConfiguration
classe est annotée avec @Configuration
.
Pour une raison quelconque, une seule façon fonctionne pour moi
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>
Voici une variante de l'approche P13nApplicationContextInitializer. Cependant, cette fois, nous obtenons le chemin d'accès aux propriétés env à partir de JNDI. Dans mon cas, j'ai défini une variable d'environnement global JNDI comme coacorrect/spring-profile = file: /tmp/env.properties
<Environment name="coacorrect/spring-profile" type="Java.lang.String" value="/opt/WebSphere/props"/>
<ResourceLink global="coacorrect/spring-profile" name="coacorrect/spring-profile" type="Java.lang.String"/>
Dans n'importe quel conteneur, ajoutez approprié dans 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);
}
}
}