Skip to content

Commit

Permalink
Close #1806 - Have to the ability to dynamically set the Validation G…
Browse files Browse the repository at this point in the history
…roup during a transaction
  • Loading branch information
exabrial authored and Jonathan S. Fisher committed Aug 12, 2024
1 parent 116033f commit ce8a62e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,21 @@ public class EntityManagerProperties {
* )
*/
public static final String COMPOSITE_UNIT_PROPERTIES = PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES;

/**
* Overrides the Bean Validation Group(s) that will execute during a prePersist event. This should be a class or class[].
*/
public static final String VALIDATION_GROUP_PRE_PERSIST = "eclipselink.validation.group.prePersist";

/**
* Overrides the Bean Validation Group(s) that will execute during a preUpdate event. This should be a class or class[].
*/
public static final String VALIDATION_GROUP_PRE_UPDATE = "eclipselink.validation.group.preUpdate";

/**
* Overrides the Bean Validation Group(s) that will execute during a preRemove event. This should be a class or class[].
*/
public static final String VALIDATION_GROUP_PRE_REMOVE = "eclipselink.validation.group.preRemove";

private static final Set<String> supportedProperties = new HashSet<String>() {

Expand All @@ -344,6 +359,9 @@ public class EntityManagerProperties {
add(PERSISTENCE_CONTEXT_COMMIT_ORDER);
add(FLUSH_CLEAR_CACHE);
add(COMPOSITE_UNIT_PROPERTIES);
add(VALIDATION_GROUP_PRE_PERSIST);
add(VALIDATION_GROUP_PRE_UPDATE);
add(VALIDATION_GROUP_PRE_REMOVE);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,20 @@
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;

import org.eclipse.persistence.config.EntityManagerProperties;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.exceptions.BeanValidationException;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;


/**
* Responsible for performing automatic bean validation on call back events.
* @author Mitesh Meswani
Expand All @@ -72,7 +75,7 @@ public BeanValidationListener(ValidatorFactory validatorFactory, Class[] groupPr

@Override
public void prePersist (DescriptorEvent event) {
// since we are using prePersist to perform validation, invlid data may get inserted into database as shown by
// since we are using prePersist to perform validation, invalid data may get inserted into database as shown by
// following example
// tx.begin()
// e = new MyEntity(...);
Expand All @@ -81,19 +84,38 @@ public void prePersist (DescriptorEvent event) {
// tx.commit();
// "invalid data" would get inserted into database.
//
// preInsert can be used to work around above issue. Howerver, the JPA spec does not itent it.
// preInsert can be used to work around above issue. However, the JPA spec does not itent it.
// This might be corrected in next iteration of spec
validateOnCallbackEvent(event, "prePersist", groupPrePersit);
Object overrideGroups = event.getSession().getParent().getProperties().get(EntityManagerProperties.VALIDATION_GROUP_PRE_PERSIST);
if (overrideGroups != null) {
if (overrideGroups instanceof Class) {
overrideGroups = new Class[] { (Class) overrideGroups };
} else if (!(overrideGroups instanceof Class[])) {
throw new BeanValidationException("prePersist validation group must be a Class or Class Array:" + overrideGroups);
}
validateOnCallbackEvent(event, "prePersist", (Class[]) overrideGroups);
} else {
validateOnCallbackEvent(event, "prePersist", groupPrePersit);
}
}

@Override
public void aboutToUpdate(DescriptorEvent event) {
Object source = event.getSource();
UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl )event.getSession();
// preUpdate is also generated for deleted objects that were modified in this UOW.
// Do not perform preUpdate validation for such objects as preRemove would have already been called.
if(!unitOfWork.isObjectDeleted(source)) {
validateOnCallbackEvent(event, "preUpdate", groupPreUpdate);
if (!unitOfWork.isObjectDeleted(source)) {
Object overrideGroups = event.getSession().getParent().getProperties().get(EntityManagerProperties.VALIDATION_GROUP_PRE_UPDATE);
if (overrideGroups != null) {
if (overrideGroups instanceof Class) {
overrideGroups = new Class[] { (Class) overrideGroups };
} else if (!(overrideGroups instanceof Class[])) {
throw new BeanValidationException("preUpdate validation group must be a Class or Class Array:" + overrideGroups);
}
validateOnCallbackEvent(event, "preUpdate", (Class[]) overrideGroups);
} else {
validateOnCallbackEvent(event, "preUpdate", groupPreUpdate);
}
}
}

Expand All @@ -104,9 +126,17 @@ public void preUpdateWithChanges(DescriptorEvent event) {

@Override
public void preRemove (DescriptorEvent event) {
if(groupPreRemove != null) { //No validation performed on preRemove if user has not explicitly specified a validation group
validateOnCallbackEvent(event, "preRemove", groupPreRemove);
}
Object overrideGroups = event.getSession().getParent().getProperties().get(EntityManagerProperties.VALIDATION_GROUP_PRE_REMOVE);
if (overrideGroups != null) {
if (overrideGroups instanceof Class) {
overrideGroups = new Class[] { (Class) overrideGroups };
} else if (!(overrideGroups instanceof Class[])) {
throw new BeanValidationException("preRemove validation group must be a Class or Class Array:" + overrideGroups);
}
validateOnCallbackEvent(event, "preRemove", (Class[]) overrideGroups);
} else if (groupPreRemove != null) { // No validation performed on preRemove if user has not explicitly specified a validation group
validateOnCallbackEvent(event, "preRemove", groupPreRemove);
}
}

private void validateOnCallbackEvent(DescriptorEvent event, String callbackEventName, Class[] validationGroup) {
Expand Down

0 comments on commit ce8a62e

Please sign in to comment.