Проверка бина весенней загрузки - PullRequest
1 голос
/ 19 февраля 2020

В моем проекте Spring Boot у меня есть класс POJO для чтения файла конфигурации yaml.

@Configuration
@ConfigurationProperties("filenet")
@Data
public class ApplicationConfig {
    @NotNull(message = "Input directory cannot be null")
    @NotBlank(message = "Input directory cannot be blank")
    private String **inputDir**;
    @NotNull(message = "Working directory cannot be null")
    @NotBlank(message = "Working directory cannot be blank")
    private String **workingDir**;
    @Pattern(regexp = "[0-9]+",message = "Invalid value for SMTP port")
    private String port;
}

Иногда бывает так, что inputDir или workingDir или другие поля конфигурационного файла не заполнены. Я использую javax.validation.constraints для проверки на пустое или нулевое значение. Когда это так, и когда приложение запускается, я вижу сообщение об исключении, и программа завершается. Например: Порт имеет подтверждение того, что это должен быть номер. То, что я хотел бы сделать, это изящно обработать это исключение и отправить электронное письмо заинтересованной команде, чтобы позаботиться о нем.

Я создал класс, в котором я проверяю содержимое файла конфигурации

@Component
public class ConfigParamValidation {

    public List<String>  validateApplicationConfigFile(ApplicationConfig applicationConfig) {

        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<ApplicationConfig.ContentEngine>> contentEngineVoilations = validator.validate(applicationConfig.contentEngine);

        exceptionMessgae = contentEngineVoilations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());

        if(!exceptionMessgae.isEmpty()) {
            through new ConfigFileException(<by passing all required params>);
        }
    }
}

Я пытался создать класс, который расширяет RuntimeException

public class ConfigFileException extends RuntimeException {

    private String message;
    private List<String> details;
    private String hint;
    private String nextActions;
    private String support;
    private HttpStatus httpStatus;
    private ZonedDateTime zonedDateTime;

    public ConfigFileException(String message) {
        super(message);
    }

    public ConfigFileException(String message, Throwable cause) {
        super(message, cause);
    }

    public ConfigFileException(String message, Throwable cause, List<String> details, String hint, String nextActions, String support, HttpStatus httpStatus, ZonedDateTime zonedDateTime) {
        super(message, cause);

        this.message = message;
        this.details=details;
        this.hint=hint;
        this.nextActions=nextActions;
        this.support=support;
        this.httpStatus=httpStatus;
        this.zonedDateTime = zonedDateTime;
    }
}

Другой класс с @ ExceptionHandler

@Data
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SupportTeamException {

    @ExceptionHandler(value = {ConfigFileException.class})
    public ResponseEntity<Object> handleConfigFileException(ConfigFileException e) {
        ConfigFileException configFileException = new ConfigFileException(e.getMessage(), e, e.getDetails(), e.getHint(), e.getNextActions(), e.getSupport(), e.getHttpStatus(), e.getZonedDateTime());
        return new ResponseEntity<Object>(configFileException,e.getHttpStatus());
    }
}

Проблема в том, что по какой-то причине управление не передается Мой класс SupportTeamException, куда я мог бы отправить электронное письмо.

Или есть лучший способ справиться с этим?

1 Ответ

1 голос
/ 23 февраля 2020

Насколько я понимаю, @ControllerAdvice работает только для компонентов, помеченных @Controller или @RestController.

, поскольку проверка происходит при запуске приложения с весенней загрузкой (а не как результат запроса http), он никогда не будет go в него. Что вы можете сделать, это создать Компонент с методом @PostConstructor. (См. Ниже). Я бы настоятельно рекомендовал внедрить ваш Validator, а не создавать его самостоятельно (чтобы использовать весь потенциал Spring Boot).

Что я не до конца понимаю, так это почему вы захотите обработать это исключение изящно. Если ваше приложение запускается без требуемых свойств, оно просто не будет работать дальше, когда приложение фактически использует это свойство. Если в зависимости от обстоятельств (например, среды) некоторые свойства не обязательно должны быть там, я бы порекомендовал использовать Группы проверки

Наконец, небольшое в стороне @NotBlank также проверит, что это не так значение NULL. Вам не нужны обе аннотации, если вы не хотите точно указывать c со своими сообщениями.

package com.yourpackage;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import java.util.Set;

import static java.util.stream.Collectors.joining;

@Component
public class PropertiesValidator {

    private final Validator validator;
    public final YourProperties properties;

    public PropertiesValidator(final Validator validator, final YourProperties properties) {
        this.validator = validator;
        this.properties = properties;
    }

    @PostConstruct
    public void propertiesShouldBeValid() {
        final Set<ConstraintViolation<YourProperties>> constraintViolations = validator.validate(properties);
        if (!constraintViolations.isEmpty()) {
            final String message = constraintViolations.stream()
                .map(ConstraintViolation::getMessage)
                .collect(joining(","));
            throw new ValidationException(message); //Or send your email
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...