Как передать объект сущности контроллеру из пользовательской аннотации проверки

У меня есть запрос data transfer object (DTO), который предназначен для приема тела POST API. Этот DTO имеет ключ ENUM объекта X. Я создал настраиваемую аннотацию проверки и проверяю, что ENUM существует в моей системе через его репозиторий сущностей, который возвращает сущность или ноль в зависимости от его существования.

Я хочу передать этот проверенный объект X своему контроллеру. Я не хочу снова получать эту сущность X с помощью ENUM в моей бизнес-логике, потому что я уже сделал это при проверке.

Я сохраняю этот объект в статической переменной из класса валидатора аннотаций и обращаюсь к нему позже, когда я хочу это в бизнес-логике, но если API попадает одновременно, моя статическая переменная переопределяется вторым запросом и когда моя бизнес-логика первого запроса извлекает X entity, он получает объект второго запроса из-за проблемы переопределения.

Я хочу, чтобы этот объект сущности X находился в пределах своего собственного цикла запроса и уничтожался или сборщик мусора после завершения запроса, как и другие объекты. Как я могу этого добиться?

Мой пользовательский валидатор:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidateXimpl.class)
@Documented
public @interface ValidateX {
    String message()  default "Message";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default{};
}

Реализация кастомного валидатора:

public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {

    @Autowired
    DBRepo dbRepo;

    @Override
    public void initialize(ValidateX annotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext ctx) {
        try {
            XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
            return (!value.isEmpty() && X != null);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

Мой DTO, в котором я разместил свою проверку:

public class DTO{
    ....
    @ValidateX
    String xEntityEnum
    ....
}

Мой контроллер:

@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
    // I want that entity here which I get from db repo in my validator
}

Если вы используете объект формы для получения параметров запроса, вы можете проверить поля в этом объекте, и он будет передан методу контроллера.

Jack Flamp 16.03.2018 12:25

это пример: stackoverflow.com/a/28010820/3959856

Jack Flamp 16.03.2018 12:35

Нет, я создал другой объект в моем настраиваемом валидаторе и хочу, чтобы этот объект был передан в контроллер.

Ali Raza 16.03.2018 12:56

Хмм хорошо. один из способов - просто проверить данные, а затем создать новый объект в методе get для этого поля в dto. это сработает? кстати, какой-нибудь код поможет

Jack Flamp 16.03.2018 13:21

Ваш маркированный список делает ваш вопрос нечитаемым. Пожалуйста, перефразируйте свой вопрос. Не используйте маркированный список, если вы действительно не перечисляете элементы. Для вопроса используйте обычную прозу.

Mark Rotteveel 16.03.2018 14:29

@MarkRotteveel Редактирую свой вопрос. Спасибо, что указали на это. Я позабочусь о

Ali Raza 16.03.2018 14:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
1 084
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я только что решил это с RequestContextHolder

Код решения:

Реализация валидатора

public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {

@Autowired
DBRepo dbRepo;

@Override
public void initialize(ValidateX annotation) {
}

@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
    try {
        XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
        RequestContextHolder.getRequestAttributes().setAttribute(
                "XEntity", X, RequestAttributes.SCOPE_REQUEST
        ); // I saved it in RequestContextHolder
        return (!value.isEmpty() && X != null);
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
}

Мой Контроллер

@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
     // I want that entity here which I get from db repo in my validator
    System.out.println(
            RequestContextHolder.getRequestAttributes().getAttribute(
                    "XEntity",
                    RequestAttributes.SCOPE_REQUEST
            )
    ); // I get that from RequestContextHolder
}

Это то, что мне действительно нужно. RequestContextHolder очищается при завершении запроса и также доступен только в собственном потоке запроса из-за настройки области запроса в функции setAttribute.

Другие вопросы по теме