web-dev-qa-db-fra.com

Comment définir le profil d'environnement Spring 3.1 actif via un fichier de propriétés et non via une variable env ou une propriété système

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?

49
Fabian

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

Dans web.xml

<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>profileName</param-value>
</context-param>

Utilisation de 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));
    }
}

SpringConfiguration classe est annotée avec @Configuration.

51
Tomasz Nurkiewicz

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>
6
Michail Nikolaev

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

  1. Dans Tomcat/tomee server.xml, ajoutez ceci: <Environment name="coacorrect/spring-profile" type="Java.lang.String" value="/opt/WebSphere/props"/>
  2. De plus, dans Tomcat/tomee, ajoutez au fichier META-INF/context.xml <ResourceLink global="coacorrect/spring-profile" name="coacorrect/spring-profile" type="Java.lang.String"/>
  3. 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);
        }
    }
    

    }

0
Jim Doyle