Comment faire conditionnellement une application de démarrage de printemps se terminent au démarrage

Marko Previsic:

Je veux mettre en œuvre le cas d'utilisation suivant - ma demande de démarrage de printemps devrait commencer que si une propriété en application.yaml est définie:

myapp
    active: true

Si la propriété est pas définie, l'initialisation du contexte devrait échouer avec un message que la propriété est manquante.

J'ai trouvé dans ce sujet comment y parvenir: Spring Boot - Détecter et mettre fin si la propriété non définie? mais le problème pourquoi je ne peux pas suivre cette approche est qu'il est possible que l'initialisation du contexte échoue avant que le haricot, qui contrôle cette propriété, est chargé.

Par exemple, si un autre grain ne se charge pas, car une autre propriété est manquante, l'initialisation du contexte échouera à ce moment - là et mon haricot, qui vérifie la propriété désirée, ne seront pas chargés. Ce n'est pas bien pour moi parce que je veux la myapp.active propriété à vérifier d' abord, avant que d' autres grains se charger.

La raison pour laquelle je veux avoir cette façon est qu'un certain profil doit être réglé lors de l'exécution de l'application - le [profil] application- .yaml contient à la fois « myapp.active: true » et d'autres propriétés obligatoires qui sont nécessaires à la charge le contexte.

Je veux que mon application toujours à l'échec en raison de myapp.active ne pas être vrai pour que je puisse sortir un révélateur de message significatif que le profil est porté disparu et que l'application doit être exécutée avec un des profils (de la liste donnée des profils). Certains gars qui ne sont pas les développeurs sont en cours d'exécution de l'application, donc je veux qu'ils sachent pourquoi l'application n'a pas couru, sinon ils penseront il y a un bogue dans l'application.

Comment puis-je atteindre cet objectif? Est - il possible de lire en quelque sorte la propriété avant que les haricots sont chargés? Je voudrais éviter de mettre en @DependsOn sur tous les haricots (ou faire la même chose à travers un BeanPostProcesser) et je cherche une solution plus élégante.

Dirk Put:

L'application ne démarre pas si vous utilisez une condition sur la propriété. Assez rapide?

 @SpringBootApplication
 @ConditionalOnProperty(name = "myapp.active")
 public class FastFailWhenPropertyNotPresentApplication {

     public static void main(String[] args) {
            SpringApplication.run(FastFailWhenPropertyNotPresentApplication.class, args);
    }

}

Au fond @SpringBootApplicationest juste une @Configurationclasse.

Vous avez une option matchIfMissingque vous pouvez utiliser pour spécifier si la condition doit correspondre si la propriété est pas définie. Par défaut à false.

ÉDITER:

Une meilleure solution est de configurer votre propriété via un @ConfigurationPropertiescombiné avec @Validated, de sorte que vous pouvez utiliser les annotations de javax.validation.constraints.

package stackoverflow.demo;

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

@Component
@ConfigurationProperties(prefix = "myapp")
@Validated
public class MyAppProperties {

  @AssertTrue
  @NotNull
  private Boolean active;

  public Boolean getActive() {
    return active;
  }

  public void setActive(Boolean active) {
    this.active = active;
  }

}

Remarque: vous pouvez omettre @ConditionalOnProperty(name = "myapp.active")

utiliser @AssertTrueen combinaison avec du @NotNullfait de @AssertTrueconsidère comme éléments nuls valides.

et au printemps démarrage génère un beau message d'erreur gratuitement:

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'myapp' to stackoverflow.demo.MyAppProperties failed:

    Property: myapp.active
    Value: false
    Origin: class path resource [application.properties]:1:16
    Reason: must be true


Action:

Update your application's configuration

EDIT (après la question mise à jour)


Une façon plus rapide: l' application ne démarre pas, ni un contexte d'application sera chargée

package stackoverflow.demo;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.ClassPathResource;

@SpringBootApplication
public class FastFailWhenPropertyNotPresentApplication {

  static Boolean active;

  static {

    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
    yaml.setResources(new ClassPathResource("application.yaml"));

    active = (Boolean) yaml.getObject().getOrDefault("myapp.active", false);

  }


    public static void main(String[] args) {
        if (!active) {
          System.err.println("your fail message");
        } else {
          SpringApplication.run(FastFailWhenPropertyNotPresentApplication.class, args);
        }
    }

}

ÉDITER

une autre solution qui correspond probablement mieux à vos besoins ...

En écoutant le ApplicationEnvironmentPreparedEvent

Événement publié lorsqu'un {} @link SpringApplication commence et la * {} @link Environnement est d'abord disponible pour l'inspection et la modification. *

Note: vous ne pouvez pas utiliser @EventListener, mais il faut ajouter l'écouteur à laSpringApplication

package stackoverflow.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;

@SpringBootApplication
public class FastFailWhenPropertyNotPresentApplication {


  static class EnvironmentPrepared implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
      Boolean active = event.getEnvironment().getProperty("myapp.active",Boolean.class,Boolean.FALSE);
      if(!active) {
        throw new RuntimeException("APPLICATION FAILED TO START: ACTIVE SHOULD BE TRUE ");
      }
    }
  };


  public static void main(String[] args) throws Exception {
    SpringApplication springApplication = new SpringApplication(FastFailWhenPropertyNotPresentApplication.class);
    springApplication.addListeners(new FastFailWhenPropertyNotPresentApplication.EnvironmentPrepared());
    springApplication.run(args);
  }

}

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=223999&siteId=1
conseillé
Classement