Cómo hacer condicional una aplicación de inicio de primavera terminan en la puesta en marcha

Marko Previsic:

Quiero poner en práctica el siguiente caso de uso - mi solicitud de inicio de primavera debería comenzar sólo si una determinada propiedad en application.yaml se establece:

myapp
    active: true

Si la propiedad no está definida, la inicialización de contexto debe fallar con un mensaje de que la propiedad no se encuentra.

He encontrado en este tema cómo lograrlo: Primavera de arranque - Detectar y terminará si no se establece la propiedad? pero el problema por qué no puedo seguir este enfoque es que es posible que el contexto de inicialización falla antes de que el grano, que los cheques de esta propiedad, se carga.

Por ejemplo, si algún otro frijol no se puede cargar porque otra propiedad no está presente, la inicialización de contexto fallará en ese momento y mi frijol, que comprueba la propiedad deseada, no se cargarán. Esto no es bueno para mí porque quiero que el myapp.active propiedad que se comprueba en primer lugar, antes que cualquier otro frijol se cargan.

La razón por la que quiero tener de esa manera es que un determinado perfil debe ser conjunto cuando se ejecuta la aplicación - la aplicación- [perfil] .yaml contiene tanto "myapp.active: true" y algunas otras propiedades obligatorias que se requieren para la carga el contexto.

Quiero mi aplicación siempre fallo debido a la myapp.active no ser verdad para que yo puede dar salida a un mensaje revelador significativo que el perfil no está y que la aplicación debe ejecutarse con uno de los perfiles (de la lista dada de perfiles). Algunos chicos que no son desarrolladores están ejecutando la aplicación, así que quiero que sepan por qué la aplicación no se ha ejecutado, de lo contrario se piensa que hay algunos errores en la aplicación.

¿Cómo puedo conseguir esto? ¿Es posible de alguna manera a leer la propiedad antes de que los granos se están cargando? Me gustaría evitar el establecimiento de @DependsOn en todos los granos (o hacer lo mismo a través de un BeanPostProcesser) y estoy en busca de una solución más elegante.

Dirk Put:

La aplicación no se iniciará si se utiliza una condición-en-propiedad. ¿Suficientemente rapido?

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

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

}

Básicamente @SpringBootApplicationes sólo una @Configurationclase.

Tiene una opción matchIfMissingque se puede utilizar para especificar si la condición debe coincidir si la propiedad no está establecida. Por defecto es falsa.

EDITAR:

Una mejor solución es configurar su propiedad a través de una @ConfigurationPropertiescombinación con @Validated, por lo que puede utilizar las anotaciones 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;
  }

}

Nota: se puede dejar de lado @ConditionalOnProperty(name = "myapp.active")

utilizar @AssertTrueen combinación con @NotNulldebido @AssertTrueconsidera elementos nulos como válido.

y la primavera-arranque genera un buen mensaje de error de forma gratuita:

***************************
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

EDITAR (tras pregunta actualizada)


Una forma más rápida: su aplicación no arranca, ni se le carga un contexto de aplicación

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

}

EDITAR

otra solución que probablemente se adapte a sus necesidades mejor ...

Al escuchar la ApplicationEnvironmentPreparedEvent

Evento publicado cuando un SpringApplication {@ link} está empezando y el Medio Ambiente * {@ link} está disponible por primera vez para la inspección y modificación. *

Nota: No se puede utilizar una @EventListener, pero hay que añadir el oyente a 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);
  }

}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=224003&siteId=1
Recomendado
Clasificación