You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/07/31 12:59:52 UTC

[3/9] isis git commit: ISIS-1182: fixing issue with the schema not being created (because our CreateSchemaObjectFromClassMetadata listener wasn't being called by DN)...

ISIS-1182: fixing issue with the schema not being created (because our CreateSchemaObjectFromClassMetadata listener wasn't being called by DN)...

... the reason being that the FastClasspathScanner, when it finds entities (in RegisterEntities), was then loading them via the ClassLoader.  These classes, being enhanced, registered themselves with DN's internal EnhancementHelper#registerClass(...) - a static method.  Somewhere along the line (perhaps because of the probe that DataNucleusApplicationComponents does to determine if it is running with a SchemaAwareStoreManager) it ended up so that DN knew about the entitiy when the PersistenceManagerFactory was created.  Consequently (per other tickets raised recently on the DN JIRA), this meant that our listener was not called.

The fix is to use a different API in RegisterEntities that returns only the names of the classes that are annotated with @PersistenceCapable, and not the Class<?> themselves.  This has a further benefit that the Class<?> aren't loaded, and neither do we bother to populate Isis' SpecificationLoader.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/f6244c11
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/f6244c11
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/f6244c11

Branch: refs/heads/master
Commit: f6244c11a7bd7a1bfba92e61c5d1ea6adbf2c6f3
Parents: a678b9b
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jul 30 18:28:50 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jul 30 18:28:50 2015 +0100

----------------------------------------------------------------------
 ...scoveryServiceUsingFastClasspathScanner.java |  6 +-
 .../org/apache/isis/applib/util/ScanUtils.java  | 32 +++++++--
 ...ataNucleusPersistenceMechanismInstaller.java | 23 ++-----
 .../jdo/service/RegisterEntities.java           | 68 ++++++--------------
 4 files changed, 51 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f6244c11/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java
index cdf4b5c..9ad28d4 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java
@@ -50,8 +50,10 @@ public class ClassDiscoveryServiceUsingFastClasspathScanner
     @Programmatic
     @Override
     public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix) {
-        final Set<Class<? extends T>> classes = Sets.newLinkedHashSet();
-        return ScanUtils.scanForSubclassesOf(Collections.singletonList(packagePrefix), type);
+        return Sets.newLinkedHashSet(
+                ScanUtils.scanForSubclassesOf(
+                        Collections.singletonList(packagePrefix),
+                        type));
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f6244c11/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java b/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java
index 872a62c..904ce6b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java
@@ -20,9 +20,8 @@ package org.apache.isis.applib.util;
 
 import java.lang.annotation.Annotation;
 import java.util.List;
-import java.util.Set;
 
-import com.google.common.collect.Sets;
+import com.google.common.collect.Lists;
 
 import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
 import io.github.lukehutch.fastclasspathscanner.matchprocessor.ClassAnnotationMatchProcessor;
@@ -32,8 +31,9 @@ public class ScanUtils {
 
     private ScanUtils(){}
 
-    public static <T extends Annotation> Set<Class<?>> scanForAnnotation(final List<String> packagePrefixList, final Class<T> annotationClass) {
-        final Set<Class<?>> classes = Sets.newLinkedHashSet();
+    public static <T extends Annotation> Iterable<Class<?>> scanForClassesWithAnnotation(
+            final List<String> packagePrefixList, final Class<T> annotationClass) {
+        final List<Class<?>> classes = Lists.newArrayList();
         new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
                 .matchClassesWithAnnotation(annotationClass,
                         new ClassAnnotationMatchProcessor() {
@@ -45,10 +45,17 @@ public class ScanUtils {
                 .scan();
         return classes;
     }
-    public static <T> Set<Class<? extends T>> scanForSubclassesOf(final List<String> packagePrefixList, final Class<T> annotationClass) {
-        final Set<Class<? extends T>> classes = Sets.newLinkedHashSet();
+
+    public static <T extends Annotation> Iterable<String> scanForNamesOfClassesWithAnnotation(
+            final List<String> packagePrefixList, final Class<T> annotationClass) {
+        final FastClasspathScanner scanner = scanner(packagePrefixList);
+        return scanner.getNamesOfClassesWithAnnotation(annotationClass);
+    }
+
+    public static <T> Iterable<Class<? extends T>> scanForSubclassesOf(final List<String> packagePrefixList, final Class<T> superClass) {
+        final List<Class<? extends T>> classes = Lists.newArrayList();
         new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
-                .matchSubclassesOf(annotationClass,
+                .matchSubclassesOf(superClass,
                         new SubclassMatchProcessor<T>() {
                             @Override
                             public void processMatch(final Class<? extends T> matchingClass) {
@@ -58,4 +65,15 @@ public class ScanUtils {
                 .scan();
         return classes;
     }
+
+    public static <T> Iterable<String> scanForNamesOfSubclassesOf(final List<String> packagePrefixList, final Class<T> superClass) {
+        final FastClasspathScanner scanner = scanner(packagePrefixList);
+        return scanner.getNamesOfSubclassesOf(superClass);
+    }
+
+    public static FastClasspathScanner scanner(final List<String> packagePrefixList) {
+        return new FastClasspathScanner(packagePrefixList.toArray(new String[] {})).scan();
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f6244c11/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
index 9abcb70..50ce240 100644
--- a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
+++ b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
@@ -18,14 +18,10 @@
  */
 package org.apache.isis.objectstore.jdo.datanucleus;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.google.common.collect.Sets;
-
 import org.datanucleus.PropertyNames;
 import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
 import org.slf4j.Logger;
@@ -35,7 +31,6 @@ import org.apache.isis.core.commons.components.Installer;
 import org.apache.isis.core.commons.config.InstallerAbstract;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
 import org.apache.isis.core.runtime.installerregistry.installerapi.PersistenceMechanismInstaller;
@@ -48,9 +43,7 @@ import org.apache.isis.objectstore.jdo.metamodel.facets.object.auditable.Auditab
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.datastoreidentity.JdoDatastoreIdentityAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.discriminator.JdoDiscriminatorAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.embeddedonly.JdoEmbeddedOnlyAnnotationFacetFactory;
-import org.apache.isis.objectstore.jdo.metamodel.facets.object.embeddedonly.JdoEmbeddedOnlyFacet;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableAnnotationFacetFactory;
-import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.query.JdoQueryAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.version.JdoVersionAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.prop.column.BigDecimalDerivedFromJdoColumnAnnotationFacetFactory;
@@ -125,7 +118,7 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
             final Map<String, String> datanucleusProps = dataNucleusConfig.asMap();
             addDataNucleusPropertiesIfRequired(datanucleusProps);
 
-            final Set<String> classesToBePersisted = catalogClassesToBePersisted(configuration, getSpecificationLoader().allSpecifications());
+            final Set<String> classesToBePersisted = catalogClassesToBePersisted(configuration);
 
             applicationComponents = new DataNucleusApplicationComponents(jdoObjectstoreConfig, datanucleusProps, classesToBePersisted);
         }
@@ -133,17 +126,9 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
         return applicationComponents;
     }
 
-    private static Set<String> catalogClassesToBePersisted(final IsisConfiguration configuration, Collection<ObjectSpecification> objectSpecs) {
-        final RegisterEntities registerEntities = new RegisterEntities();
-        registerEntities.init(configuration.asMap());
-        
-        Set<String> classNames = Sets.newTreeSet();
-        for (final ObjectSpecification spec : objectSpecs) {
-            if(spec.containsFacet(JdoPersistenceCapableFacet.class) || spec.containsFacet(JdoEmbeddedOnlyFacet.class)) {
-                classNames.add(spec.getFullIdentifier());
-            }
-        }
-        return Collections.unmodifiableSet(classNames);
+    private static Set<String> catalogClassesToBePersisted(
+            final IsisConfiguration configuration) {
+        return new RegisterEntities(configuration.asMap()).getEntityTypes();
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/f6244c11/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/service/RegisterEntities.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/service/RegisterEntities.java b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/service/RegisterEntities.java
index da2ba1b..1e02568 100644
--- a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/service/RegisterEntities.java
+++ b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/service/RegisterEntities.java
@@ -22,8 +22,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
 import javax.jdo.annotations.PersistenceCapable;
 
 import com.google.common.base.Function;
@@ -32,16 +30,14 @@ import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.util.ScanUtils;
-import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
-import org.apache.isis.core.runtime.system.context.IsisContext;
 
-@Hidden
 public class RegisterEntities {
 
     @SuppressWarnings("unused")
@@ -49,54 +45,35 @@ public class RegisterEntities {
     
     public final static String PACKAGE_PREFIX_KEY = "isis.persistor.datanucleus.RegisterEntities.packagePrefix";
 
-    // //////////////////////////////////////
-
     private String packagePrefixes;
 
-    @PostConstruct
-    public void init(Map<String,String> configuration) {
+    public RegisterEntities(final Map<String, String> configuration) {
         packagePrefixes = configuration.get(PACKAGE_PREFIX_KEY);
         if(Strings.isNullOrEmpty(packagePrefixes)) {
             throw new IllegalStateException("Could not locate '" + PACKAGE_PREFIX_KEY + "' key in property files - aborting");
         }
         
-        registerAllPersistenceCapables();
-    }
-
-    @PreDestroy
-    public void shutdown() {
+        discoverAllPersistenceCapables();
     }
 
-    private void registerAllPersistenceCapables() {
+    private void discoverAllPersistenceCapables() {
 
         final List<String> packagePrefixList = Lists.newArrayList(Iterables.transform(Splitter.on(",").split(packagePrefixes), trim()));
         for (final String packagePrefix : packagePrefixList) {
 
-            final Set<Class<?>> entityTypes = ScanUtils.scanForAnnotation(packagePrefixList, PersistenceCapable.class);
-            if(noEntitiesIn(entityTypes)) {
+            final Iterable<String> entityTypes = ScanUtils.scanForNamesOfClassesWithAnnotation(packagePrefixList, PersistenceCapable.class);
+            if(notEmpty(entityTypes)) {
                 throw new IllegalStateException("Could not locate any @PersistenceCapable entities in package " + packagePrefix);
             }
-            for (Class<?> entityType : entityTypes) {
-                if(ignore(entityType)) {
-                    // ignore (probably a testing class)
-                    continue;
-                }
-                getSpecificationLoader().loadSpecification(entityType);
-            }
+            this.entityTypes = Sets.newLinkedHashSet(entityTypes);
         }
     }
 
-    private static boolean ignore(final Class<?> entityType) {
-        try {
-            if(entityType.isAnonymousClass() || entityType.isLocalClass() || entityType.isMemberClass()) {
-                return true;
-            }
-            final PersistenceCapable persistenceCapable = entityType.getAnnotation(PersistenceCapable.class);
-            final boolean hasPersistenceCapable = persistenceCapable != null;
-            return !hasPersistenceCapable; // don't ignore if has @PersistenceCapable
-        } catch (NoClassDefFoundError ex) {
-            return true;
-        }
+    private Set<String> entityTypes;
+
+    @Programmatic
+    public Set<String> getEntityTypes() {
+        return entityTypes;
     }
 
     private static Function<String,String> trim() {
@@ -111,26 +88,17 @@ public class RegisterEntities {
     /**
      * legacy from using <tt>org.reflections.Reflections</tt> that seems to return a set with 1 null element if none can be found.
      */
-    private static boolean noEntitiesIn(Set<Class<?>> entityTypes) {
-        return Iterables.filter(entityTypes, nullClass()).iterator().hasNext();
+    private static <T> boolean notEmpty(Iterable<T> set) {
+        return Iterables.filter(set, isNull()).iterator().hasNext();
     }
 
-    private static Predicate<Class<?>> nullClass() {
-        return new Predicate<Class<?>>() {
-
+    private static <T> Predicate<T> isNull() {
+        return new Predicate<T>() {
             @Override
-            public boolean apply(Class<?> input) {
+            public boolean apply(T input) {
                 return input == null;
             }
         };
     }
 
-    // //////////////////////////////////////
-
-    SpecificationLoaderSpi getSpecificationLoader() {
-        return IsisContext.getSpecificationLoader();
-    }
-
-
-    
 }