Мне было поручено создать аннотацию для пользовательской проверки. Это было связано с некоторыми проблемами с handling database constraint violations nicely. Что я сделал в ответ на это было относительно просто. Я создал CustomConstraint на уровне класса специально для одного домена-класса, который этого требовал. Что я, как мой текущий результат заключается в следующем:Пользовательская проверка аннотации представляет ConcurrentModificationException
@UniqueLocation Аннотация:
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueLocationValidator.class)
@Documented
public @interface UniqueLocation {
String message() default "must be unique!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Это не зрелищно, на самом деле он копируется почти дословно из hibernate documentation.
I протекала для создания моего UniqueLocationValidator
и столкнулся с проблемой использования контекста персистентности. Я хотел запустить защитный отбор и, таким образом, попытался применить широкомасштабное приложение @Produces @PersistenceContext EntityManager
.
Therefor Я включил JBoss Seam использовать это InjectingConstraintValidatorFactory
настройки моего validation.xml следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">
<constraint-validator-factory>
org.jboss.seam.validation.InjectingConstraintValidatorFactory
</constraint-validator-factory>
</validation-config>
После запуска в некоторых вопросах с Creating Constraint Violations это как мой валидатор выглядит на самом деле:
@ManagedBean
public class UniqueLocationValidator implements
ConstraintValidator<UniqueLocation, Location> {
// must not return a result for name-equality on the same Id
private final String QUERY_STRING = "SELECT * FROM Location WHERE locationName = :value AND id <> :id";
@Inject
EntityManager entityManager;
private String constraintViolationMessage;
@Override
public void initialize(final UniqueLocation annotation) {
constraintViolationMessage = annotation.message();
}
@Override
public boolean isValid(final Location instance,
final ConstraintValidatorContext context) {
if (instance == null) {
// Recommended, instead use explicit @NotNull Annotation for
// validating non-nullable instances
return true;
}
if (duplicateLocationExists(instance)) {
createConstraintViolations(context);
return false;
} else {
return true;
}
}
private void createConstraintViolations(
final ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(constraintViolationMessage)
.addNode("locationName").addConstraintViolation();
}
private boolean duplicateLocationExists(final Location location) {
final String checkedValue = location.getLocationName();
final long id = location.getId();
Query defensiveSelect = entityManager.createNativeQuery(QUERY_STRING)
.setParameter("value", checkedValue).setParameter("id", id);
return !defensiveSelect.getResultList().isEmpty();
}
}
Так что для моей текущей конфигурации, теперь к настоящей говядине, проблема:
Когда я запускаю следующий код после r ecieving действие от потребителя, вещь работает чудесно и правильно маркирует дублированное имя места как недействительное. Также упорствует работает как раз отлично когда имя места не дублируется.
public long add(@Valid final Location location) {
entityManager.persist(location);
return location.getId();
}
ум, что entityManager
здесь и entityManager
в UniqueLocationValidator оба вводят через Weld CDI от вышеупомянутого @PersistenceContext EntityManager.
Что не работает, состоит в следующем:
public long update(@Valid final Location location){
entityManager.merge(location);
return location.getId();
}
При вызове этого кода я получаю относительно короткий StackTrace, который имеет ConcurrentModificationException
как первопричин.
Я не понимаю, почему это так, и как я могу это исправить. Я нигде не пытался явно использовать многопоточное мое приложение, поэтому это должно было управляться JBoss 7.1.1-Final, которое я использую в качестве сервера приложений.