OPENJPA-1068 Use validation mode to determine if we should setup a ValidatingLifecycleEventManager or not. Based on patch from Jeremy with one config scenario still to be addressed in OPENJPA-1111.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@780706 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Donald Woods 2009-06-01 16:26:43 +00:00
parent f90952b286
commit d4c227ef00
6 changed files with 188 additions and 47 deletions

View File

@ -26,6 +26,7 @@ import org.apache.openjpa.datacache.DataCacheManager;
import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.enhance.RuntimeUnenhancedClasssesModes;
import org.apache.openjpa.event.BrokerFactoryEventManager;
import org.apache.openjpa.event.LifecycleEventManager;
import org.apache.openjpa.event.OrphanedKeyAction;
import org.apache.openjpa.event.RemoteCommitEventManager;
import org.apache.openjpa.event.RemoteCommitProvider;
@ -1676,7 +1677,7 @@ public interface OpenJPAConfiguration
*
* @since 2.0.0
*/
public Object getValidationFactory();
public Object getValidationFactoryInstance();
/**
* Set the container or application provided ValidatorFactory instance.
@ -1685,4 +1686,18 @@ public interface OpenJPAConfiguration
* @since 2.0.0
*/
public void setValidationFactory(Object factory);
/**
* Gets the lifecycle event manager instance
*
* @since 2.0.0
*/
public LifecycleEventManager getLifecycleEventManagerInstance();
/**
* Sets the lifecycle event manager instance.
*
* @since 2.0.0
*/
public void setLifecycleEventManager(LifecycleEventManager eventMgr);
}

View File

@ -31,6 +31,7 @@ import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.enhance.PCEnhancerAgent;
import org.apache.openjpa.enhance.RuntimeUnenhancedClasssesModes;
import org.apache.openjpa.event.BrokerFactoryEventManager;
import org.apache.openjpa.event.LifecycleEventManager;
import org.apache.openjpa.event.OrphanedKeyAction;
import org.apache.openjpa.event.RemoteCommitEventManager;
import org.apache.openjpa.event.RemoteCommitProvider;
@ -155,6 +156,8 @@ public class OpenJPAConfigurationImpl
public ObjectValue specification;
public StringValue validationMode;
public ObjectValue validationFactory;
public ObjectValue lifecycleEventManager;
// custom values
public BrokerFactoryValue brokerFactoryPlugin;
@ -557,17 +560,8 @@ public class OpenJPAConfigurationImpl
queryTimeout.setDynamic(true);
// kernel can't access javax.persistence.ValidationMode enums here
// so the config will be done in PersistenceProductDerivation
validationMode = addString("javax.persistence.validation.mode");
aliases =
new String[] {
"AUTO", "auto",
"CALLBACK", "callback",
"NONE", "none"
};
validationMode.setAliases(aliases);
validationMode.setAliasListComprehensive(true);
validationMode.setDefault(aliases[0]);
validationMode.set(aliases[0]);
validationMode.setDynamic(true);
validationFactory = addObject("javax.persistence.validation.factory");
@ -575,6 +569,10 @@ public class OpenJPAConfigurationImpl
"getValidationFactoryInstance");
validationFactory.setDynamic(true);
lifecycleEventManager = addObject("LifecycleEventManager");
lifecycleEventManager.setInstantiatingGetter(
"getLifecycleEventManagerInstance");
dynamicEnhancementAgent = addBoolean("DynamicEnhancementAgent");
dynamicEnhancementAgent.setDefault("true");
dynamicEnhancementAgent.set(true);
@ -1538,11 +1536,15 @@ public class OpenJPAConfigurationImpl
}
public void setValidationMode(String mode) {
Thread.dumpStack();
validationMode.setString(mode);
}
public String getValidationMode() {
return validationMode.getString();
String mode = validationMode.getString();
if (mode == null)
mode = validationMode.getDefault();
return mode;
}
public void instantiateAll() {
@ -1601,10 +1603,6 @@ public class OpenJPAConfigurationImpl
return (FinderCache)finderCachePlugin.get();
}
public Object getValidationFactory() {
return validationFactory.get();
}
public Object getValidationFactoryInstance() {
return validationFactory.get();
}
@ -1612,10 +1610,24 @@ public class OpenJPAConfigurationImpl
public void setValidationFactory(Object factory) {
validationFactory.set(factory);
}
public LifecycleEventManager getLifecycleEventManagerInstance() {
if (lifecycleEventManager.get() == null) {
lifecycleEventManager.set(new LifecycleEventManager());
}
return (LifecycleEventManager)lifecycleEventManager.get();
}
public void setLifecycleEventManager(LifecycleEventManager eventMgr) {
lifecycleEventManager.set(eventMgr);
}
public boolean getDynamicEnhancementAgent() {
return dynamicEnhancementAgent.get();
}
public void setDynamicEnhancementAgent(boolean dynamic) {
dynamicEnhancementAgent.set(dynamic);
}
}

View File

@ -89,6 +89,7 @@ import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UnsupportedException;
import org.apache.openjpa.util.UserException;
import org.apache.openjpa.util.WrappedException;
/**
* Concrete {@link Broker}. The broker handles object-level behavior,
@ -301,7 +302,7 @@ public class BrokerImpl
_runtime = new LocalManagedRuntime(this);
if (!fromDeserialization) {
_lifeEventManager = new LifecycleEventManager();
_lifeEventManager = _conf.getLifecycleEventManagerInstance();
_transEventManager = new TransactionEventManager();
int cmode = _conf.getMetaDataRepositoryInstance().
getMetaDataFactory().getDefaults().getCallbackMode();
@ -315,7 +316,7 @@ public class BrokerImpl
// make sure to do this after configuring broker so that store manager
// can look to broker configuration; we set both store and lock managers
// before initializing them because they may each try to access the
// other in thier initialization
// other in their initialization
_store = sm;
_lm = _conf.newLockManagerInstance();
_im = _conf.newInverseManagerInstance();
@ -800,11 +801,17 @@ public class BrokerImpl
return;
OpenJPAException ce;
if (exceps.length == 1)
ce = new CallbackException(exceps[0]);
if (exceps.length == 1) {
// If the exception is already a wrapped exception throw the
// exception instead of wrapping it with a callback exception
if (exceps[0] instanceof WrappedException)
throw (WrappedException)exceps[0];
else
ce = new CallbackException(exceps[0]);
} else {
ce = new CallbackException(_loc.get("callback-err")).
setNestedThrowables(exceps);
}
if ((mode & CALLBACK_ROLLBACK) != 0 && (_flags & FLAG_ACTIVE) != 0) {
ce.setFatal(true);
setRollbackOnlyInternal(ce);

View File

@ -44,7 +44,6 @@ import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.conf.OpenJPAProductDerivation;
import org.apache.openjpa.conf.Specification;
import org.apache.openjpa.kernel.LockLevels;
import org.apache.openjpa.kernel.MixedLockLevels;
import org.apache.openjpa.lib.conf.AbstractProductDerivation;
import org.apache.openjpa.lib.conf.Configuration;
@ -57,6 +56,10 @@ import org.apache.openjpa.lib.meta.XMLMetaDataParser;
import org.apache.openjpa.lib.meta.XMLVersionParser;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.persistence.validation.ValidatorImpl;
import org.apache.openjpa.validation.Validator;
import org.apache.openjpa.validation.ValidationException;
import org.apache.openjpa.validation.ValidatingLifecycleEventManager;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@ -142,6 +145,18 @@ public class PersistenceProductDerivation
conf.lockManagerPlugin.setAlias("mixed",
"org.apache.openjpa.jdbc.kernel.MixedLockManager");
String[] aliases = new String[] {
String.valueOf(ValidationMode.AUTO),
String.valueOf(ValidationMode.AUTO).toLowerCase(),
String.valueOf(ValidationMode.CALLBACK),
String.valueOf(ValidationMode.CALLBACK).toLowerCase(),
String.valueOf(ValidationMode.NONE),
String.valueOf(ValidationMode.NONE).toLowerCase()
};
conf.validationMode.setAliases(aliases);
conf.validationMode.setAliasListComprehensive(true);
conf.validationMode.setDefault(aliases[0]);
return true;
}
@ -164,6 +179,39 @@ public class PersistenceProductDerivation
Compatibility compatibility = conf.getCompatibilityInstance();
compatibility.setFlushBeforeDetach(true);
compatibility.setCopyOnDetach(true);
} else {
// only try creating a ValidatingLifecycleEventManager if needed
if (!ValidatorImpl.skipValidation(conf.getValidationMode())) {
try {
Validator val = new ValidatorImpl(
conf.getValidationFactoryInstance(),
conf.getValidationMode());
// we have a Validator, so try to create a VLEM
conf.setLifecycleEventManager(
new ValidatingLifecycleEventManager(val));
} catch (RuntimeException e) {
if (ValidatorImpl.validationRequired(
conf.getValidationMode())) {
// fatal error - ValidationMode requires a Validator
conf.getConfigurationLog().error(
_loc.get("vlem-creation-error"), e);
// rethrow as a WrappedException
throw new ValidationException(e);
} else {
// unexpected, but validation is optional,
// so just log it as a warning
conf.getConfigurationLog().warn(
_loc.get("vlem-creation-warn"));
// if tracing, log the exception details
conf.getConfigurationLog().trace(e);
}
}
} else {
conf.getConfigurationLog().trace(
"Validation has been disabled by supplied mode.");
}
// make sure we have at least a LifecycleEventManager created
conf.getLifecycleEventManagerInstance();
}
return true;
}

View File

@ -64,53 +64,102 @@ public class ValidatorImpl extends AbstractValidator {
LifecycleEvent.BEFORE_UPDATE);
}
/**
* Is a Validator required based on the given validation mode?
* Keeping validation mode logic in a single class...
* @param mode
* @return true if a Validator is required
*/
public static boolean validationRequired(String mode) {
return String.valueOf(ValidationMode.CALLBACK).equalsIgnoreCase(mode);
}
/**
* Skip creating a Validator based on the given validation mode?
* Keeping validation mode logic in a single class...
* @param mode
* @return true if a Validator should not be created
*/
public static boolean skipValidation(String mode) {
return String.valueOf(ValidationMode.NONE).equalsIgnoreCase(mode);
}
/**
* Default constructor. Builds a default validator factory, if available
* and creates the validator.
* Returns an Exception if a Validator could not be created.
*/
public ValidatorImpl() {
// Add the default validation groups
_validatorFactory = getDefaultValidatorFactory();
if (_validatorFactory != null)
_validator = _validatorFactory.getValidator();
addDefaultValidationGroups();
initialize();
}
/**
* Type-specific constructor
* Returns an Exception if a Validator could not be created.
* @param validatorFactory Instance of validator factory to use. Specify
* null to use the default factory.
* @param mode ValdiationMode enum value
*/
public ValidatorImpl(ValidatorFactory validatorFactory,
ValidationMode mode) {
if (mode != null) {
_mode = mode;
}
if (validatorFactory != null) {
_validatorFactory = validatorFactory;
} else {
_validatorFactory = getDefaultValidatorFactory();
}
if (_validatorFactory != null)
_validator = _validatorFactory.getValidator();
addDefaultValidationGroups();
initialize();
}
/**
* Generic-type constructor
* Returns an Exception if a Validator could not be created.
* @param validatorFactory an instance to the validatorFactory
* @param mode validation mode enum as string value
*/
public ValidatorImpl(Object validatorFactory,
String mode) {
if (validatorFactory != null && validatorFactory instanceof
ValidatorFactory) {
_mode = Enum.valueOf(ValidationMode.class, mode);
if (validatorFactory != null) {
if (validatorFactory instanceof ValidatorFactory) {
_validatorFactory = (ValidatorFactory)validatorFactory;
} else {
// TODO: Add a localized exception
throw new IllegalArgumentException();
}
}
initialize();
}
/**
* Common setup code factored out of the constructors
*/
private void initialize() {
// only try setting up a validator if mode is not NONE
if (_mode != ValidationMode.NONE) {
if (_validatorFactory == null) {
_validatorFactory = getDefaultValidatorFactory();
}
_mode = Enum.valueOf(ValidationMode.class, mode);
if (_validatorFactory != null)
if (_validatorFactory != null) {
_validator = _validatorFactory.getValidator();
} else {
// TODO: Add a localized exception
throw new RuntimeException("No default ValidatorFactory");
}
// throw an exception if we have no Validator
if (_validator == null) {
// TODO: Add a localized exception
throw new RuntimeException("No Validator provider");
}
// add in default validation groups, which can be over-ridden later
addDefaultValidationGroups();
} else {
// TODO: Add a localized exception
throw new RuntimeException("No Validator should be created based " +
"on the supplied Validation Mode.");
}
}
/**
@ -126,9 +175,11 @@ public class ValidatorImpl extends AbstractValidator {
if (event != null) {
_validationGroups.put(event, vgs);
return;
}
} else {
// TODO: Add a localized exception
throw new IllegalArgumentException();
throw new IllegalArgumentException("There were no events found " +
"for the supplied group name.");
}
}
/**
@ -161,7 +212,7 @@ public class ValidatorImpl extends AbstractValidator {
* @return returns true if validating for this particular event
*/
public boolean isValidating(Integer event) {
return _validationGroups.get(event) != null;
return (_validationGroups.get(event) != null);
}
/**
@ -275,8 +326,12 @@ public class ValidatorImpl extends AbstractValidator {
// Get the default validator factory
private ValidatorFactory getDefaultValidatorFactory() {
ValidatorFactory factory =
Validation.buildDefaultValidatorFactory();
ValidatorFactory factory = null;
try {
factory = Validation.buildDefaultValidatorFactory();
} catch (javax.validation.ValidationException e) {
// no validation providers found
}
return factory;
}

View File

@ -195,4 +195,8 @@ invalid-orderBy: This is not a valid OrderBy annotation. The property or \
for "{0}".
dynamic-agent: OpenJPA dynamically loaded the class enhancer. Any classes \
that were not enhanced at build time will be enhanced when the are \
loaded by the JVM
loaded by the JVM.
vlem-creation-warn: Failed to create the optional Validation Provider.
vlem-creation-error: A fatal error occurred while trying to \
create the required Validation Provider.