diff --git a/src/main/java/com/samskivert/depot/PersistenceContext.java b/src/main/java/com/samskivert/depot/PersistenceContext.java index aac46a7..f9853db 100644 --- a/src/main/java/com/samskivert/depot/PersistenceContext.java +++ b/src/main/java/com/samskivert/depot/PersistenceContext.java @@ -181,7 +181,7 @@ public class PersistenceContext * @param conprov provides JDBC {@link Connection} instances. * @param adapter an optional adapter to a cache management system. */ - public void init (String ident, ConnectionProvider conprov, CacheAdapter adapter) + public synchronized void init (String ident, ConnectionProvider conprov, CacheAdapter adapter) { // if we have no URL for the ident, freak out now; lest confusing failure happen later String url = conprov.getURL(ident); @@ -267,10 +267,8 @@ public class PersistenceContext Class type, SchemaMigration migration) { DepotMarshaller marshaller = getRawMarshaller(type); - if (marshaller.isInitialized()) { - throw new IllegalStateException( - "Migrations must be registered before initializeRepositories() is called."); - } + marshaller.requireInitialized( + "Migrations must be registered before initializeRepositories() is called."); marshaller.registerMigration(migration); } @@ -284,10 +282,9 @@ public class PersistenceContext checkAreInitialized(); // le check du sanity DepotMarshaller marshaller = getRawMarshaller(type); try { - if (!marshaller.isInitialized()) { - // initialize the marshaller which may create or migrate the table for its - // underlying persistent object - marshaller.init(this, _meta); + // initialize the marshaller which may create or migrate the table for its underlying + // persistent object + if (marshaller.init(this, _meta)) { if (marshaller.getTableName() != null && _warnOnLazyInit) { log.warning("Record initialized lazily", "type", type.getName(), new Exception()); @@ -568,10 +565,11 @@ public class PersistenceContext /** * Looks up and creates, but does not initialize, the marshaller for the specified Entity type. */ - protected DepotMarshaller getRawMarshaller (Class type) + protected synchronized DepotMarshaller getRawMarshaller ( + Class type) { - @SuppressWarnings("unchecked") DepotMarshaller marshaller = - (DepotMarshaller)_marshallers.get(type); + @SuppressWarnings("unchecked") DepotMarshaller marshaller = (DepotMarshaller) + _marshallers.get(type); if (marshaller == null) { _marshallers.put(type, marshaller = new DepotMarshaller(type, this)); } @@ -664,7 +662,7 @@ public class PersistenceContext return invoke(op, false); } - protected void checkAreInitialized () + protected synchronized void checkAreInitialized () { if (_conprov == null) { throw new IllegalStateException( diff --git a/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java b/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java index 3c1e7c2..900428f 100644 --- a/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java +++ b/src/main/java/com/samskivert/depot/impl/DepotMarshaller.java @@ -456,27 +456,22 @@ public class DepotMarshaller implements QueryMarshal } /** - * Returns true if this marshaller has been initialized ({@link #init} has been called), its - * migrations run and it is ready for operation. False otherwise. + * Throws {@link IllegalStateException} with {@code msg} if this marshaller is not initialized. */ - public boolean isInitialized () - { - return _meta != null; + public synchronized void requireInitialized (String msg) { + if (_meta == null) throw new IllegalStateException(msg); } /** - * Initializes the table used by this marshaller. This is called automatically by the {@link - * PersistenceContext} the first time an entity is used. If the table does not exist, it will - * be created. If the schema version specified by the persistent object is newer than the - * database schema, it will be migrated. + * Initializes the table used by this marshaller if it has not yet been done. If the table does + * not exist, it will be created. If the schema version specified by the persistent object is + * newer than the database schema, it will be migrated. + * @return true if initialization was performed, false if it has already been performed. */ - public void init (PersistenceContext ctx, DepotMetaData meta) + public synchronized boolean init (PersistenceContext ctx, DepotMetaData meta) throws DatabaseException { - if (_meta != null) { // sanity check - throw new IllegalStateException( - "Cannot re-initialize marshaller [type=" + _pClass + "]."); - } + if (_meta != null) return false; _meta = meta; final SQLBuilder builder = ctx.getSQLBuilder(new DepotTypes(ctx, _pClass)); @@ -488,7 +483,7 @@ public class DepotMarshaller implements QueryMarshal // if we have no table (i.e. we're a computed entity), we have nothing to create if (getTableName() == null) { - return; + return true; } // figure out the list of fields that correspond to actual table columns and generate the @@ -522,7 +517,7 @@ public class DepotMarshaller implements QueryMarshal if (Boolean.getBoolean("com.samskivert.depot.verifyschema")) { checkForStaleness(TableMetaData.load(ctx, getTableName()), ctx, builder); } - return; + return true; } // check whether migrations are allowed by our context @@ -530,7 +525,7 @@ public class DepotMarshaller implements QueryMarshal case WARN: log.warning(_pClass.getName() + " requires migration, which is disallowed. " + "Failures may be encountered later."); - return; + return true; case FAIL: throw new DatabaseException( _pClass.getName() + " requires migration, which is disallowed."); @@ -577,6 +572,7 @@ public class DepotMarshaller implements QueryMarshal // and update our version in the schema version table _meta.updateVersion(getTableName(), _schemaVersion); expectedDbVersion = _schemaVersion; + return true; } finally { // set our migrating version back to zero