diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java index a5fee9f19..c027a5271 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/MetaDataRepositoryValue.java @@ -35,9 +35,7 @@ public class MetaDataRepositoryValue extends PluginValue { private static final String KEY = "MetaDataRepository"; - private static final String PRELOAD_STR = "Preload=true"; - private static final String NOLOCK_STR = "NoLock=true"; - + public MetaDataRepositoryValue() { super(KEY, false); String[] aliases = new String[] { @@ -49,25 +47,6 @@ public class MetaDataRepositoryValue setString(aliases[0]); } - public boolean getPreload() { - String p = getProperties(); - if (p != null && p.indexOf(PRELOAD_STR) >= 0) { - return true; - } else if (getNoLock() == true) { - // No locking implies that we need to also preload. - // Return true regardless of the value of the - // preload flag. - return true; - } - return false; - } - public boolean getNoLock(){ - String p = getProperties(); - if (p != null && p.indexOf(NOLOCK_STR) >= 0) { - return true; - } - return false; - } public Object instantiate(Class type, Configuration c, boolean fatal) { MetaDataRepository repos = null; OpenJPAConfiguration conf = (OpenJPAConfiguration) c; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java index f0fbca84d..90a95aaea 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java @@ -333,7 +333,7 @@ public class OpenJPAConfigurationImpl mapping = addString("Mapping"); metaFactoryPlugin = addPlugin("MetaDataFactory", false); - metaRepositoryPlugin = (MetaDataRepositoryValue)addValue(new MetaDataRepositoryValue()); + metaRepositoryPlugin = addValue(new MetaDataRepositoryValue()); connectionFactory = addObject("ConnectionFactory"); connectionFactory.setInstantiatingGetter("getConnectionFactory"); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java index df75dd339..b8d90b194 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AbstractBrokerFactory.java @@ -60,6 +60,7 @@ import org.apache.openjpa.meta.MetaDataModes; import org.apache.openjpa.meta.MetaDataRepository; import org.apache.openjpa.util.GeneralException; import org.apache.openjpa.util.InvalidStateException; +import org.apache.openjpa.util.MetaDataException; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; import org.apache.openjpa.writebehind.WriteBehindCache; @@ -163,21 +164,24 @@ public abstract class AbstractBrokerFactory _conf.getConnectionRetainModeConstant(), false).close(); } - // This logic needs to happen here for a reason! The preloading of the MDR - // can not happen during the configuration of the MDR because when running - // in a container environment we need to be able to get an uninitialized - // MDR to pass to the PCClassFileTransformer. If we preload before registering + // This eager metadata loading is invoked at construction. + // It can not happen during the MetaDataRepository configuration because + // within a container environment an uninitialized repository must be passed + // to the PCClassFileTransformer. If we attempt to load before registering // the class transformer, we miss the class being defined by the JVM and in turn // we fail to enhance our entities. - OpenJPAConfigurationImpl impl = (OpenJPAConfigurationImpl) config; - MetaDataRepositoryValue m = impl.metaRepositoryPlugin; - if (m.getPreload() == true) { - // Obtain a reference to the MetaDataRepository and trigger the preload + try { MetaDataRepository mdr = config.getMetaDataRepositoryInstance(); mdr.preload(); + } catch (MetaDataException e) { + // recognize metadata related error if using early initialization + throw e; + } catch (Throwable t) { + // swallow other errors because merely trying to obtain a repository + // may trigger a database connection + _conf.getConfigurationLog().error(_loc.get("factory-init-error",t)); } - - initWriteBehindCallback(); + initWriteBehindCallback(); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java index 575ffd45a..dce6cf3d3 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java @@ -274,32 +274,58 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con _sourceMode &= ~mode; } + /** + * Sets whether this repository will load all known persistent classes at initialization. + * Defaults to false. + */ + public boolean getPreload() { + return _preload; + } + + /** + * Sets whether this repository will load all known persistent classes at initialization. + * Defaults to false. + */ public void setPreload(boolean l) { _preload = l; } + /** + * Sets whether this repository will use unguarded access. Unguarded access + * can be safe if all metadata has been loaded at initialization. + */ public void setNoLock(boolean l) { _noLock = l; } + + /** + * Affirms whether this repository will use unguarded access. Unguarded access + * can be safe if all metadata has been loaded at initialization. + */ + public boolean getNoLock() { + return _noLock; + } /** + * Loads all the known persistent classes if {@linkplain #setPreload(boolean) early loading} + * initialization has been set. The configuration must enlist all classes. + * + *
+ * If {@linkplain #setNoLock(boolean) no lock} has been set then uses unguarded access to + * all internal data container structures. * If the openjpa.MetaDataRepository plugin value preload=false is set, this method will noop. - * If preload=true this method gets the list of persistent classes and calls to the - * MetaDataFactory to load ALL metadata. *

- * - * If noLock=true, calling this method will also remove ALL locking from this class. - *

- * * NOTE : This method is not thread safe and should ONLY be called by the AbstractBrokerFactory * constructor. + * + * @see #getPersistentTypeNames(boolean, ClassLoader) */ public void preload() { - if (_preload == false) { + if (!_preload) { return; } - if (_log.isTraceEnabled()) { - _log.trace("MetaDataRepository preload=" + _preload + ",noLock=" + _noLock); + if (_log.isInfoEnabled()) { + _log.info(_loc.get(_noLock ? "repos-preload" : "repos-preload-nolock")); } // Remove locking and use unsynchronized maps. @@ -319,15 +345,14 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con MultiClassLoader multi = AccessController.doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction()); multi.addClassLoader(AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction())); multi.addClassLoader(AccessController.doPrivileged(J2DoPrivHelper - .getClassLoaderAction(MetaDataRepository.class))); + .getClassLoaderAction(MetaDataRepository.class))); Set classes = getPersistentTypeNames(false, multi); if (classes == null || classes.size() == 0) { - throw new RuntimeException("No persistent classes listed when trying to preload the MetaDataRepository"); + throw new MetaDataException(_loc.get("repos-preload-none")); } - if (_log.isTraceEnabled() == true) { - _log.trace(MetaDataRepository.class.getName() - + " preloading the following classes : " + classes.toString()); + if (_log.isTraceEnabled()) { + _log.trace(_loc.get("repos-preloading", this.getClass().getName(), classes.toString())); } for (String c : classes) { @@ -335,12 +360,9 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con Class cls = AccessController.doPrivileged((J2DoPrivHelper.getForNameAction(c, true, multi))); _factory.load(cls, MODE_ALL, multi); } catch (PrivilegedActionException pae) { - // Unexpected! - if (_log.isTraceEnabled() == true) { - _log.trace(MetaDataRepository.class.getName() + " encountered an unexpected exception ", pae); - } + throw new MetaDataException(_loc.get("repos-preload-error"), pae); } - }// end for + } } protected void lock() { diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index 1f0e8a7a8..af50e5288 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -187,6 +187,8 @@ dup-load: Cannot load object with id "{0}". Instance "{1}" with the same id \ bad-id-value: The given value "{0}" cannot be converted into an identity \ for "{2}". The value is the wrong type ({1}). factory-init: Starting OpenJPA {0} +factory-init-error: Error during initialization of configured properties: "{0}"\ + The initialization will continue. factory-properties: Properties: {0} inverse-consistency: An inverse inconsistency in the object model was \ detected while flushing the field "{0}" of the instance with id "{1}" \ diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties index 495b3d3bc..e4e62958d 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties @@ -336,5 +336,15 @@ unexpected_proxy_sm_attribute_type: Unexpected attribute type "{1}" for \ inherited class(es) are packaged in the same jar file. meta-no-model: Meta class "{0}" for entity {1} can not be registered with \ following exception "{2}" -no-mapped-by-in-mapped-super: Persistent relationship {0} defined by a mapped superclass {1} must be \ - unidirectional. \ No newline at end of file +no-mapped-by-in-mapped-super: Persistent relationship {0} defined by a mapped \ + superclass {1} must be unidirectional. +repos-preload: Metadata is loaded during initialization. The persistent classes \ + must be enlisted in configuration to be loaded during initialization. +repos-preload-nolock: Metadata is loaded during initialization with unguarded access. \ + The persistent classes must be enlisted in configuration to be loaded during \ + initialization. +repos-preload-none: No persistent metadata found for loading during initialization. \ + The persistent classes must be enlisted in configuration to be loaded during initialization. +repos-preloading: Following metadata are being loaded during initialization by "{0}": {1}. +repos-preload-error: Unexpected error during early loading during initialization. \ + See nested stacktrace for details. \ No newline at end of file diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configuration.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configuration.java index 708f6a4e7..dc9749d63 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configuration.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configuration.java @@ -158,7 +158,8 @@ public interface Configuration * Add the given value to the set of configuration properties. This * method replaces any existing value under the same property. */ - public Value addValue(Value val); + public T addValue(T val); + //public Value addValue(Value val); /** * Remove the given value from the set of configuration properties. diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java index 0342c654b..c40497059 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java @@ -994,7 +994,7 @@ public class ConfigurationImpl return true; } - public Value addValue(Value val) { + public T addValue(T val) { _vals.add(val); val.addListener(this); return val;