diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/bootup/BootupClasses.java b/src/main/java/com/avaje/ebeaninternal/server/core/bootup/BootupClasses.java index d846536d8..1722d0962 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/bootup/BootupClasses.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/bootup/BootupClasses.java @@ -7,6 +7,7 @@ import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.event.BeanFindController; import com.avaje.ebean.event.BeanPersistController; import com.avaje.ebean.event.BeanPersistListener; +import com.avaje.ebean.event.BeanPostConstructListener; import com.avaje.ebean.event.BeanPostLoad; import com.avaje.ebean.event.BeanQueryAdapter; import com.avaje.ebean.event.ServerConfigStartup; @@ -41,38 +42,59 @@ public class BootupClasses implements ClassFilter { private final List> entityList = new ArrayList>(); - private final List> scalarTypeList = new ArrayList>(); + private final List>> scalarTypeList + = new ArrayList>>(); - private final List> scalarConverterList = new ArrayList>(); + private final List>> scalarConverterList + = new ArrayList>>(); - private final List> compoundTypeList = new ArrayList>(); + private final List>> compoundTypeList + = new ArrayList>>(); - private final List> idGeneratorList = new ArrayList>(); + + // The following objects are instantiiated on first request + // there is always a candidate list, that holds the class and an + // instance list, that holds the instance. Once a class is instantiiated + // (or added) it will get removed from the candidate list + private final List> idGeneratorCandidates + = new ArrayList>(); + + private final List> beanPersistControllerCandidates + = new ArrayList>(); + + private final List> beanPostLoadCandidates + = new ArrayList>(); - private final List> beanControllerList = new ArrayList>(); - - private final List> beanPostLoadList = new ArrayList>(); - - private final List> beanFindControllerList = new ArrayList>(); - private final List> beanQueryAdapterList = new ArrayList>(); - - private final List> beanListenerList = new ArrayList>(); - - private final List> serverConfigStartupList = new ArrayList>(); - private final List serverConfigStartupInstances = new ArrayList(); + private final List> beanPostConstructListenerCandidates + = new ArrayList>(); + + private final List> beanFindControllerCandidates + = new ArrayList>(); + + private final List> beanPersistListenerCandidates + = new ArrayList>(); + + private final List> beanQueryAdapterCandidates + = new ArrayList>(); + + private final List> serverConfigStartupCandidates + = new ArrayList>(); private final List idGeneratorInstances = new ArrayList(); - private final List findControllerInstances = new ArrayList(); - private final List persistControllerInstances = new ArrayList(); + private final List beanPersistControllerInstances = new ArrayList(); private final List beanPostLoadInstances = new ArrayList(); - private final List persistListenerInstances = new ArrayList(); - private final List queryAdapterInstances = new ArrayList(); - - private Class changeLogPrepareClass; - private Class changeLogListenerClass; - private Class changeLogRegisterClass; - private Class readAuditPrepareClass; - private Class readAuditLoggerClass; + private final List beanPostConstructListenerInstances = new ArrayList(); + private final List beanFindControllerInstances = new ArrayList(); + private final List beanPersistListenerInstances = new ArrayList(); + private final List beanQueryAdapterInstances = new ArrayList(); + private final List serverConfigStartupInstances = new ArrayList(); + + // single objects + private Class changeLogPrepareClass; + private Class changeLogListenerClass; + private Class changeLogRegisterClass; + private Class readAuditPrepareClass; + private Class readAuditLoggerClass; private ChangeLogPrepare changeLogPrepare; private ChangeLogListener changeLogListener; @@ -96,7 +118,7 @@ public class BootupClasses implements ClassFilter { */ public void runServerConfigStartup(ServerConfig serverConfig) { - for (Class cls : serverConfigStartupList) { + for (Class cls : serverConfigStartupCandidates) { try { ServerConfigStartup newInstance = (ServerConfigStartup) cls.newInstance(); newInstance.onStart(serverConfig); @@ -115,114 +137,90 @@ public class BootupClasses implements ClassFilter { } } + /** + * Adds the list toAdd to instances and removes any pending + * candiate, to prevent duplicate instantiiation. + */ + private void add(List toAdd, List instances, List> candidates) { + if (toAdd != null) { + for (T obj : toAdd) { + instances.add(obj); + // don't automatically instantiate + candidates.remove(obj.getClass()); + } + } + } + /** * Add IdGenerator instances (registered explicitly with the ServerConfig). */ public void addIdGenerators(List idGenerators) { - if (idGenerators != null) { - for (IdGenerator c : idGenerators) { - this.idGeneratorInstances.add(c); - // don't automatically instantiate - this.idGeneratorList.remove(c.getClass()); - } - } - } - - public void addQueryAdapters(List queryAdapterInstances) { - if (queryAdapterInstances != null) { - for (BeanQueryAdapter a : queryAdapterInstances) { - this.queryAdapterInstances.add(a); - // don't automatically instantiate - this.beanQueryAdapterList.remove(a.getClass()); - } - } + add(idGenerators, idGeneratorInstances, idGeneratorCandidates); } /** * Add BeanPersistController instances. */ - public void addPersistControllers(List beanControllerInstances) { - if (beanControllerInstances != null) { - for (BeanPersistController c : beanControllerInstances) { - this.persistControllerInstances.add(c); - // don't automatically instantiate - this.beanControllerList.remove(c.getClass()); - } - } + public void addPersistControllers(List beanControllers) { + add(beanControllers, beanPersistControllerInstances, beanPersistControllerCandidates); } /** * Add BeanPostLoad instances. */ - public void addPostLoaders(List postLoadInstances) { - if (postLoadInstances != null) { - for (BeanPostLoad c : postLoadInstances) { - this.beanPostLoadInstances.add(c); - // don't automatically instantiate - this.beanPostLoadList.remove(c.getClass()); - } - } + public void addPostLoaders(List postLoaders) { + add(postLoaders, beanPostLoadInstances, beanPostLoadCandidates); } - + /** + * Add BeanPostConstructListener instances. + */ + public void addPostConstructListeners(List postConstructListener) { + add(postConstructListener, beanPostConstructListenerInstances, beanPostConstructListenerCandidates); + } + /** * Add BeanFindController instances. */ public void addFindControllers(List findControllers) { - if (findControllers != null) { - for (BeanFindController c : findControllers) { - this.findControllerInstances.add(c); - // don't automatically instantiate - this.beanFindControllerList.remove(c.getClass()); - } - } + add(findControllers, beanFindControllerInstances, beanFindControllerCandidates); } public void addPersistListeners(List listenerInstances) { - if (listenerInstances != null) { - for (BeanPersistListener l : listenerInstances) { - this.persistListenerInstances.add(l); - // don't automatically instantiate - this.beanListenerList.remove(l.getClass()); - } - } + add(listenerInstances, beanPersistListenerInstances, beanPersistListenerCandidates); } + public void addQueryAdapters(List queryAdapters) { + add(queryAdapters, beanQueryAdapterInstances, beanQueryAdapterCandidates); + } + public void addServerConfigStartup(List startupInstances) { - if (startupInstances != null) { - for (ServerConfigStartup l : startupInstances) { - this.serverConfigStartupInstances.add(l); - // don't automatically instantiate - this.serverConfigStartupList.remove(l.getClass()); - } - } + add(startupInstances, serverConfigStartupInstances, serverConfigStartupCandidates); } public void addChangeLogInstances(ServerConfig serverConfig) { readAuditPrepare = serverConfig.getReadAuditPrepare(); readAuditLogger = serverConfig.getReadAuditLogger(); - - if (readAuditPrepare == null && readAuditPrepareClass != null) { - readAuditPrepare = (ReadAuditPrepare)create(readAuditPrepareClass, false); - } - if (readAuditLogger == null && readAuditLoggerClass != null) { - readAuditLogger = (ReadAuditLogger)create(readAuditLoggerClass, false); - } - + changeLogPrepare = serverConfig.getChangeLogPrepare(); changeLogListener = serverConfig.getChangeLogListener(); changeLogRegister = serverConfig.getChangeLogRegister(); - changeLogPrepare = serverConfig.getChangeLogPrepare(); // if not already set create the implementations found // via classpath scanning + if (readAuditPrepare == null && readAuditPrepareClass != null) { + readAuditPrepare = create(readAuditPrepareClass, false); + } + if (readAuditLogger == null && readAuditLoggerClass != null) { + readAuditLogger = create(readAuditLoggerClass, false); + } if (changeLogPrepare == null && changeLogPrepareClass != null) { - changeLogPrepare = (ChangeLogPrepare)create(changeLogPrepareClass, false); + changeLogPrepare = create(changeLogPrepareClass, false); } if (changeLogListener == null && changeLogListenerClass != null) { - changeLogListener = (ChangeLogListener)create(changeLogListenerClass, false); + changeLogListener = create(changeLogListenerClass, false); } if (changeLogRegister == null && changeLogRegisterClass != null) { - changeLogRegister = (ChangeLogRegister)create(changeLogRegisterClass, false); + changeLogRegister = create(changeLogRegisterClass, false); } } @@ -233,10 +231,10 @@ public class BootupClasses implements ClassFilter { *

* Use logOnException = true to log the error and carry on. */ - private Object create(Class cls, boolean logOnException) { + private T create(Class cls, boolean logOnException) { try { // instantiate via found class - Constructor constructor = cls.getConstructor(); + Constructor constructor = cls.getConstructor(); return constructor.newInstance(); } catch (NoSuchMethodException e) { @@ -258,13 +256,18 @@ public class BootupClasses implements ClassFilter { /** * Create the instance if it has a default constructor and add it to the list of instances. + * It clears the list of classes afterwards, so that each class in the given list is + * instantiated only once */ - @SuppressWarnings(value = "unchecked") - private void createAdd(Class cls, List instances) { - Object newInstance = create(cls, true); - if (newInstance != null) { - instances.add((T)newInstance); - } + private List createAdd(List instances, List> candidates) { + for (Class cls : candidates) { + T newInstance = create(cls, true); + if (newInstance != null) { + instances.add(newInstance); + } + } + candidates.clear(); // important, clear class list! + return instances; } public ChangeLogPrepare getChangeLogPrepare() { @@ -286,54 +289,36 @@ public class BootupClasses implements ClassFilter { public ReadAuditLogger getReadAuditLogger() { return readAuditLogger; } - - public List getBeanQueryAdapters() { - // add class registered BeanQueryAdapter to the already created instances - for (Class cls : beanQueryAdapterList) { - createAdd(cls, queryAdapterInstances); - } - return queryAdapterInstances; + + + public List getIdGenerators() { + return createAdd(idGeneratorInstances, idGeneratorCandidates); } - - public List getBeanFindControllers() { - // add class registered BeanFindController to the list of created instances - for (Class cls : beanFindControllerList) { - createAdd(cls, findControllerInstances); - } - return findControllerInstances; - } - - public List getBeanPersistListeners() { - // add class registered BeanPersistController to the already created instances - for (Class cls : beanListenerList) { - createAdd(cls, persistListenerInstances); - } - return persistListenerInstances; - } - + public List getBeanPersistControllers() { - // add class registered BeanPersistController to the already created instances - for (Class cls : beanControllerList) { - createAdd(cls, persistControllerInstances); - } - return persistControllerInstances; + return createAdd(beanPersistControllerInstances, beanPersistControllerCandidates); } public List getBeanPostLoaders() { - // add class registered BeanPostLoad to the already created instances - for (Class cls : beanPostLoadList) { - createAdd(cls, beanPostLoadInstances); - } - return beanPostLoadInstances; + return createAdd(beanPostLoadInstances, beanPostLoadCandidates); + } + + public List getBeanPostConstructoListeners() { + return createAdd(beanPostConstructListenerInstances, beanPostConstructListenerCandidates); } - public List getIdGenerators() { - for (Class cls : idGeneratorList) { - createAdd(cls, idGeneratorInstances); - } - return idGeneratorInstances; + public List getBeanFindControllers() { + return createAdd(beanFindControllerInstances, beanFindControllerCandidates); } - + + public List getBeanPersistListeners() { + return createAdd(beanPersistListenerInstances, beanPersistListenerCandidates); + } + + public List getBeanQueryAdapters() { + return createAdd(beanQueryAdapterInstances, beanQueryAdapterCandidates); + } + /** * Return the list of Embeddable classes. */ @@ -351,21 +336,21 @@ public class BootupClasses implements ClassFilter { /** * Return the list of ScalarTypes found. */ - public List> getScalarTypes() { + public List>> getScalarTypes() { return scalarTypeList; } /** * Return the list of ScalarConverters found. */ - public List> getScalarConverters() { + public List>> getScalarConverters() { return scalarConverterList; } /** * Return the list of ScalarConverters found. */ - public List> getCompoundTypes() { + public List>> getCompoundTypes() { return compoundTypeList; } @@ -391,6 +376,7 @@ public class BootupClasses implements ClassFilter { * This includes ScalarType, BeanController, BeanFinder and BeanListener. *

*/ + @SuppressWarnings("unchecked") private boolean isInterestingInterface(Class cls) { if (Modifier.isAbstract(cls.getModifiers())) { @@ -400,77 +386,87 @@ public class BootupClasses implements ClassFilter { } boolean interesting = false; - if (IdGenerator.class.isAssignableFrom(cls)) { - idGeneratorList.add(cls); - interesting = true; - } - - if (BeanPersistController.class.isAssignableFrom(cls)) { - beanControllerList.add(cls); - interesting = true; - } - - if (BeanPostLoad.class.isAssignableFrom(cls)) { - beanPostLoadList.add(cls); - interesting = true; - } - + // Types if (ScalarType.class.isAssignableFrom(cls)) { - scalarTypeList.add(cls); - interesting = true; + scalarTypeList.add((Class>) cls); + interesting = true; } if (ScalarTypeConverter.class.isAssignableFrom(cls)) { - scalarConverterList.add(cls); + scalarConverterList.add((Class>) cls); interesting = true; } if (CompoundType.class.isAssignableFrom(cls)) { - compoundTypeList.add(cls); + compoundTypeList.add((Class>) cls); + interesting = true; + } + + if (IdGenerator.class.isAssignableFrom(cls)) { + idGeneratorCandidates.add((Class) cls); + interesting = true; + } + + // "Candidates" + if (BeanPersistController.class.isAssignableFrom(cls)) { + beanPersistControllerCandidates.add((Class) cls); + interesting = true; + } + + if (BeanPostLoad.class.isAssignableFrom(cls)) { + beanPostLoadCandidates.add((Class) cls); + interesting = true; + } + + if (BeanPostConstructListener.class.isAssignableFrom(cls)) { + beanPostConstructListenerCandidates.add((Class) cls); interesting = true; } if (BeanFindController.class.isAssignableFrom(cls)) { - beanFindControllerList.add(cls); + beanFindControllerCandidates.add((Class) cls); interesting = true; - } + } if (BeanPersistListener.class.isAssignableFrom(cls)) { - beanListenerList.add(cls); + beanPersistListenerCandidates.add((Class) cls); interesting = true; } if (BeanQueryAdapter.class.isAssignableFrom(cls)) { - beanQueryAdapterList.add(cls); + beanQueryAdapterCandidates.add((Class) cls); interesting = true; } if (ServerConfigStartup.class.isAssignableFrom(cls)) { - serverConfigStartupList.add(cls); + serverConfigStartupCandidates.add((Class) cls); interesting = true; } + // single instances + // TODO: What should happen, if there is already an other + // changeLogListener assigned? (Last wins? / Exception?) if (ChangeLogListener.class.isAssignableFrom(cls)) { - changeLogListenerClass = cls; + changeLogListenerClass = (Class) cls; interesting = true; } if (ChangeLogRegister.class.isAssignableFrom(cls)) { - changeLogRegisterClass = cls; + changeLogRegisterClass = (Class) cls; interesting = true; } if (ChangeLogPrepare.class.isAssignableFrom(cls)) { - changeLogPrepareClass = cls; + changeLogPrepareClass = (Class) cls; interesting = true; } if (ReadAuditPrepare.class.isAssignableFrom(cls)) { - readAuditPrepareClass = cls; + readAuditPrepareClass = (Class) cls; interesting = true; } if (ReadAuditLogger.class.isAssignableFrom(cls)) { - readAuditLoggerClass = cls; + readAuditLoggerClass = (Class) cls; interesting = true; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java index c29a7b6e3..c382068c4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java @@ -178,8 +178,6 @@ public class DeployBeanDescriptor { private String name; - private boolean processedRawSqlExtend; - private ChangeLogFilter changeLogFilter; private String dbComment; diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java index 1bdf25101..b260d9cb7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/DefaultTypeManager.java @@ -688,22 +688,22 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { customScalarTypes.add(longToTimestamp); - List> foundTypes = bootupClasses.getScalarTypes(); + List>> foundTypes = bootupClasses.getScalarTypes(); for (int i = 0; i < foundTypes.size(); i++) { - Class cls = foundTypes.get(i); + Class> cls = foundTypes.get(i); try { ScalarType scalarType; if (objectMapper == null) { - scalarType = (ScalarType) cls.newInstance(); + scalarType = cls.newInstance(); } else { try { // first try objectMapper constructor - Constructor constructor = cls.getConstructor(ObjectMapper.class); - scalarType = (ScalarType) constructor.newInstance((ObjectMapper) objectMapper); + Constructor> constructor = cls.getConstructor(ObjectMapper.class); + scalarType = constructor.newInstance((ObjectMapper) objectMapper); } catch (NoSuchMethodException e) { - scalarType = (ScalarType) cls.newInstance(); + scalarType = cls.newInstance(); } } @@ -730,7 +730,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { @SuppressWarnings({"unchecked", "rawtypes"}) protected void initialiseScalarConverters(BootupClasses bootupClasses) { - List> foundTypes = bootupClasses.getScalarConverters(); + List>> foundTypes = bootupClasses.getScalarConverters(); for (int i = 0; i < foundTypes.size(); i++) { Class cls = foundTypes.get(i); @@ -766,7 +766,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable { protected void initialiseCompoundTypes(BootupClasses bootupClasses) { - List> compoundTypes = bootupClasses.getCompoundTypes(); + List>> compoundTypes = bootupClasses.getCompoundTypes(); for (int j = 0; j < compoundTypes.size(); j++) { Class type = compoundTypes.get(j);