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:50 UTC

[1/9] isis git commit: ISIS-1182: spiking using fast-classpath-scanner.

Repository: isis
Updated Branches:
  refs/heads/master c3d348088 -> 59c3b4942


ISIS-1182: spiking using fast-classpath-scanner.


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

Branch: refs/heads/master
Commit: f311839c2fecef433bfd8dd6e1e3427bc5facf64
Parents: c3d3480
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Jul 29 21:26:38 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Jul 29 21:26:38 2015 +0100

----------------------------------------------------------------------
 core/applib/pom.xml                             | 13 ++++
 ...scoveryServiceUsingFastClasspathScanner.java | 68 +++++++++++++++++
 .../ClassDiscoveryServiceUsingReflections.java  | 14 +---
 .../ServicesInstallerFromAnnotation.java        | 77 +++++++++++++++++++-
 4 files changed, 157 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f311839c/core/applib/pom.xml
----------------------------------------------------------------------
diff --git a/core/applib/pom.xml b/core/applib/pom.xml
index 2e2b100..f101151 100644
--- a/core/applib/pom.xml
+++ b/core/applib/pom.xml
@@ -168,6 +168,19 @@
             <optional>true</optional>
         </dependency>
 
+        <!-- as used by ClassDiscoveryServiceUsingFastClasspathScanner -->
+        <dependency>
+            <groupId>io.github.lukehutch</groupId>
+            <artifactId>fast-classpath-scanner</artifactId>
+            <version>1.4.1</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>junit</groupId>
+                    <artifactId>junit</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
     </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/isis/blob/f311839c/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
new file mode 100644
index 0000000..daa081a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingFastClasspathScanner.java
@@ -0,0 +1,68 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.classdiscovery;
+
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+
+import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
+import io.github.lukehutch.fastclasspathscanner.matchprocessor.SubclassMatchProcessor;
+
+/**
+ * This utility service supports the dynamic discovery of classes from the classpath.  One service that uses this
+ * is the <tt>FixtureScripts</tt> domain service.
+ *
+ */
+@DomainService(
+        nature = NatureOfService.DOMAIN
+)
+public class ClassDiscoveryServiceUsingFastClasspathScanner
+            extends AbstractService
+            implements ClassDiscoveryService2 {
+
+
+    @Programmatic
+    @Override
+    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type) {
+        throw new IllegalStateException("Shouldn't be called as this class implements ClassDiscoveryService2");
+    }
+
+    @Programmatic
+    @Override
+    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix) {
+        final Set<Class<? extends T>> classes = Sets.newLinkedHashSet();
+        new FastClasspathScanner(packagePrefix)
+                .matchSubclassesOf(type, new SubclassMatchProcessor<T>() {
+                    @Override
+                    public void processMatch(final Class<? extends T> aClass) {
+                        classes.add(aClass);
+                    }
+                })
+                .scan();
+        return classes;
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f311839c/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
index e23a48d..c9a12ba 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
@@ -26,30 +26,22 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+
 import com.google.common.collect.Lists;
+
 import org.reflections.Reflections;
 import org.reflections.scanners.SubTypesScanner;
 import org.reflections.util.ClasspathHelper;
 import org.reflections.vfs.SystemDir;
 import org.reflections.vfs.Vfs;
+
 import org.apache.isis.applib.AbstractService;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 
 /**
  * This utility service supports the dynamic discovery of classes from the classpath.  One service that uses this
  * is the <tt>FixtureScripts</tt> domain service.
- *
- * <p>
- * This service has no UI and there is only one implementation (this class) in applib, so it is annotated with
- * {@link org.apache.isis.applib.annotation.DomainService}.  This means that it is automatically registered and
- * available for use; no further configuration is required.
- * </p>
  */
-@DomainService(
-        nature = NatureOfService.DOMAIN
-)
 public class ClassDiscoveryServiceUsingReflections
             extends AbstractService 
             implements ClassDiscoveryService2 {

http://git-wip-us.apache.org/repos/asf/isis/blob/f311839c/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
index b4434d4..5bf95e0 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
@@ -25,7 +25,10 @@ import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
+
+import javax.annotation.Nullable;
 import javax.annotation.PreDestroy;
+
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
@@ -34,10 +37,14 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Sets;
+
 import org.reflections.Reflections;
 import org.reflections.vfs.Vfs;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.DomainServiceLayout;
 import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections;
@@ -46,6 +53,8 @@ import org.apache.isis.core.runtime.system.DeploymentType;
 
 import static com.google.common.base.Predicates.and;
 import static com.google.common.base.Predicates.not;
+import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
+import io.github.lukehutch.fastclasspathscanner.matchprocessor.ClassAnnotationMatchProcessor;
 
 public class ServicesInstallerFromAnnotation extends InstallerAbstract implements ServicesInstaller {
 
@@ -209,11 +218,30 @@ public class ServicesInstallerFromAnnotation extends InstallerAbstract implement
 
         final List<String> packagePrefixList = asList(packagePrefixes);
 
-        Vfs.setDefaultURLTypes(ClassDiscoveryServiceUsingReflections.getUrlTypes());
-        final Reflections reflections = new Reflections(packagePrefixList);
+        final List<Class<?>> domainServiceClassesR = Lists.newArrayList(findClassesUsingReflections(packagePrefixList));
+        final List<Class<?>> domainServiceClassesFCS = Lists.newArrayList(findClassesUsingFastClasspathScanner(packagePrefixList));
+
+        final List<Class<?>> domainServiceClasses = Lists.newArrayList(domainServiceClassesFCS);
+
+        final List<String> sortedR_orig = sortedClassNames(domainServiceClassesR);
+        final List<String> sortedR = sortedClassNames(domainServiceClassesR);
+        final List<String> sortedFCS_orig = sortedClassNames(domainServiceClassesFCS);
+        final List<String> sortedFCS = sortedClassNames(domainServiceClassesFCS);
+
+        sortedR.removeAll(sortedFCS_orig);
+        sortedFCS.removeAll(sortedR_orig);
+
+        System.out.println("in R, not in FCS:");
+        for (String s : sortedR) {
+            System.out.println("  " + s);
+        }
+
+        System.out.println("in FCS, not in R:");
+        for (String s : sortedFCS) {
+            System.out.println("  " + s);
+        }
+
 
-        final Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(DomainService.class);
-        final List<Class<?>> domainServiceClasses = Lists.newArrayList(Iterables.filter(typesAnnotatedWith, instantiatable()));
         for (final Class<?> cls : domainServiceClasses) {
 
             final String order = orderOf(cls);
@@ -226,6 +254,47 @@ public class ServicesInstallerFromAnnotation extends InstallerAbstract implement
         }
     }
 
+    public List<String> sortedClassNames(final List<Class<?>> classes) {
+        final Iterable<String> transform = Iterables.transform(classes, new Function<Class<?>, String>() {
+            @Nullable @Override public String apply(@Nullable final Class<?> input) {
+                return input.getName();
+            }
+        });
+        return Ordering.natural().sortedCopy(transform);
+    }
+
+    protected Iterable<Class<?>> findClassesUsingFastClasspathScanner(final List<String> packagePrefixList) {
+        final Set<Class<?>> classes = Sets.newLinkedHashSet();
+        new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
+                .matchClassesWithAnnotation(DomainService.class, new ClassAnnotationMatchProcessor() {
+                    @Override
+                    public void processMatch(final Class<?> aClass) {
+                        if(instantiatable().apply(aClass)) {
+                            classes.add(aClass);
+                        }
+                    }
+                })
+                .scan();
+        return classes;
+    }
+
+    protected Iterable<Class<?>> findClassesUsingFastClasspathScanner2(final List<String> packagePrefixList) {
+        final Set<Class<?>> classes = Sets.newLinkedHashSet();
+        final FastClasspathScanner scan = new FastClasspathScanner(packagePrefixList.toArray(new String[] {}))
+                .scan();
+        final List<String> namesOfClassesWithAnnotation = scan.getNamesOfClassesWithAnnotation(DomainService.class);
+
+        return classes;
+    }
+
+    protected Iterable<Class<?>> findClassesUsingReflections(final List<String> packagePrefixList) {
+        Vfs.setDefaultURLTypes(ClassDiscoveryServiceUsingReflections.getUrlTypes());
+        final Reflections reflections = new Reflections(packagePrefixList);
+
+        final Set<Class<?>> classes = reflections.getTypesAnnotatedWith(DomainService.class);
+        return Iterables.filter(classes, instantiatable());
+    }
+
     private static String orderOf(final Class<?> cls) {
         final DomainServiceLayout domainServiceLayout = cls.getAnnotation(DomainServiceLayout.class);
         String order = domainServiceLayout != null ? domainServiceLayout.menuOrder(): null;


[7/9] isis git commit: Merge branch 'ISIS-1182'

Posted by da...@apache.org.
Merge branch 'ISIS-1182'


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

Branch: refs/heads/master
Commit: fdac0fe8ab8050891f46352ef102f60a9eb2734f
Parents: c3d3480 b584c78
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 11:45:59 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 11:45:59 2015 +0100

----------------------------------------------------------------------
 .../_migration-notes_1.8.0-to-1.9.0.adoc        |   1 +
 ...1.8.0-to-1.9.0_specify-all-dom-packages.adoc |  43 ++++
 ...notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc |   2 +-
 .../src/main/asciidoc/isis-in-pictures.adoc     |  14 +-
 core/applib/pom.xml                             |   7 +-
 ...scoveryServiceUsingFastClasspathScanner.java |  59 ++++++
 .../ClassDiscoveryServiceUsingReflections.java  | 200 -------------------
 .../org/apache/isis/applib/util/ScanUtils.java  |  79 ++++++++
 .../integtestsupport/IsisSystemDefault.java     |   4 +-
 .../isis/core/metamodel/app/IsisMetaModel.java  |   7 +-
 .../services/ServicesInjectorDefault.java       | 129 ++++++++++--
 .../metamodel/services/ServicesInjectorSpi.java |  12 +-
 .../metamodel/MetaModelServiceDefault.java      |  26 ++-
 .../metamodel/spec/SpecificationLoaderSpi.java  |   3 +-
 .../specloader/ObjectReflectorDefault.java      |  28 +--
 .../metamodel/facets/ProgrammableReflector.java |   5 +
 .../services/ServicesInjectorDefaultTest.java   |   6 +-
 ...ServicesInjectorDefaultTest_usingFields.java |   3 +-
 .../ObjectReflectorDefaultTestAbstract.java     |   2 +-
 core/pom.xml                                    |  18 +-
 core/runtime/pom.xml                            |  92 +++++----
 .../PersistenceMechanismInstaller.java          |   4 +-
 .../ServicesInstallerFromAnnotation.java        |  34 +++-
 .../system/IsisSystemFixturesHookAbstract.java  |   7 +-
 .../system/persistence/PersistenceSession.java  |  29 +--
 .../persistence/PersistenceSessionFactory.java  |  37 ++--
 .../session/IsisSessionFactoryDefault.java      |  78 +-------
 .../IsisSystemAbstract.java                     |  56 ++----
 .../IsisSystemUsingInstallers.java              |   4 +-
 .../CreateSchemaObjectFromClassMetadata.java    |  81 +++++---
 ...ataNucleusPersistenceMechanismInstaller.java |  32 +--
 .../jdo/service/RegisterEntities.java           | 126 +++++-------
 .../core/runtime/context/IsisContextTest.java   |   2 +-
 ...reTransactionManager_EndTransactionTest.java |   2 +-
 ...oreTransactionManager_InstantiationTest.java |   4 +-
 ...TransactionManager_StartTransactionTest.java |   4 +-
 .../persistence/PersistenceSessionTest.java     |   7 +-
 ...onFactoryAbstractTest_init_and_shutdown.java |   2 +-
 core/unittestsupport/pom.xml                    |   6 +-
 39 files changed, 632 insertions(+), 623 deletions(-)
----------------------------------------------------------------------



[4/9] isis git commit: ISIS-1182: refactoring ownership of list of services [ABORTIVE: the simpleapp runs up, but todoapp seems to hang?]

Posted by da...@apache.org.
ISIS-1182: refactoring ownership of list of services [ABORTIVE: the simpleapp runs up, but todoapp seems to hang?]

- make ServicesInjectorDefault hold the list of services, passed into PersistenceSessionFactory via
  - IsisSystemUsingInstallers#obtainPersistenceSessionFactory
  - PersistenceMechanismInstaller#createPersistenceSessionFactory
  - IsisSystemAbstract#doCreateSessionFactory
    - should call obtainServices and pass them to #createSessionFactory
 move call to validate the services (@PostConstruct and @PreDestroy stuff):
  - relocate to ServicesInjectorSpi
  - moved from IsisSessionFactoryDefault (the validateServices method, can be made static quite easily), and don't call at end of its constructor
  - call from IsisSystemAbstract (after adding the fallback FixtureScriptsDefault service)
- in IsisSystemAbstract, inline newIsisSessionFactory, no need to be separate
- ObjectReflectorDefault, split out initAndValidate so that validation is called not in the ObjectReflector's init, but instead by:
  - IsisSystemFixturesHookAbstract, after calling sessionFactory#init()


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

Branch: refs/heads/master
Commit: 97013cb3e23e1173260c1aed61164ab40c807766
Parents: f6244c1
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 07:06:09 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 07:06:09 2015 +0100

----------------------------------------------------------------------
 .../integtestsupport/IsisSystemDefault.java     |   4 +-
 .../isis/core/metamodel/app/IsisMetaModel.java  |   7 +-
 .../services/ServicesInjectorDefault.java       | 129 ++++++++++++++++---
 .../metamodel/services/ServicesInjectorSpi.java |  12 +-
 .../metamodel/MetaModelServiceDefault.java      |  26 +++-
 .../metamodel/spec/SpecificationLoaderSpi.java  |   3 +-
 .../specloader/ObjectReflectorDefault.java      |  28 ++--
 .../metamodel/facets/ProgrammableReflector.java |   5 +
 .../services/ServicesInjectorDefaultTest.java   |   6 +-
 ...ServicesInjectorDefaultTest_usingFields.java |   3 +-
 .../ObjectReflectorDefaultTestAbstract.java     |   2 +-
 .../PersistenceMechanismInstaller.java          |   4 +-
 .../system/IsisSystemFixturesHookAbstract.java  |   7 +-
 .../system/persistence/PersistenceSession.java  |  29 ++---
 .../persistence/PersistenceSessionFactory.java  |  37 +++---
 .../session/IsisSessionFactoryDefault.java      |  78 +----------
 .../IsisSystemAbstract.java                     |  56 +++-----
 .../IsisSystemUsingInstallers.java              |   4 +-
 ...ataNucleusPersistenceMechanismInstaller.java |  17 +--
 .../jdo/service/RegisterEntities.java           |  70 +++++-----
 .../core/runtime/context/IsisContextTest.java   |   2 +-
 ...reTransactionManager_EndTransactionTest.java |   2 +-
 ...oreTransactionManager_InstantiationTest.java |   4 +-
 ...TransactionManager_StartTransactionTest.java |   4 +-
 .../persistence/PersistenceSessionTest.java     |   7 +-
 ...onFactoryAbstractTest_init_and_shutdown.java |   2 +-
 26 files changed, 279 insertions(+), 269 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemDefault.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemDefault.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemDefault.java
index 1e05f65..7a1bae9 100644
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemDefault.java
+++ b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IsisSystemDefault.java
@@ -195,14 +195,14 @@ public class IsisSystemDefault extends IsisSystemAbstract {
      * The in-memory object store (unless overridden by {@link #obtainPersistenceMechanismInstaller(IsisConfiguration)}).
      */
     @Override
-    protected PersistenceSessionFactory obtainPersistenceSessionFactory(DeploymentType deploymentType) throws IsisSystemException {
+    protected PersistenceSessionFactory obtainPersistenceSessionFactory(DeploymentType deploymentType, final List<Object> services) throws IsisSystemException {
         PersistenceMechanismInstaller installer = obtainPersistenceMechanismInstaller(getConfiguration());
         if(installer == null) {
             final DataNucleusPersistenceMechanismInstaller persistenceMechanismInstaller = new DataNucleusPersistenceMechanismInstaller();
             persistenceMechanismInstaller.setConfiguration(getConfiguration());
             installer = persistenceMechanismInstaller;
         }
-        return installer.createPersistenceSessionFactory(deploymentType);
+        return installer.createPersistenceSessionFactory(deploymentType, services);
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/app/IsisMetaModel.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/app/IsisMetaModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/app/IsisMetaModel.java
index 6c881e8..9a19e72 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/app/IsisMetaModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/app/IsisMetaModel.java
@@ -117,14 +117,15 @@ public class IsisMetaModel implements ApplicationScopedComponent {
 
         reflector = new ObjectReflectorDefault(configuration, programmingModel, facetDecorators, metaModelValidator, layoutMetadataReaders);
 
-        final ServicesInjectorDefault servicesInjector = new ServicesInjectorDefault();
-        servicesInjector.setServices(services);
+        final ServicesInjectorDefault servicesInjector = new ServicesInjectorDefault(services);
         reflector.setServiceInjector(servicesInjector);
         
         runtimeContext.injectInto(reflector);
         reflector.injectInto(runtimeContext);
 
-        validationFailures = reflector.initAndValidate();
+        reflector.initialize();
+
+        validationFailures = reflector.validate();
         runtimeContext.init();
 
         for (final Object service : services) {

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
index 1fa3dcf..c7b84b9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
@@ -23,14 +23,19 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -46,6 +51,7 @@ import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware;
 import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
+import org.apache.isis.core.metamodel.specloader.ServiceInitializer;
 
 /**
  * Must be a thread-safe.
@@ -54,6 +60,9 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
 
     private static final Logger LOG = LoggerFactory.getLogger(ServicesInjectorDefault.class);
 
+    /**
+     * This is mutable internally, but only ever exposed (in {@link #getRegisteredServices()}) as immutable.
+     */
     private final List<Object> services = Lists.newArrayList();
 
     /**
@@ -64,8 +73,8 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
 
     private final Map<Class<?>, Object> serviceByConcreteType = Maps.newHashMap();
 
-    public ServicesInjectorDefault() {
-        this(null);
+    public ServicesInjectorDefault(final List<Object> services) {
+        this(services, null);
     }
 
     /**
@@ -77,8 +86,11 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
      * </p>
      * @param injectorMethodEvaluator
      */
-    public ServicesInjectorDefault(final InjectorMethodEvaluator injectorMethodEvaluator) {
+    public ServicesInjectorDefault(final List<Object> services, final InjectorMethodEvaluator injectorMethodEvaluator) {
+        this.services.addAll(services);
         this.injectorMethodEvaluator = injectorMethodEvaluator != null ? injectorMethodEvaluator : new InjectorMethodEvaluatorDefault();
+
+        autowireServicesAndContainer();
     }
 
 //region > init, shutdown
@@ -94,19 +106,7 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
 
     //endregion
 
-    //region > setServices, replaceServices
-
-    @Override
-    public void setServices(final List<Object> services) {
-        this.services.clear();
-        addServices(services);
-        autowireServicesAndContainer();
-    }
-
-    public ServicesInjectorDefault withServices(final List<Object> services) {
-        setServices(services);
-        return this;
-    }
+    //region > replaceServices
 
     @Override
     public <T> void replaceService(final T existingService, final T replacementService) {
@@ -137,6 +137,103 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
     }
 
     @Override
+    public <T> void addFallbackIfRequired(final Class<T> serviceClass, final T serviceInstance) {
+        if(!contains(services, serviceClass)) {
+            // add to beginning;
+            // (when first introduced, this feature has been used for the
+            // FixtureScriptsDefault so that appears it top of prototyping menu; not
+            // more flexible than this currently just because of YAGNI).
+            services.add(0, serviceInstance);
+        }
+    }
+
+    /**
+     * Validate domain service Ids are unique, and that the {@link PostConstruct} method, if present, must either
+     * take no arguments or take a {@link Map} object), and that the {@link PreDestroy} method, if present, must take
+     * no arguments.
+     *
+     * <p>
+     * TODO: there seems to be some duplication/overlap with {@link ServiceInitializer}.
+     */
+    @Override
+    public void validateServices() {
+        validate(getRegisteredServices());
+    }
+
+    private static void validate(List<Object> serviceList) {
+        for (Object service : serviceList) {
+            final Method[] methods = service.getClass().getMethods();
+            for (Method method : methods) {
+                validatePostConstructMethods(service, method);
+                validatePreDestroyMethods(service, method);
+            }
+        }
+        ListMultimap<String, Object> servicesById = ArrayListMultimap.create();
+        for (Object service : serviceList) {
+            String id = ServiceUtil.id(service);
+            servicesById.put(id, service);
+        }
+        for (Map.Entry<String, Collection<Object>> servicesForId : servicesById.asMap().entrySet()) {
+            String serviceId = servicesForId.getKey();
+            Collection<Object> services = servicesForId.getValue();
+            if(services.size() > 1) {
+                throw new IllegalStateException(
+                        String.format("Service ids must be unique; serviceId '%s' is declared by domain services %s",
+                                serviceId, classNamesFor(services)));
+            }
+        }
+    }
+
+    private static String classNamesFor(Collection<Object> services) {
+        StringBuilder buf = new StringBuilder();
+        for (Object service : services) {
+            if(buf.length() > 0) {
+                buf.append(", ");
+            }
+            buf.append(service.getClass().getName());
+        }
+        return buf.toString();
+    }
+
+    private static void validatePostConstructMethods(Object service, Method method) {
+        final PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
+        if(postConstruct == null) {
+            return;
+        }
+        final int numParams = method.getParameterTypes().length;
+        if(numParams == 0) {
+            return;
+        }
+        if(numParams == 1 && method.getParameterTypes()[0].isAssignableFrom(Map.class)) {
+            return;
+        }
+        throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PostConstruct method " + method.getName() + "; such methods must take either no argument or 1 argument of type Map<String,String>");
+    }
+
+    private static void validatePreDestroyMethods(Object service, Method method) {
+        final PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
+        if(preDestroy == null) {
+            return;
+        }
+        final int numParams = method.getParameterTypes().length;
+        if(numParams == 0) {
+            return;
+        }
+        throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PreDestroy method " + method.getName() + "; such methods must take no arguments");
+    }
+
+
+    static boolean contains(final List<Object> services, final Class<?> serviceClass) {
+        for (Object service : services) {
+            if(serviceClass.isAssignableFrom(service.getClass())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    @Override
     public List<Object> getRegisteredServices() {
         return Collections.unmodifiableList(services);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
index dd351cd..a029d1f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
@@ -19,8 +19,6 @@
 
 package org.apache.isis.core.metamodel.services;
 
-import java.util.List;
-
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.components.Injectable;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
@@ -35,12 +33,6 @@ public interface ServicesInjectorSpi extends ApplicationScopedComponent, Injecta
 
 
     /**
-     * Services to be injected.
-     */
-    void setServices(List<Object> services);
-
-
-    /**
      * Update an individual service.
      *
      * <p>
@@ -53,4 +45,8 @@ public interface ServicesInjectorSpi extends ApplicationScopedComponent, Injecta
     <T> void replaceService(T originalService, T replacementService);
 
     boolean isRegisteredService(Class<?> cls);
+
+    <T> void addFallbackIfRequired(Class<T> serviceClass, T serviceInstance);
+
+    void validateServices();
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 7952d9e..c1118b7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -18,6 +18,17 @@
  */
 package org.apache.isis.core.metamodel.services.metamodel;
 
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
@@ -33,8 +44,12 @@ import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware;
 )
 public class MetaModelServiceDefault implements MetaModelService, SpecificationLoaderAware {
 
-    private SpecificationLoader specificationLookup;
+    @SuppressWarnings("unused")
+    private final static Logger LOG = LoggerFactory.getLogger(MetaModelServiceDefault.class);
+
 
+
+    //region > fromObjectType, toObjectType
     @Programmatic
     public Class<?> fromObjectType(final String objectType) {
         if(objectType == null) {
@@ -45,7 +60,8 @@ public class MetaModelServiceDefault implements MetaModelService, SpecificationL
         return objectSpecification != null? objectSpecification.getCorrespondingClass(): null;
     }
 
-    @Override public String toObjectType(final Class<?> domainType) {
+    @Override
+    public String toObjectType(final Class<?> domainType) {
         if(domainType == null) {
             return null;
         }
@@ -54,9 +70,15 @@ public class MetaModelServiceDefault implements MetaModelService, SpecificationL
         final ObjectSpecId objectSpecId = objectSpecIdFacet.value();
         return objectSpecId.asString();
     }
+    //endregion
+
+    //region > injected dependencies
+    private SpecificationLoader specificationLookup;
 
     @Override
     public void setSpecificationLookup(final SpecificationLoader specificationLookup) {
         this.specificationLookup = specificationLookup;
     }
+    //endregion
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
index 0b53830..af0aabc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.metamodel.spec;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 import org.apache.isis.core.commons.debug.DebuggableWithTitle;
 import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
-import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
 
 public interface SpecificationLoaderSpi extends ApplicationScopedComponent, DebuggableWithTitle, SpecificationLoader {
 
@@ -37,4 +36,6 @@ public interface SpecificationLoaderSpi extends ApplicationScopedComponent, Debu
     void invalidateCache(Class<?> domainClass);
     
     boolean isInitialized();
+
+    void validateAndAssert();
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index 9cb6f24..22ffd82 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -202,19 +202,27 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
     @Override
     public void init() {
 
-        ValidationFailures validationFailures = initAndValidate();
-        
-        validationFailures.assertNone();
-        
+        initialize();
+
         cacheBySpecId();
         
         initialized = true;
     }
 
-    /**
-     * not API; <code>public</code> visibility for benefit of <tt>IsisMetaModel</tt>.
-     */
-    public ValidationFailures initAndValidate() {
+    public void validateAndAssert() {
+        ValidationFailures validationFailures = validate();
+        validationFailures.assertNone();
+
+        cacheBySpecId();
+    }
+
+    public ValidationFailures validate() {
+        ValidationFailures validationFailures = new ValidationFailures();
+        metaModelValidator.validate(validationFailures);
+        return validationFailures;
+    }
+
+    public void initialize() {
         if (LOG.isDebugEnabled()) {
             LOG.debug("initialising " + this);
         }
@@ -237,10 +245,6 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
         metaModelValidator.init();
 
         loadSpecificationsForServices();
-
-        ValidationFailures validationFailures = new ValidationFailures();
-        metaModelValidator.validate(validationFailures);
-        return validationFailures;
     }
 
     private void loadSpecificationsForServices() {

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
index e638f14..da01275 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
@@ -152,4 +152,9 @@ public class ProgrammableReflector extends SpecificationLoaderAbstract implement
         return false;
     }
 
+    @Override
+    public void validateAndAssert() {
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
index 361474b..2958892 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest.java
@@ -68,7 +68,9 @@ public class ServicesInjectorDefaultTest {
 
     @Before
     public void setUp() throws Exception {
-        injector = new ServicesInjectorDefault(new InjectorMethodEvaluatorDefault());
+        final Object[] services = { mockContainer, mockService1, mockService2 };
+
+        injector = new ServicesInjectorDefault(Arrays.asList(services), new InjectorMethodEvaluatorDefault());
     }
 
     @After
@@ -77,8 +79,6 @@ public class ServicesInjectorDefaultTest {
 
     @Test
     public void shouldInjectContainer() {
-        final Object[] services = { mockContainer, mockService1, mockService2 };
-        injector.setServices(Arrays.asList(services));
 
         context.checking(new Expectations() {
             {

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
index af6ca86..754bf32 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefaultTest_usingFields.java
@@ -81,12 +81,11 @@ public class ServicesInjectorDefaultTest_usingFields {
         service1 = new SomeDomainService1();
         service3 = new SomeDomainService3();
         service2 = new SomeDomainService2();
-        injector = new ServicesInjectorDefault();
+        injector = new ServicesInjectorDefault(Arrays.asList(container, service1, service3, service2));
     }
 
     @Test
     public void shouldInjectContainer() {
-        injector.setServices(Arrays.asList(container, service1, service3, service2));
 
         injector.injectServicesInto(service1);
         injector.injectServicesInto(service2);

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefaultTestAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefaultTestAbstract.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefaultTestAbstract.java
index 8f0c611..e7edc32 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefaultTestAbstract.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefaultTestAbstract.java
@@ -88,7 +88,7 @@ public abstract class ObjectReflectorDefaultTestAbstract {
                         new MetaModelValidatorDefault(),
                         Lists.<LayoutMetadataReader>newArrayList(new LayoutMetadataReaderFromJson()));
         reflector.setRuntimeContext(runtimeContext);
-        reflector.setServiceInjector(new ServicesInjectorDefault().withServices(Collections.<Object>singletonList(new DomainObjectContainerDefault())));
+        reflector.setServiceInjector(new ServicesInjectorDefault(Collections.<Object>singletonList(new DomainObjectContainerDefault())));
         reflector.init();
         
         specification = loadSpecification(reflector);

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
index f7594cc..d18f351 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.core.runtime.installerregistry.installerapi;
 
+import java.util.List;
+
 import org.apache.isis.core.commons.components.Installer;
 import org.apache.isis.core.runtime.persistence.ObjectStoreFactory;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
@@ -32,6 +34,6 @@ public interface PersistenceMechanismInstaller extends Installer, ObjectStoreFac
 
     static String TYPE = "persistor";
 
-    PersistenceSessionFactory createPersistenceSessionFactory(DeploymentType deploymentType);
+    PersistenceSessionFactory createPersistenceSessionFactory(DeploymentType deploymentType, final List<Object> services);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
index 14b32a2..799bc96 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/IsisSystemFixturesHookAbstract.java
@@ -123,6 +123,10 @@ public abstract class IsisSystemFixturesHookAbstract implements IsisSystem {
             initContext(sessionFactory);
             sessionFactory.init();
 
+            // validate here after all entities have been registered in the persistence session factory
+            final SpecificationLoaderSpi specificationLoader = sessionFactory.getSpecificationLoader();
+            specificationLoader.validateAndAssert();
+
             serviceInitializer = initializeServices();
 
             installFixturesIfRequired();
@@ -260,6 +264,7 @@ public abstract class IsisSystemFixturesHookAbstract implements IsisSystem {
      */
     protected abstract IsisSessionFactory doCreateSessionFactory(final DeploymentType deploymentType) throws IsisSystemException;
 
+
     // ///////////////////////////////////////////
     // Configuration
     // ///////////////////////////////////////////
@@ -302,7 +307,7 @@ public abstract class IsisSystemFixturesHookAbstract implements IsisSystem {
     // PersistenceSessionFactory
     // ///////////////////////////////////////////
 
-    protected abstract PersistenceSessionFactory obtainPersistenceSessionFactory(DeploymentType deploymentType) throws IsisSystemException;
+    protected abstract PersistenceSessionFactory obtainPersistenceSessionFactory(DeploymentType deploymentType, final List<Object> services) throws IsisSystemException;
 
     // ///////////////////////////////////////////
     // Fixtures (hooks)

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index d5e01ec..0403b44 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -73,7 +73,6 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
 
     private final PersistenceSessionFactory persistenceSessionFactory;
     private final ObjectAdapterFactory objectAdapterFactory;
-    private final ServicesInjectorSpi servicesInjector;
     private final OidGenerator oidGenerator;
     private final AdapterManagerDefault adapterManager;
 
@@ -87,8 +86,6 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
 
     private boolean dirtiableSupport = true;
 
-
-
     private static enum State {
         NOT_INITIALIZED, OPEN, CLOSED
     }
@@ -101,20 +98,15 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
      */
     public PersistenceSession(
             final PersistenceSessionFactory persistenceSessionFactory,
-            final ServicesInjectorSpi servicesInjector,
             final ObjectStore objectStore,
             final IsisConfiguration configuration) {
 
+
         ensureThatArg(persistenceSessionFactory, is(not(nullValue())), "persistence session factory required");
-        ensureThatArg(servicesInjector, is(not(nullValue())), "services injector required");
         ensureThatArg(objectStore, is(not(nullValue())), "object store required");
 
-        // owning, application scope
         this.persistenceSessionFactory = persistenceSessionFactory;
 
-        // session scope
-        this.servicesInjector = servicesInjector;
-
         this.objectAdapterFactory = new PojoAdapterFactory();
         this.oidGenerator = new OidGenerator(new IdentifierGeneratorUnified(configuration));
         this.adapterManager = new AdapterManagerDefault(new PojoRecreatorUnified(configuration));
@@ -122,7 +114,7 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
         this.objectStore = objectStore;
 
         this.persistenceQueryFactory = new PersistenceQueryFactory(getSpecificationLoader(), adapterManager);
-        this.transactionManager = new IsisTransactionManager(this, objectStore, servicesInjector);
+        this.transactionManager = new IsisTransactionManager(this, objectStore, persistenceSessionFactory.getServicesInjector());
 
         setState(State.NOT_INITIALIZED);
 
@@ -164,9 +156,8 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
         ensureThatState(transactionManager, is(not(nullValue())), "TransactionManager missing");
 
         // inject any required dependencies into object factory
+        final ServicesInjectorSpi servicesInjector = persistenceSessionFactory.getServicesInjector();
         servicesInjector.injectInto(objectFactory);
-
-        // wire dependencies into adapterManager
         servicesInjector.injectInto(adapterManager);
 
         adapterManager.open();
@@ -188,9 +179,8 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
 
     
     private void initServices() {
-
-        final List<Object> registeredServices = servicesInjector.getRegisteredServices();
-        
+        final List<Object> registeredServices =
+                persistenceSessionFactory.getServicesInjector().getRegisteredServices();
         createServiceAdapters(registeredServices);
     }
 
@@ -224,7 +214,7 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
      * @return - the service, or <tt>null</tt> if no service registered of specified type.
      */
     public <T> T getServiceOrNull(final Class<T> serviceType) {
-        return servicesInjector.lookupService(serviceType);
+        return persistenceSessionFactory.getServicesInjector().lookupService(serviceType);
     }
 
     // ///////////////////////////////////////////////////////////////////////////
@@ -516,7 +506,7 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
 
     // REVIEW why does this get called multiple times when starting up
     public List<ObjectAdapter> getServices() {
-        final List<Object> services = servicesInjector.getRegisteredServices();
+        final List<Object> services = persistenceSessionFactory.getServicesInjector().getRegisteredServices();
         final List<ObjectAdapter> serviceAdapters = Lists.newArrayList();
         for (final Object servicePojo : services) {
             serviceAdapters.add(getService(servicePojo));
@@ -913,7 +903,6 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
     @Override
     public void debugData(final DebugBuilder debug) {
         debug.appendTitle(getClass().getName());
-        debug.appendln("container", servicesInjector);
         debug.appendln();
 
         adapterManager.debugData(debug);
@@ -926,7 +915,7 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
         debug.appendln();
 
         debug.appendTitle("Services");
-        for (final Object servicePojo : servicesInjector.getRegisteredServices()) {
+        for (final Object servicePojo : persistenceSessionFactory.getServicesInjector().getRegisteredServices()) {
             final String id = ServiceUtil.id(servicePojo);
             final Class<? extends Object> serviceClass = servicePojo.getClass();
             final ObjectSpecification serviceSpecification = getSpecificationLoader().loadSpecification(serviceClass);
@@ -1030,7 +1019,7 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
      * The configured {@link ServicesInjectorSpi}.
      */
     public ServicesInjectorSpi getServicesInjector() {
-        return servicesInjector;
+        return persistenceSessionFactory.getServicesInjector();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
index 2b203a2..fe989cb 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactory.java
@@ -21,8 +21,10 @@ package org.apache.isis.core.runtime.system.persistence;
 
 import java.util.List;
 import java.util.Properties;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.clock.Clock;
 import org.apache.isis.applib.fixtures.FixtureClock;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
@@ -42,7 +44,10 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
 
 import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
 import static org.apache.isis.core.commons.ensure.Ensure.ensureThatState;
-import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
 
 /**
  * Implementation that just delegates to a supplied
@@ -56,23 +61,23 @@ public class PersistenceSessionFactory implements MetaModelRefiner, ApplicationS
     private final IsisConfiguration configuration;
     private final ObjectStoreFactory objectStoreFactory;
 
-    /**
-     * @see #setServices(List)
-     */
-    private List<Object> serviceList;
-
     private Boolean fixturesInstalled;
 
-    private final ServicesInjectorSpi servicesInjector = new ServicesInjectorDefault();
+    private final ServicesInjectorSpi servicesInjector;
     private RuntimeContext runtimeContext;
 
     public PersistenceSessionFactory(
             final DeploymentType deploymentType,
+            final List<Object> serviceList,
             final IsisConfiguration isisConfiguration,
             final ObjectStoreFactory objectStoreFactory) {
+
+        ensureThatState(serviceList, is(notNullValue()));
+
         this.deploymentType = deploymentType;
         this.configuration = isisConfiguration;
         this.objectStoreFactory = objectStoreFactory;
+        servicesInjector = new ServicesInjectorDefault(serviceList);
     }
 
     public DeploymentType getDeploymentType() {
@@ -92,20 +97,13 @@ public class PersistenceSessionFactory implements MetaModelRefiner, ApplicationS
         ServicesInjectorSpi servicesInjector = getServicesInjector();
 
         final ObjectStore objectStore = objectStoreFactory.createObjectStore(getConfiguration());
-
         ensureThatArg(objectStore, is(not(nullValue())));
 
-        final PersistenceSession persistenceSession = new PersistenceSession(this, servicesInjector, objectStore, getConfiguration());
-
-
-        return persistenceSession;
+        return new PersistenceSession(this, objectStore, getConfiguration());
     }
 
     public final void init() {
 
-        // check prereq dependencies injected
-        ensureThatState(serviceList, is(notNullValue()));
-
         // a bit of a workaround, but required if anything in the metamodel (for
         // example, a
         // ValueSemanticsProvider for a date value type) needs to use the Clock
@@ -124,13 +122,12 @@ public class PersistenceSessionFactory implements MetaModelRefiner, ApplicationS
         runtimeContext.injectInto(servicesInjector);
         
         // wire up components
-
         getSpecificationLoader().injectInto(runtimeContext);
-        for (Object service : serviceList) {
+
+        for (Object service : servicesInjector.getRegisteredServices()) {
             runtimeContext.injectInto(service);
         }
 
-        servicesInjector.setServices(serviceList);
         servicesInjector.init();
     }
 
@@ -211,10 +208,6 @@ public class PersistenceSessionFactory implements MetaModelRefiner, ApplicationS
     // Dependencies (injected via setters)
     // //////////////////////////////////////////////////////
 
-    public void setServices(final List<Object> serviceList) {
-        this.serviceList = serviceList;
-    }
-
     // //////////////////////////////////////////////////////
     // Dependencies (from context)
     // //////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryDefault.java
index d575c6f..1d38172 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryDefault.java
@@ -72,7 +72,6 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
     private final AuthenticationManager authenticationManager;
     private final AuthorizationManager authorizationManager;
     private final PersistenceSessionFactory persistenceSessionFactory;
-    private final List<Object> serviceList;
     private final OidMarshaller oidMarshaller;
 
     public IsisSessionFactoryDefault(
@@ -82,7 +81,6 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
             final AuthenticationManager authenticationManager,
             final AuthorizationManager authorizationManager,
             final PersistenceSessionFactory persistenceSessionFactory,
-            final List<Object> serviceList,
             final OidMarshaller oidMarshaller) {
 
         ensureThatArg(deploymentType, is(not(nullValue())));
@@ -91,7 +89,6 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
         ensureThatArg(authenticationManager, is(not(nullValue())));
         ensureThatArg(authorizationManager, is(not(nullValue())));
         ensureThatArg(persistenceSessionFactory, is(not(nullValue())));
-        ensureThatArg(serviceList, is(not(nullValue())));
 
         this.deploymentType = deploymentType;
         this.configuration = configuration;
@@ -99,80 +96,9 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
         this.authenticationManager = authenticationManager;
         this.authorizationManager = authorizationManager;
         this.persistenceSessionFactory = persistenceSessionFactory;
-        this.serviceList = serviceList;
         this.oidMarshaller = oidMarshaller;
-        
-        validateServices(serviceList);
-    }
-
-    /**
-     * Validate domain service Ids are unique, and that the {@link PostConstruct} method, if present, must either 
-     * take no arguments or take a {@link Map} object), and that the {@link PreDestroy} method, if present, must take 
-     * no arguments.
-     * 
-     * <p>
-     * TODO: there seems to be some duplication/overlap with {@link ServiceInitializer}.
-     */
-    private void validateServices(List<Object> serviceList) {
-        for (Object service : serviceList) {
-            final Method[] methods = service.getClass().getMethods();
-            for (Method method : methods) {
-                validatePostConstructMethods(service, method);
-                validatePreDestroyMethods(service, method);
-            }
-        }
-        
-        ListMultimap<String, Object> servicesById = ArrayListMultimap.create();
-        for (Object service : serviceList) {
-            String id = ServiceUtil.id(service);
-            servicesById.put(id, service);
-        }
-        for (Entry<String, Collection<Object>> servicesForId : servicesById.asMap().entrySet()) {
-            String serviceId = servicesForId.getKey();
-            Collection<Object> services = servicesForId.getValue();
-            if(services.size() > 1) {
-                throw new IllegalStateException("Service ids must be unique; serviceId '" + serviceId + "' is declared by domain services " + classNamesFor(services)); 
-            }
-        }
     }
 
-    private static String classNamesFor(Collection<Object> services) {
-        StringBuilder buf = new StringBuilder();
-        for (Object service : services) {
-            if(buf.length() > 0) {
-                buf.append(", ");
-            }
-            buf.append(service.getClass().getName());
-        }
-        return buf.toString();
-    }
-
-    private void validatePostConstructMethods(Object service, Method method) {
-        final PostConstruct postConstruct = method.getAnnotation(PostConstruct.class);
-        if(postConstruct == null) {
-            return;
-        }
-        final int numParams = method.getParameterTypes().length;
-        if(numParams == 0) {
-            return;
-        }
-        if(numParams == 1 && method.getParameterTypes()[0].isAssignableFrom(Map.class)) {
-            return;
-        }
-        throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PostConstruct method " + method.getName() + "; such methods must take either no argument or 1 argument of type Map<String,String>"); 
-    }
-
-    private void validatePreDestroyMethods(Object service, Method method) {
-        final PreDestroy preDestroy = method.getAnnotation(PreDestroy.class);
-        if(preDestroy == null) {
-            return;
-        }
-        final int numParams = method.getParameterTypes().length;
-        if(numParams == 0) {
-            return;
-        }
-        throw new IllegalStateException("Domain service " + service.getClass().getName() + " has @PreDestroy method " + method.getName() + "; such methods must take no arguments"); 
-    }
 
 
     // ///////////////////////////////////////////
@@ -186,14 +112,12 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
     @Override
     public void init() {
         final ServicesInjectorSpi servicesInjector = persistenceSessionFactory.getServicesInjector();
-        servicesInjector.setServices(serviceList);
         specificationLoaderSpi.setServiceInjector(servicesInjector);
 
         specificationLoaderSpi.init();
 
         // must come after init of spec loader.
         specificationLoaderSpi.injectInto(persistenceSessionFactory);
-        persistenceSessionFactory.setServices(serviceList);
 
         authenticationManager.init();
         authorizationManager.init();
@@ -263,7 +187,7 @@ public class IsisSessionFactoryDefault implements IsisSessionFactory {
 
     @Override
     public List<Object> getServices() {
-        return serviceList;
+        return getPersistenceSessionFactory().getServicesInjector().getRegisteredServices();
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemAbstract.java
index 53981a7..9341c50 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemAbstract.java
@@ -22,8 +22,10 @@ package org.apache.isis.core.runtime.systemusinginstallers;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.fixtures.LogonFixture;
 import org.apache.isis.applib.fixturescripts.FixtureScripts;
 import org.apache.isis.applib.services.fixturespec.FixtureScriptsDefault;
@@ -34,13 +36,13 @@ import org.apache.isis.core.commons.debug.DebugBuilder;
 import org.apache.isis.core.commons.lang.ListExtensions;
 import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
 import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
+import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.authentication.AuthenticationManager;
 import org.apache.isis.core.runtime.authentication.exploration.ExplorationSession;
 import org.apache.isis.core.runtime.authorization.AuthorizationManager;
 import org.apache.isis.core.runtime.fixtures.FixturesInstaller;
 import org.apache.isis.core.runtime.installerregistry.InstallerLookup;
-import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
 import org.apache.isis.core.runtime.persistence.internal.RuntimeContextFromSession;
 import org.apache.isis.core.runtime.system.DeploymentType;
 import org.apache.isis.core.runtime.system.IsisSystemException;
@@ -49,6 +51,7 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.internal.InitialisationSession;
 import org.apache.isis.core.runtime.system.internal.IsisLocaleInitializer;
 import org.apache.isis.core.runtime.system.internal.IsisTimeZoneInitializer;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSessionFactory;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactoryDefault;
 
@@ -152,14 +155,15 @@ public abstract class IsisSystemAbstract extends IsisSystemFixturesHookAbstract
 
     @Override
     public IsisSessionFactory doCreateSessionFactory(final DeploymentType deploymentType) throws IsisSystemException {
-        final PersistenceSessionFactory persistenceSessionFactory = obtainPersistenceSessionFactory(deploymentType);
+        final List<Object> services = obtainServices();
+        final PersistenceSessionFactory persistenceSessionFactory = obtainPersistenceSessionFactory(deploymentType, services);
         return createSessionFactory(deploymentType, persistenceSessionFactory);
     }
 
     /**
      * Overloaded version designed to be called by subclasses that need to
      * explicitly specify different persistence mechanisms.
-     * 
+     *
      * <p>
      * This is <i>not</i> a hook method, rather it is designed to be called
      * <i>from</i> the {@link #doCreateSessionFactory(DeploymentType) hook
@@ -167,61 +171,35 @@ public abstract class IsisSystemAbstract extends IsisSystemFixturesHookAbstract
      */
     protected final IsisSessionFactory createSessionFactory(
             final DeploymentType deploymentType,
-            final PersistenceSessionFactory persistenceSessionFactory) throws IsisSystemException {
+    final PersistenceSessionFactory persistenceSessionFactory) throws IsisSystemException {
 
         final IsisConfiguration configuration = getConfiguration();
         final AuthenticationManager authenticationManager = obtainAuthenticationManager(deploymentType);
         final AuthorizationManager authorizationManager = obtainAuthorizationManager(deploymentType);
         final OidMarshaller oidMarshaller = obtainOidMarshaller();
-        
-        final Collection<MetaModelRefiner> metaModelRefiners = refiners(authenticationManager, authorizationManager, persistenceSessionFactory);
+
+        final Collection<MetaModelRefiner> metaModelRefiners =
+                refiners(authenticationManager, authorizationManager, persistenceSessionFactory);
         final SpecificationLoaderSpi reflector = obtainSpecificationLoaderSpi(deploymentType, metaModelRefiners);
 
-        final List<Object> services = obtainServices();
-        if(!contains(services, FixtureScripts.class)) {
-            // add to beginning so that appears at top of prototyping menu.
-            services.add(0, new FixtureScriptsDefault());
-        }
+        ServicesInjectorSpi servicesInjector = persistenceSessionFactory.getServicesInjector();
+        servicesInjector.addFallbackIfRequired(FixtureScripts.class, new FixtureScriptsDefault());
+        servicesInjector.validateServices();
 
         // bind metamodel to the (runtime) framework
         final RuntimeContextFromSession runtimeContext = obtainRuntimeContextFromSession();
         runtimeContext.injectInto(reflector);
 
-        return newIsisSessionFactory(
-                deploymentType,
-                persistenceSessionFactory,
-                configuration,
+        return new IsisSessionFactoryDefault(
+                deploymentType, configuration, reflector,
                 authenticationManager, authorizationManager,
-                oidMarshaller,
-                reflector,
-                services);
+                persistenceSessionFactory, oidMarshaller);
     }
 
-    static boolean contains(final List<Object> services, final Class<?> serviceClass) {
-        for (Object service : services) {
-            if(serviceClass.isAssignableFrom(service.getClass())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-
     protected RuntimeContextFromSession obtainRuntimeContextFromSession() {
         return new RuntimeContextFromSession();
     }
 
-    protected IsisSessionFactoryDefault newIsisSessionFactory(
-            final DeploymentType deploymentType,
-            final PersistenceSessionFactory persistenceSessionFactory,
-            final IsisConfiguration configuration,
-            final AuthenticationManager authenticationManager, final AuthorizationManager authorizationManager,
-            final OidMarshaller oidMarshaller,
-            final SpecificationLoaderSpi reflector,
-            final List<Object> services) {
-        return new IsisSessionFactoryDefault(deploymentType, configuration, reflector, authenticationManager, authorizationManager, persistenceSessionFactory, services, oidMarshaller);
-    }
-
     private static Collection<MetaModelRefiner> refiners(Object... possibleRefiners ) {
         return ListExtensions.filtered(Arrays.asList(possibleRefiners), MetaModelRefiner.class);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemUsingInstallers.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemUsingInstallers.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemUsingInstallers.java
index a14f917..46a046e 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemUsingInstallers.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisSystemUsingInstallers.java
@@ -216,7 +216,7 @@ public class IsisSystemUsingInstallers extends IsisSystemAbstract {
     }
 
     @Override
-    protected PersistenceSessionFactory obtainPersistenceSessionFactory(final DeploymentType deploymentType) throws IsisSystemException {
+    protected PersistenceSessionFactory obtainPersistenceSessionFactory(final DeploymentType deploymentType, final List<Object> services) throws IsisSystemException {
 
         // look for a object store persistor
         if (persistenceMechanismInstaller == null) {
@@ -225,6 +225,6 @@ public class IsisSystemUsingInstallers extends IsisSystemAbstract {
         }
 
         ensureThatState(persistenceMechanismInstaller, is(not(nullValue())), "persistor installer has not been injected and could not be looked up");
-        return persistenceMechanismInstaller.createPersistenceSessionFactory(deploymentType);
+        return persistenceMechanismInstaller.createPersistenceSessionFactory(deploymentType, services);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/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 50ce240..7aeb633 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
@@ -89,8 +89,9 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
 
     //region > createPersistenceSessionFactory
     @Override
-    public PersistenceSessionFactory createPersistenceSessionFactory(final DeploymentType deploymentType) {
-        return new PersistenceSessionFactory(deploymentType, getConfiguration(), this);
+    public PersistenceSessionFactory createPersistenceSessionFactory(
+            final DeploymentType deploymentType, final List<Object> services) {
+        return new PersistenceSessionFactory(deploymentType, services, getConfiguration(), this);
     }
     //endregion
 
@@ -108,7 +109,8 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
     
     private DataNucleusApplicationComponents applicationComponents = null;
 
-    private DataNucleusApplicationComponents createDataNucleusApplicationComponentsIfRequired(IsisConfiguration configuration) {
+    private DataNucleusApplicationComponents createDataNucleusApplicationComponentsIfRequired(
+            final IsisConfiguration configuration) {
 
         if (applicationComponents == null || applicationComponents.isStale()) {
 
@@ -118,7 +120,8 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
             final Map<String, String> datanucleusProps = dataNucleusConfig.asMap();
             addDataNucleusPropertiesIfRequired(datanucleusProps);
 
-            final Set<String> classesToBePersisted = catalogClassesToBePersisted(configuration);
+            final RegisterEntities registerEntities = new RegisterEntities(configuration.asMap());
+            final Set<String> classesToBePersisted = registerEntities.getEntityTypes();
 
             applicationComponents = new DataNucleusApplicationComponents(jdoObjectstoreConfig, datanucleusProps, classesToBePersisted);
         }
@@ -126,12 +129,6 @@ public class DataNucleusPersistenceMechanismInstaller extends InstallerAbstract
         return applicationComponents;
     }
 
-    private static Set<String> catalogClassesToBePersisted(
-            final IsisConfiguration configuration) {
-        return new RegisterEntities(configuration.asMap()).getEntityTypes();
-    }
-
-
     private static void addDataNucleusPropertiesIfRequired(
             final Map<String, String> props) {
         

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/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 1e02568..1892594 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
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.objectstore.jdo.service;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -25,80 +26,73 @@ import java.util.Set;
 import javax.jdo.annotations.PersistenceCapable;
 
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 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.Programmatic;
 import org.apache.isis.applib.util.ScanUtils;
 
 public class RegisterEntities {
 
-    @SuppressWarnings("unused")
-    private final static Logger LOG = LoggerFactory.getLogger(RegisterEntities.class);
-    
     public final static String PACKAGE_PREFIX_KEY = "isis.persistor.datanucleus.RegisterEntities.packagePrefix";
 
-    private String packagePrefixes;
+    //region > init
 
     public RegisterEntities(final Map<String, String> configuration) {
-        packagePrefixes = configuration.get(PACKAGE_PREFIX_KEY);
+        String packagePrefixes = configuration.get(PACKAGE_PREFIX_KEY);
         if(Strings.isNullOrEmpty(packagePrefixes)) {
             throw new IllegalStateException("Could not locate '" + PACKAGE_PREFIX_KEY + "' key in property files - aborting");
         }
-        
-        discoverAllPersistenceCapables();
+
+        domPackages = parseDomPackages(packagePrefixes);
+        this.entityTypes = scanForEntityTypesIn(this.domPackages);
     }
 
-    private void discoverAllPersistenceCapables() {
+    //endregion
 
-        final List<String> packagePrefixList = Lists.newArrayList(Iterables.transform(Splitter.on(",").split(packagePrefixes), trim()));
-        for (final String packagePrefix : packagePrefixList) {
+    //region > domPackages
+    private List<String> domPackages;
 
-            final Iterable<String> entityTypes = ScanUtils.scanForNamesOfClassesWithAnnotation(packagePrefixList, PersistenceCapable.class);
-            if(notEmpty(entityTypes)) {
-                throw new IllegalStateException("Could not locate any @PersistenceCapable entities in package " + packagePrefix);
-            }
-            this.entityTypes = Sets.newLinkedHashSet(entityTypes);
-        }
+    public List<String> getDomPackages() {
+        return domPackages;
     }
+    //endregion
 
+    //region > entityTypes
     private Set<String> entityTypes;
 
-    @Programmatic
     public Set<String> getEntityTypes() {
         return entityTypes;
     }
-
-    private static Function<String,String> trim() {
-        return new Function<String,String>(){
-            @Override
-            public String apply(String input) {
-                return input.trim();
+    //endregion
+
+    //region > helpers
+    private static Set<String> scanForEntityTypesIn(final List<String> domPackages) {
+        Set<String> entityTypes = Sets.newLinkedHashSet();
+        for (final String packagePrefix : domPackages) {
+            final Iterable<String> entityTypes1 = ScanUtils.scanForNamesOfClassesWithAnnotation(domPackages, PersistenceCapable.class);
+            if(Iterables.isEmpty(entityTypes1)) {
+                throw new IllegalStateException("Could not locate any @PersistenceCapable entities in package " + packagePrefix);
             }
-        };
+            Iterables.addAll(entityTypes, entityTypes1);
+        }
+        return entityTypes;
     }
 
-    /**
-     * 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 <T> boolean notEmpty(Iterable<T> set) {
-        return Iterables.filter(set, isNull()).iterator().hasNext();
+    private static List<String> parseDomPackages(String packagePrefixes) {
+        return Collections.unmodifiableList(Lists.newArrayList(Iterables.transform(Splitter.on(",").split(packagePrefixes), trim())));
     }
 
-    private static <T> Predicate<T> isNull() {
-        return new Predicate<T>() {
+    private static Function<String,String> trim() {
+        return new Function<String,String>(){
             @Override
-            public boolean apply(T input) {
-                return input == null;
+            public String apply(String input) {
+                return input.trim();
             }
         };
     }
+    //endregion
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/context/IsisContextTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/context/IsisContextTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/context/IsisContextTest.java
index 73cf1be..5838ace 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/context/IsisContextTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/context/IsisContextTest.java
@@ -102,7 +102,7 @@ public class IsisContextTest {
             }
         });
 
-        sessionFactory = new IsisSessionFactoryDefault(DeploymentType.UNIT_TESTING, configuration, mockSpecificationLoader, mockAuthenticationManager, mockAuthorizationManager, mockPersistenceSessionFactory, servicesList, oidMarshaller);
+        sessionFactory = new IsisSessionFactoryDefault(DeploymentType.UNIT_TESTING, configuration, mockSpecificationLoader, mockAuthenticationManager, mockAuthorizationManager, mockPersistenceSessionFactory, oidMarshaller);
         authSession = new SimpleSession("tester", Collections.<String>emptyList());
         
         IsisContext.setConfiguration(configuration);

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
index f9cc749..ef9d3b7 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
@@ -68,7 +68,7 @@ public class ObjectStoreTransactionManager_EndTransactionTest {
             will(returnValue(mockMessageBroker));
         }});
 
-        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault()) {
+        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault(Collections.emptyList())) {
             @Override
             public AuthenticationSession getAuthenticationSession() {
                 return mockAuthenticationSession;

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
index d064e5d..e917802 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_InstantiationTest.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.core.runtime.persistence.objectstore.transaction;
 
+import java.util.Collections;
+
 import org.jmock.auto.Mock;
 import org.junit.Rule;
 import org.junit.Test;
@@ -44,7 +46,7 @@ public class ObjectStoreTransactionManager_InstantiationTest {
 
     @Test
     public void canInstantiate() throws Exception {
-        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault());
+        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault(Collections.emptyList()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
index 14f67e9..cb8fe52 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.core.runtime.persistence.objectstore.transaction;
 
+import java.util.Collections;
+
 import org.jmock.Expectations;
 import org.jmock.auto.Mock;
 import org.junit.Before;
@@ -56,7 +58,7 @@ public class ObjectStoreTransactionManager_StartTransactionTest {
 
     @Before
     public void setUpTransactionManager() throws Exception {
-        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault()) {
+        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault(Collections.emptyList())) {
             @Override
             protected AuthenticationSession getAuthenticationSession() {
                 return mockAuthenticationSession;

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionTest.java
index 3cf5d3a..87408d4 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionTest.java
@@ -147,11 +147,12 @@ public class PersistenceSessionTest {
 
         runtimeContext.injectInto(container);
 
-        servicesInjector = new ServicesInjectorDefault(new InjectorMethodEvaluatorDefault());
+        servicesInjector = new ServicesInjectorDefault(
+                Collections.<Object>singletonList(container),new InjectorMethodEvaluatorDefault());
 
         adapterManager = new AdapterManagerDefault(new PojoRecreatorUnified(mockConfiguration));
         adapterFactory = new PojoAdapterFactory();
-        persistenceSession = new PersistenceSession(mockPersistenceSessionFactory, servicesInjector, mockObjectStore, mockConfiguration) {
+        persistenceSession = new PersistenceSession(mockPersistenceSessionFactory, mockObjectStore, mockConfiguration) {
             @Override
             protected SpecificationLoaderSpi getSpecificationLoader() {
                 return isisMetaModel.getSpecificationLoader();
@@ -159,8 +160,6 @@ public class PersistenceSessionTest {
             
         };
         
-        servicesInjector.setServices(Collections.<Object>singletonList(container));
-        
         context.checking(new Expectations(){{
             allowing(mockAuthenticationSession).getUserName();
             will(returnValue("sven"));

http://git-wip-us.apache.org/repos/asf/isis/blob/97013cb3/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
index 2ba697e..77af285 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryAbstractTest_init_and_shutdown.java
@@ -84,7 +84,7 @@ public class IsisSessionFactoryAbstractTest_init_and_shutdown {
     public void validate_DomainServicesWithDuplicateIds() {
         serviceList.add(new DomainServiceWithSomeId());
         serviceList.add(new DomainServiceWithDuplicateId());
-        isf = new IsisSessionFactoryDefault(mockDeploymentType, configuration, mockSpecificationLoader, mockAuthenticationManager, mockAuthorizationManager, mockPersistenceSessionFactory, serviceList, mockOidMarshaller) {
+        isf = new IsisSessionFactoryDefault(mockDeploymentType, configuration, mockSpecificationLoader, mockAuthenticationManager, mockAuthorizationManager, mockPersistenceSessionFactory, mockOidMarshaller) {
         };
     }
 }


[5/9] isis git commit: ISIS-1182: CreateSchema... listener now uses the PMF to obtain connection. Upgrading to released version of fast-classpath-scanner. Added migration notes.

Posted by da...@apache.org.
ISIS-1182: CreateSchema... listener now uses the PMF to obtain connection.  Upgrading to released version of fast-classpath-scanner.  Added migration notes.


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

Branch: refs/heads/master
Commit: b83db19183fd082355ca24b7cfaea5378038f346
Parents: 97013cb
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 10:42:48 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 10:42:48 2015 +0100

----------------------------------------------------------------------
 .../_migration-notes_1.8.0-to-1.9.0.adoc        |  1 +
 ...1.8.0-to-1.9.0_specify-all-dom-packages.adoc | 35 +++++++++
 ...notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc |  2 +-
 core/pom.xml                                    |  2 +-
 .../CreateSchemaObjectFromClassMetadata.java    | 81 +++++++++++++-------
 5 files changed, 90 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b83db191/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0.adoc
index 4bae36c..f7b103e 100644
--- a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0.adoc
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0.adoc
@@ -13,6 +13,7 @@ Apache Isis 1.9.0 has not yet been released; it is still 1.9.0-SNAPSHOT.
 ====
 
 include::_migration-notes_1.8.0-to-1.9.0_upgrading-to-dn4.adoc[leveloffset=+1]
+include::_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc[leveloffset=+1]
 include::_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc[leveloffset=+1]
 include::_migration-notes_1.8.0-to-1.9.0_exception-recognizer.adoc[leveloffset=+1]
 include::_migration-notes_1.8.0-to-1.9.0_fixture-scripts-specification-provider.adoc[leveloffset=+1]

http://git-wip-us.apache.org/repos/asf/isis/blob/b83db191/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
new file mode 100644
index 0000000..72cc639
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
@@ -0,0 +1,35 @@
+[[_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages]]
+= Specify all `dom` packages
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+
+
+Apache Isis automatically scans for certain classes on the classpath in order to configure itself.  Specifically these are:
+
+* searching for classes annotated with xref:rg.adoc#_rg_annotations_manpage-DomainService[`@DomainService`].
+
+* searching for classes extending xref:rg.adoc#_rg_classes_super_manpage-FixtureScript[`FixtureScript`]
+
+* searching for classes annotated with xref:rg.adoc#_rg_annotations_manpage-PersistenceCapable[`@PersistenceCapable`].
+
+Prior to 1.9.0 we used the link:https://github.com/ronmamo/reflections[Reflections] library to do this, which under the covers uses link:http://www.javassist.org/[Javassist].  This is a relatively heavyweight approach.
+
+In 1.9.0 we have changed to using the link:https://github.com/lukehutch/fast-classpath-scanner[Fast-Classpath-Scanner] library, which is altogether more lightweight and has no dependencies.
+
+Generally this change should be transparent, however you should ensure that all domain classes are correctly registered using the `isis.persistor.datanucleus.RegisterEntities.packagePrefix` key.  This should include any domain classes for addon modules.
+
+For example, the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp]'s configuration now reads:
+
+[source,ini]
+----
+isis.persistor.datanucleus.RegisterEntities.packagePrefix=\
+                todoapp.dom.module,\
+                org.isisaddons.module.security.dom,\
+                org.isisaddons.module.settings.dom,\
+                org.isisaddons.module.sessionlogger.dom,\
+                org.isisaddons.module.command.dom,\
+                org.isisaddons.module.audit.dom,\
+                org.isisaddons.module.publishing.dom
+----

http://git-wip-us.apache.org/repos/asf/isis/blob/b83db191/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc
index dacc0f8..185b7f7 100644
--- a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_upgrading-to-java8.adoc
@@ -12,7 +12,7 @@ Apache Isis 1.9.0 is the first version to support Java 8.  You can continue to u
 
 == In the parent `pom.xml`
 
-under `<build>/<pluginManagement>/<plugins>`, add (or update) maven-enforcer-plugin:
+under `build/pluginManagement/plugins`, add (or update) `maven-compiler-plugin`:
 
 [source,xml]
 ----

http://git-wip-us.apache.org/repos/asf/isis/blob/b83db191/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index fcf5c43..ba68a17 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -116,7 +116,7 @@
         <javassist.version>3.19.0-GA</javassist.version>
         <reflections.version>0.9.9</reflections.version>
 
-        <fast-classpath-scanner.version>1.4.2-SNAPSHOT</fast-classpath-scanner.version>
+        <fast-classpath-scanner.version>1.6.0</fast-classpath-scanner.version>
 
         <commons-logging.version>1.1.2</commons-logging.version>
         <commons-cli.version>1.2</commons-cli.version>

http://git-wip-us.apache.org/repos/asf/isis/blob/b83db191/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/CreateSchemaObjectFromClassMetadata.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/CreateSchemaObjectFromClassMetadata.java b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/CreateSchemaObjectFromClassMetadata.java
index e4ce6cc..1c4e5b8 100644
--- a/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/CreateSchemaObjectFromClassMetadata.java
+++ b/core/runtime/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/CreateSchemaObjectFromClassMetadata.java
@@ -19,29 +19,43 @@
 package org.apache.isis.objectstore.jdo.datanucleus;
 
 import java.sql.Connection;
-import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Locale;
 import java.util.Map;
+
+import javax.jdo.PersistenceManager;
 import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.datastore.JDOConnection;
+
 import com.google.common.base.Strings;
+
 import org.datanucleus.metadata.AbstractClassMetaData;
 import org.datanucleus.metadata.MetaDataListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Implementation note: the methods in this class are <tt>protected</tt> to allow for easy subclassing.
+ */
 public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, PersistenceManagerFactoryAware, DataNucleusPropertiesAware {
 
     private static final Logger LOG = LoggerFactory.getLogger(DataNucleusPersistenceMechanismInstaller.class);
 
-    // unused
-    protected PersistenceManagerFactory persistenceManagerFactory;
-    protected Map<String, String> properties;
+    //region > persistenceManagerFactory, properties
+    private PersistenceManagerFactory persistenceManagerFactory;
+    protected PersistenceManagerFactory getPersistenceManagerFactory() {
+        return persistenceManagerFactory;
+    }
 
-    protected String driverName;
-    protected String url;
+    private Map<String, String> properties;
+    protected Map<String, String> getProperties() {
+        return properties;
+    }
+    //endregion
+
+    //region > loaded (API)
 
     @Override
     public void loaded(final AbstractClassMetaData cmd) {
@@ -51,39 +65,36 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
             return;
         }
 
-        driverName = properties.get("javax.jdo.option.ConnectionDriverName");
-        url = properties.get("javax.jdo.option.ConnectionURL");
-        final String userName = properties.get("javax.jdo.option.ConnectionUserName");
-        final String password = properties.get("javax.jdo.option.ConnectionPassword");
-
+        JDOConnection dataStoreConnection = null;
         Connection connection = null;
         Statement statement = null;
+
+
+        final PersistenceManager persistenceManager =
+                persistenceManagerFactory.getPersistenceManager();
+        dataStoreConnection = persistenceManager.getDataStoreConnection();
         try {
-            connection = DriverManager.getConnection(url, userName, password);
+            final Object connectionObj = dataStoreConnection.getNativeConnection();
+            connection = (java.sql.Connection) connectionObj;
+
             statement = connection.createStatement();
             if(skip(cmd, statement)) {
                 return;
             }
             exec(cmd, statement);
+
         } catch (SQLException e) {
             LOG.warn("Unable to create schema", e);
+
         } finally {
             closeSafely(statement);
-            closeSafely(connection);
+            dataStoreConnection.close();
         }
-    }
 
-    protected void closeSafely(final AutoCloseable connection) {
-        if(connection != null) {
-            try {
-                connection.close();
-            } catch (Exception e) {
-                // ignore
-            }
-        }
     }
+    //endregion
 
-    //region > skip
+    //region > skip, exec, schemaNameFor
 
     /**
      * Whether to skip creating this schema.
@@ -105,9 +116,6 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
         final String schemaName = schemaNameFor(cmd);
         return String.format("SELECT count(*) FROM INFORMATION_SCHEMA.SCHEMATA where SCHEMA_NAME = '%s'", schemaName);
     }
-    //endregion
-
-    //region > exec
 
     /**
      * Create the schema
@@ -121,7 +129,6 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
         final String schemaName = schemaNameFor(cmd);
         return String.format("CREATE SCHEMA \"%s\"", schemaName);
     }
-    //endregion
 
     /**
      * Determine the name of the schema.
@@ -138,6 +145,8 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
         // db vendors without requiring lots of complex configuration of DataNucleus
         //
 
+        String url = getProperties().get("javax.jdo.option.ConnectionURL");
+
         if(url.contains("postgres")) {
             schemaName = schemaName.toLowerCase(Locale.ROOT);
         }
@@ -149,10 +158,21 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
         }
         return schemaName;
     }
+    //endregion
 
+    //region > helpers: closeSafely
+    protected void closeSafely(final AutoCloseable connection) {
+        if(connection != null) {
+            try {
+                connection.close();
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+    //endregion
 
-    // //////////////////////////////////////
-
+    //region > injected dependencies
     public void setPersistenceManagerFactory(final PersistenceManagerFactory persistenceManagerFactory) {
         this.persistenceManagerFactory = persistenceManagerFactory;
     }
@@ -161,4 +181,7 @@ public class CreateSchemaObjectFromClassMetadata implements MetaDataListener, Pe
     public void setDataNucleusProperties(final Map<String, String> properties) {
         this.properties = properties;
     }
+    //endregion
+
+
 }


[8/9] isis git commit: ISIS-1082: minor edits to docs

Posted by da...@apache.org.
ISIS-1082: minor edits to docs


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

Branch: refs/heads/master
Commit: fabea33fcc04b2b23ef56eb2f8cd57f1490e9469
Parents: fdac0fe
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 11:43:41 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 11:46:14 2015 +0100

----------------------------------------------------------------------
 adocs/documentation/src/main/asciidoc/asf.adoc              | 2 +-
 .../asciidoc/guides/_cg_committers_release-process.adoc     | 4 ----
 adocs/documentation/src/main/asciidoc/more-thanks.adoc      | 9 +++++++++
 3 files changed, 10 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/fabea33f/adocs/documentation/src/main/asciidoc/asf.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/asf.adoc b/adocs/documentation/src/main/asciidoc/asf.adoc
index 0080981..67aa505 100644
--- a/adocs/documentation/src/main/asciidoc/asf.adoc
+++ b/adocs/documentation/src/main/asciidoc/asf.adoc
@@ -18,7 +18,7 @@ Apache Software Foundation:
 * link:http://www.apache.org/foundation/thanks.html[Thanks]
 
 
-Thanks to companies that have in one way or another supported Apache Isis' development:
+Thanks to companies and other third parties that have in one way or another supported Apache Isis' development:
 
 * link:./more-thanks.html[More thanks]
 

http://git-wip-us.apache.org/repos/asf/isis/blob/fabea33f/adocs/documentation/src/main/asciidoc/guides/_cg_committers_release-process.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_cg_committers_release-process.adoc b/adocs/documentation/src/main/asciidoc/guides/_cg_committers_release-process.adoc
index d7e5ac2..344aa77 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_cg_committers_release-process.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_cg_committers_release-process.adoc
@@ -17,10 +17,6 @@ If you've not performed a release before, then note that there are some configur
 
 These release notes using bash command line tools.  They should work on Linux and MacOS; for Windows, use mSysGit.
 
-See also:
-
-* the xref:cg.adoc#_cg_committers_release-process-one-pager[one pager] which lists the essential steps
-* the xref:cg.adoc#_cg_committers_release-checklist[release checklist] for keeping track of where you are while releasing Apache Isis component(s).
 
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/fabea33f/adocs/documentation/src/main/asciidoc/more-thanks.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/more-thanks.adoc b/adocs/documentation/src/main/asciidoc/more-thanks.adoc
index 4d9a044..6e92a5f 100644
--- a/adocs/documentation/src/main/asciidoc/more-thanks.adoc
+++ b/adocs/documentation/src/main/asciidoc/more-thanks.adoc
@@ -34,3 +34,12 @@ In addition to the http://www.apache.org/foundation/thanks.html[support given to
 
 
 
+Also to:
+
+- link:https://github.com/mojavelinux[Dan Allen] for his fantastic work on link:https://github.com/asciidoctor/asciidoctor[Asciidoctor]
+
+- link:https://github.com/lukehutch[Luke Hutch] for his link:https://github.com/lukehutch/fast-classpath-scanner[fast-classpath-scanner], in particular for merging in our PR for Java 7 support and releasing so quickly
+
+- link:https://github.com/krasa/MavenHelper[Vojtech Krasa] for his super https://github.com/krasa/MavenHelper[MavenHelper] plugin to IntelliJ
+
+and to many others who contribute their free time and passion to open source.
\ No newline at end of file


[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)...

Posted by da...@apache.org.
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();
-    }
-
-
-    
 }


[2/9] isis git commit: ISIS-1182: tidying up with the FCS implementation, deleting Reflections-related stuff.

Posted by da...@apache.org.
ISIS-1182: tidying up with the FCS implementation, deleting Reflections-related stuff.


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

Branch: refs/heads/master
Commit: a678b9b554447b331444b699bf85d279a21abf71
Parents: f311839
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jul 30 16:42:44 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jul 30 16:42:44 2015 +0100

----------------------------------------------------------------------
 .../src/main/asciidoc/isis-in-pictures.adoc     |  14 +-
 core/applib/pom.xml                             |  14 --
 ...scoveryServiceUsingFastClasspathScanner.java |  17 +-
 .../ClassDiscoveryServiceUsingReflections.java  | 192 -------------------
 .../org/apache/isis/applib/util/ScanUtils.java  |  61 ++++++
 core/pom.xml                                    |  18 +-
 core/runtime/pom.xml                            |  92 +++++----
 .../ServicesInstallerFromAnnotation.java        |  59 +-----
 .../jdo/service/RegisterEntities.java           |  20 +-
 core/unittestsupport/pom.xml                    |   6 +-
 10 files changed, 152 insertions(+), 341 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/adocs/documentation/src/main/asciidoc/isis-in-pictures.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/isis-in-pictures.adoc b/adocs/documentation/src/main/asciidoc/isis-in-pictures.adoc
index ae960ea..75687f4 100644
--- a/adocs/documentation/src/main/asciidoc/isis-in-pictures.adoc
+++ b/adocs/documentation/src/main/asciidoc/isis-in-pictures.adoc
@@ -91,7 +91,7 @@ In general though, all actions are associated with some object, and are (at leas
 
 === Contributions
 
-As an alternative to placing actions (business logic) on a domain object, it can instead be placed on an (application-scoped, stateless) domain service. When an object is rendered by Apache Isis, it will automatically render all "contributed" behaviour; rather like traits or aspect-oriented mix-ins).
+As an alternative to placing actions (business logic) on a domain object, it can instead be placed on an (application-scoped, stateless) domain service. When an object is rendered by Apache Isis, it will automatically render all "contributed" behaviour; rather like traits or aspect-oriented mix-ins.
 
 In the screenshot below the highlighted "export as xml" action, the "relative priority" property (and "previous" and "next" actions) and also the "similar to" collection are all contributed:
 
@@ -108,7 +108,7 @@ image::{_imagesdir}/isis-in-pictures/067-contributed-action.png[width="600px",li
 
 == Extensible Views
 
-The Apache Isis viewer is implemented using http://wicket.apache.org[Apache Wicket], and has been architected to be extensible. For example, when a collection of objects is rendered, this is just one several views, as shown in the selector drop-down:
+The Apache Isis viewer is implemented using http://wicket.apache.org[Apache Wicket], and has been designed to be extensible. For example, when a collection of objects is rendered, this is just one of several views, as shown in the selector drop-down:
 
 image::{_imagesdir}/isis-in-pictures/070-pluggable-views.png[width="600px",link="{_imagesdir}/isis-in-pictures/070-pluggable-views.png"]
 
@@ -128,7 +128,7 @@ image::{_imagesdir}/isis-in-pictures/090-fullcalendar2-view.png[width="600px",li
 
 
 
-Yet another "view" (though this one is rather simpler is that provided by the Isis Addons https://github.com/isisaddons/isis-wicket-excel[excel component] (non ASF). This provides a download button to the table as a spreadsheet:
+Yet another "view" (though this one is rather simpler) is that provided by the Isis Addons https://github.com/isisaddons/isis-wicket-excel[excel component] (non ASF). This provides a download button to the table as a spreadsheet:
 
 image::{_imagesdir}/isis-in-pictures/100-excel-view-and-docx.png[width="600px",link="{_imagesdir}/isis-in-pictures/100-excel-view-and-docx.png"]
 
@@ -152,7 +152,7 @@ Please note that the Isis Addons are not part of ASF, but they _are_ all license
 
 == Security, Auditing and more...
 
-As well as providing extensions to the UI, the Isis Addons provides a rich set of modules to support various cross-cutting concerns.
+As well as providing extensions to the UI, the Isis Addons provide a rich set of modules to support various cross-cutting concerns.
 
 Under the activity menu are four sets of services which provide support for https://github.com/isisaddons/isis-module-sessionlogger[user session logging/auditing] (non ASF), https://github.com/isisaddons/isis-module-command[command profiling] (non ASF), https://github.com/isisaddons/isis-module-audit[(object change) auditing] (shown, non-ASF) and (inter-system) https://github.com/isisaddons/isis-module-publishing[event publishing] (non ASF):
 
@@ -161,7 +161,7 @@ image::{_imagesdir}/isis-in-pictures/120-auditing.png[width="600px",link="{_imag
 
 
 
-In the security menu is access to the rich set of functionality provided by the Isis addons https://github.com/isisaddons/isis-module-security[security module] (non ASF):
+In the security menu is access to the rich set of functionality provided by the Isis Addons https://github.com/isisaddons/isis-module-security[security module] (non ASF):
 
 image::{_imagesdir}/isis-in-pictures/130-security.png[width="600px",link="{_imagesdir}/isis-in-pictures/130-security.png"]
 
@@ -175,7 +175,7 @@ image::{_imagesdir}/isis-in-pictures/140-i18n.png[width="600px",link="{_imagesdi
 
 
 
-The Isis addons also provides a module for managing application and user https://github.com/isisaddons/isis-module-settings[settings] (non ASF). Most apps (the todoapp example included) won't expose these services directly, but will usually wrap them in their own app-specific settings service that trivially delegates to the settings module's services:
+The Isis Addons also provides a module for managing application and user https://github.com/isisaddons/isis-module-settings[settings] (non ASF). Most apps (the todoapp example included) won't expose these services directly, but will usually wrap them in their own app-specific settings service that trivially delegates to the settings module's services:
 
 image::{_imagesdir}/isis-in-pictures/150-appsettings.png[width="600px",link="{_imagesdir}/isis-in-pictures/150-appsettings.png"]
 
@@ -184,7 +184,7 @@ image::{_imagesdir}/isis-in-pictures/150-appsettings.png[width="600px",link="{_i
 
 === Multi-tenancy support
 
-Of the various Isis addons, the https://github.com/isisaddons/isis-module-security[security module] has the most features. One significant feature is the ability to associate users and objects with a "tenancy". The todoapp uses this feature so that different users' list of todo items are kept separate from one another. A user with administrator is able to switch their own "tenancy" to the tenancy of some other user, in order to access the objects in that tenancy:
+Of the various Isis Addons, the https://github.com/isisaddons/isis-module-security[security module] has the most features. One significant feature is the ability to associate users and objects with a "tenancy". The todoapp uses this feature so that different users' list of todo items are kept separate from one another. A user with administrator is able to switch their own "tenancy" to the tenancy of some other user, in order to access the objects in that tenancy:
 
 image::{_imagesdir}/isis-in-pictures/160-switch-tenancy.png[width="600px",link="{_imagesdir}/isis-in-pictures/160-switch-tenancy.png"]
 

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/applib/pom.xml
----------------------------------------------------------------------
diff --git a/core/applib/pom.xml b/core/applib/pom.xml
index f101151..bae8b30 100644
--- a/core/applib/pom.xml
+++ b/core/applib/pom.xml
@@ -161,24 +161,10 @@
             <scope>test</scope>
         </dependency>
 
-        <!-- as used by ClassDiscoveryServiceUsingReflections -->
-        <dependency>
-            <groupId>org.reflections</groupId>
-            <artifactId>reflections</artifactId>
-            <optional>true</optional>
-        </dependency>
-
         <!-- as used by ClassDiscoveryServiceUsingFastClasspathScanner -->
         <dependency>
             <groupId>io.github.lukehutch</groupId>
             <artifactId>fast-classpath-scanner</artifactId>
-            <version>1.4.1</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>junit</groupId>
-                    <artifactId>junit</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
 
     </dependencies>

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/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 daa081a..cdf4b5c 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
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.applib.services.classdiscovery;
 
+import java.util.Collections;
 import java.util.Set;
 
 import com.google.common.collect.Sets;
@@ -26,9 +27,7 @@ import org.apache.isis.applib.AbstractService;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
-
-import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
-import io.github.lukehutch.fastclasspathscanner.matchprocessor.SubclassMatchProcessor;
+import org.apache.isis.applib.util.ScanUtils;
 
 /**
  * This utility service supports the dynamic discovery of classes from the classpath.  One service that uses this
@@ -42,7 +41,6 @@ public class ClassDiscoveryServiceUsingFastClasspathScanner
             extends AbstractService
             implements ClassDiscoveryService2 {
 
-
     @Programmatic
     @Override
     public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type) {
@@ -53,16 +51,7 @@ public class ClassDiscoveryServiceUsingFastClasspathScanner
     @Override
     public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix) {
         final Set<Class<? extends T>> classes = Sets.newLinkedHashSet();
-        new FastClasspathScanner(packagePrefix)
-                .matchSubclassesOf(type, new SubclassMatchProcessor<T>() {
-                    @Override
-                    public void processMatch(final Class<? extends T> aClass) {
-                        classes.add(aClass);
-                    }
-                })
-                .scan();
-        return classes;
+        return ScanUtils.scanForSubclassesOf(Collections.singletonList(packagePrefix), type);
     }
 
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java b/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
deleted file mode 100644
index c9a12ba..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/classdiscovery/ClassDiscoveryServiceUsingReflections.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.services.classdiscovery;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import com.google.common.collect.Lists;
-
-import org.reflections.Reflections;
-import org.reflections.scanners.SubTypesScanner;
-import org.reflections.util.ClasspathHelper;
-import org.reflections.vfs.SystemDir;
-import org.reflections.vfs.Vfs;
-
-import org.apache.isis.applib.AbstractService;
-import org.apache.isis.applib.annotation.Programmatic;
-
-/**
- * This utility service supports the dynamic discovery of classes from the classpath.  One service that uses this
- * is the <tt>FixtureScripts</tt> domain service.
- */
-public class ClassDiscoveryServiceUsingReflections
-            extends AbstractService 
-            implements ClassDiscoveryService2 {
-
-
-    @Programmatic
-    @Override
-    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type) {
-        Vfs.setDefaultURLTypes(getUrlTypes());
-
-        final Reflections reflections = new Reflections(
-                ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()),
-                ClasspathHelper.forClass(Object.class),
-                new SubTypesScanner(false)
-        );
-        return reflections.getSubTypesOf(type);
-    }
-
-    @Programmatic
-    @Override
-    public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type, String packagePrefix) {
-        Vfs.setDefaultURLTypes(getUrlTypes());
-
-        final Reflections reflections = new Reflections(
-                ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()),
-                ClasspathHelper.forClass(Object.class),
-                ClasspathHelper.forPackage(packagePrefix),
-                new SubTypesScanner(false)
-        );
-        return reflections.getSubTypesOf(type);
-    }
-
-    // //////////////////////////////////////
-
-    /**
-     * Has <tt>public</tt> visibility only so can be reused by other services (including Isis runtime itself).
-     */
-    public static List<Vfs.UrlType> getUrlTypes() {
-        final List<Vfs.UrlType> urlTypes = Lists.newArrayList();
-        urlTypes.add(new EmptyIfFileEndingsUrlType(".pom", ".jnilib", "QTJava.zip"));
-        urlTypes.add(new JettyConsoleUrlType());
-        urlTypes.addAll(Arrays.asList(Vfs.DefaultUrlTypes.values()));
-
-        return urlTypes;
-    }
-
-
-    private static class EmptyIfFileEndingsUrlType implements Vfs.UrlType {
-
-        private final List<String> fileEndings;
-
-        private EmptyIfFileEndingsUrlType(final String... fileEndings) {
-            this.fileEndings = Lists.newArrayList(fileEndings);
-        }
-
-        public boolean matches(URL url) {
-            final String protocol = url.getProtocol();
-            final String externalForm = url.toExternalForm();
-            if (!protocol.equals("file")) {
-                return false;
-            }
-            for (String fileEnding : fileEndings) {
-                if (externalForm.endsWith(fileEnding))
-                    return true;
-            }
-            return false;
-        }
-
-        public Vfs.Dir createDir(final URL url) throws Exception {
-            return emptyVfsDir(url);
-        }
-
-        private static Vfs.Dir emptyVfsDir(final URL url) {
-            return new Vfs.Dir() {
-                @Override
-                public String getPath() {
-                    return url.toExternalForm();
-                }
-
-                @Override
-                public Iterable<Vfs.File> getFiles() {
-                    return Collections.emptyList();
-                }
-
-                @Override
-                public void close() {
-                    //
-                }
-            };
-        }
-    }
-
-
-    public static class JettyConsoleUrlType implements Vfs.UrlType {
-        public boolean matches(URL url) {
-            final String protocol = url.getProtocol();
-            final String externalForm = url.toExternalForm();
-            final boolean matches = protocol.equals("file") && externalForm.contains("jetty-console") && externalForm.contains("-any-") && externalForm.endsWith("webapp/WEB-INF/classes/");
-            return matches;
-        }
-
-        public Vfs.Dir createDir(final URL url) throws Exception {
-            return new SystemDir(getFile(url));
-        }
-
-        /**
-         * try to get {@link java.io.File} from url
-         *
-         * <p>
-         *     Copied from {@link org.reflections.vfs.Vfs} (not publicly accessible)
-         * </p>
-         */
-        static java.io.File getFile(URL url) {
-            java.io.File file;
-            String path;
-
-            try {
-                path = url.toURI().getSchemeSpecificPart();
-                if ((file = new java.io.File(path)).exists()) return file;
-            } catch (URISyntaxException e) {
-            }
-
-            try {
-                path = URLDecoder.decode(url.getPath(), "UTF-8");
-                if (path.contains(".jar!")) path = path.substring(0, path.lastIndexOf(".jar!") + ".jar".length());
-                if ((file = new java.io.File(path)).exists()) return file;
-
-            } catch (UnsupportedEncodingException e) {
-            }
-
-            try {
-                path = url.toExternalForm();
-                if (path.startsWith("jar:")) path = path.substring("jar:".length());
-                if (path.startsWith("file:")) path = path.substring("file:".length());
-                if (path.contains(".jar!")) path = path.substring(0, path.indexOf(".jar!") + ".jar".length());
-                if ((file = new java.io.File(path)).exists()) return file;
-
-                path = path.replace("%20", " ");
-                if ((file = new java.io.File(path)).exists()) return file;
-
-            } catch (Exception e) {
-            }
-
-            return null;
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/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
new file mode 100644
index 0000000..872a62c
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/ScanUtils.java
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+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 io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
+import io.github.lukehutch.fastclasspathscanner.matchprocessor.ClassAnnotationMatchProcessor;
+import io.github.lukehutch.fastclasspathscanner.matchprocessor.SubclassMatchProcessor;
+
+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();
+        new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
+                .matchClassesWithAnnotation(annotationClass,
+                        new ClassAnnotationMatchProcessor() {
+                            @Override
+                            public void processMatch(final Class<?> matchingClass) {
+                                classes.add(matchingClass);
+                            }
+                        })
+                .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();
+        new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
+                .matchSubclassesOf(annotationClass,
+                        new SubclassMatchProcessor<T>() {
+                            @Override
+                            public void processMatch(final Class<? extends T> matchingClass) {
+                                classes.add(matchingClass);
+                            }
+                        })
+                .scan();
+        return classes;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 6111219..fcf5c43 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -65,7 +65,6 @@
         <testsToInclude>**/*Test_*.java</testsToInclude>
         <testsToExclude>**/*IntegrationTest.java</testsToExclude>
 
-
         <!-- remaining properties should not need to be overridden -->
         <compileSource>1.7</compileSource>
         <compileTarget>1.7</compileTarget>
@@ -117,6 +116,8 @@
         <javassist.version>3.19.0-GA</javassist.version>
         <reflections.version>0.9.9</reflections.version>
 
+        <fast-classpath-scanner.version>1.4.2-SNAPSHOT</fast-classpath-scanner.version>
+
         <commons-logging.version>1.1.2</commons-logging.version>
         <commons-cli.version>1.2</commons-cli.version>
         <commons-httpclient.version>3.1</commons-httpclient.version>
@@ -166,7 +167,6 @@
         <geronimo-atinject_1.0_spec.version>1.0</geronimo-atinject_1.0_spec.version>
         <geronimo-jcdi_1.0_spec.version>1.0</geronimo-jcdi_1.0_spec.version>
         <validation-api.version>1.1.0.Final</validation-api.version>
-
     </properties>
 
     <scm>
@@ -1352,7 +1352,19 @@ ${license.additional-notes}
             <dependency>
                 <groupId>org.reflections</groupId>
                 <artifactId>reflections</artifactId>
-                <version>${reflections.version}</version>
+                <version>0.9.9</version>
+            </dependency>
+
+            <dependency>
+                <groupId>io.github.lukehutch</groupId>
+                <artifactId>fast-classpath-scanner</artifactId>
+                <version>${fast-classpath-scanner.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>junit</groupId>
+                        <artifactId>junit</artifactId>
+                    </exclusion>
+                </exclusions>
             </dependency>
 
             <!-- Bytecode libraries -->

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/runtime/pom.xml
----------------------------------------------------------------------
diff --git a/core/runtime/pom.xml b/core/runtime/pom.xml
index 428b772..172aaf9 100644
--- a/core/runtime/pom.xml
+++ b/core/runtime/pom.xml
@@ -120,7 +120,6 @@
             <scope>test</scope>
         </dependency>
 
-
         <dependency>
             <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-log4j</artifactId>
@@ -153,11 +152,7 @@
             <artifactId>log4j</artifactId>
         </dependency>
 
-        <!--  for the RegisterEntities service -->
-        <dependency>
-            <groupId>org.reflections</groupId>
-            <artifactId>reflections</artifactId>
-        </dependency>
+        <!-- for our home-grown proxies for @RequestScoped -->
         <dependency>
             <groupId>org.javassist</groupId>
             <artifactId>javassist</artifactId>
@@ -169,44 +164,57 @@
             <scope>provided</scope>
         </dependency>
 
-        <!-- Email Notification Service -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-email</artifactId>
-            <version>1.3.3</version>
-            <exclusions>
-                <exclusion>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>email-notification-service</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.commons</groupId>
+                    <artifactId>commons-email</artifactId>
+                    <version>1.3.3</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>javax.mail</groupId>
+                            <artifactId>mail</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
                     <groupId>javax.mail</groupId>
                     <artifactId>mail</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>javax.mail</groupId>
-            <artifactId>mail</artifactId>
-            <version>1.4.7</version>
-            <exclusions>
-                <exclusion>
+                    <version>1.4.7</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>javax.activation</groupId>
+                            <artifactId>activation</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
                     <groupId>javax.activation</groupId>
                     <artifactId>activation</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>javax.activation</groupId>
-            <artifactId>activation</artifactId>
-            <version>1.1.1</version>
-        </dependency>
-        <!-- Email Notification Service -->
-        
-        <!-- Axon Event Bus Service -->
-        <dependency>
-            <groupId>org.axonframework</groupId>
-            <artifactId>axon-core</artifactId>
-            <version>2.4</version>
-        </dependency>
-
-    </dependencies>
+                    <version>1.1.1</version>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>axon-event-bus</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.axonframework</groupId>
+                    <artifactId>axon-core</artifactId>
+                    <version>2.4</version>
+                </dependency>
+            </dependencies>
+        </profile>
+
+    </profiles>
 </project>

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
index 5bf95e0..88a0f3a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
@@ -26,7 +26,6 @@ import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
 
-import javax.annotation.Nullable;
 import javax.annotation.PreDestroy;
 
 import com.google.common.base.Function;
@@ -37,17 +36,13 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Ordering;
 import com.google.common.collect.Sets;
 
-import org.reflections.Reflections;
-import org.reflections.vfs.Vfs;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections;
 import org.apache.isis.core.commons.config.InstallerAbstract;
 import org.apache.isis.core.runtime.system.DeploymentType;
 
@@ -217,52 +212,18 @@ public class ServicesInstallerFromAnnotation extends InstallerAbstract implement
         initIfRequired();
 
         final List<String> packagePrefixList = asList(packagePrefixes);
-
-        final List<Class<?>> domainServiceClassesR = Lists.newArrayList(findClassesUsingReflections(packagePrefixList));
-        final List<Class<?>> domainServiceClassesFCS = Lists.newArrayList(findClassesUsingFastClasspathScanner(packagePrefixList));
-
-        final List<Class<?>> domainServiceClasses = Lists.newArrayList(domainServiceClassesFCS);
-
-        final List<String> sortedR_orig = sortedClassNames(domainServiceClassesR);
-        final List<String> sortedR = sortedClassNames(domainServiceClassesR);
-        final List<String> sortedFCS_orig = sortedClassNames(domainServiceClassesFCS);
-        final List<String> sortedFCS = sortedClassNames(domainServiceClassesFCS);
-
-        sortedR.removeAll(sortedFCS_orig);
-        sortedFCS.removeAll(sortedR_orig);
-
-        System.out.println("in R, not in FCS:");
-        for (String s : sortedR) {
-            System.out.println("  " + s);
-        }
-
-        System.out.println("in FCS, not in R:");
-        for (String s : sortedFCS) {
-            System.out.println("  " + s);
-        }
-
-
+        final Iterable<Class<?>> domainServiceClasses = findClassesUsingFastClasspathScanner(packagePrefixList);
         for (final Class<?> cls : domainServiceClasses) {
 
             final String order = orderOf(cls);
             // we want the class name in order to instantiate it
             // (and *not* the value of the @DomainServiceLayout(named=...) annotation attribute)
             final String fullyQualifiedClassName = cls.getName();
-            final String name = nameOf(cls);
 
             ServicesInstallerUtils.appendInPosition(positionedServices, order, fullyQualifiedClassName);
         }
     }
 
-    public List<String> sortedClassNames(final List<Class<?>> classes) {
-        final Iterable<String> transform = Iterables.transform(classes, new Function<Class<?>, String>() {
-            @Nullable @Override public String apply(@Nullable final Class<?> input) {
-                return input.getName();
-            }
-        });
-        return Ordering.natural().sortedCopy(transform);
-    }
-
     protected Iterable<Class<?>> findClassesUsingFastClasspathScanner(final List<String> packagePrefixList) {
         final Set<Class<?>> classes = Sets.newLinkedHashSet();
         new FastClasspathScanner(packagePrefixList.toArray(new String[]{}))
@@ -278,23 +239,6 @@ public class ServicesInstallerFromAnnotation extends InstallerAbstract implement
         return classes;
     }
 
-    protected Iterable<Class<?>> findClassesUsingFastClasspathScanner2(final List<String> packagePrefixList) {
-        final Set<Class<?>> classes = Sets.newLinkedHashSet();
-        final FastClasspathScanner scan = new FastClasspathScanner(packagePrefixList.toArray(new String[] {}))
-                .scan();
-        final List<String> namesOfClassesWithAnnotation = scan.getNamesOfClassesWithAnnotation(DomainService.class);
-
-        return classes;
-    }
-
-    protected Iterable<Class<?>> findClassesUsingReflections(final List<String> packagePrefixList) {
-        Vfs.setDefaultURLTypes(ClassDiscoveryServiceUsingReflections.getUrlTypes());
-        final Reflections reflections = new Reflections(packagePrefixList);
-
-        final Set<Class<?>> classes = reflections.getTypesAnnotatedWith(DomainService.class);
-        return Iterables.filter(classes, instantiatable());
-    }
-
     private static String orderOf(final Class<?> cls) {
         final DomainServiceLayout domainServiceLayout = cls.getAnnotation(DomainServiceLayout.class);
         String order = domainServiceLayout != null ? domainServiceLayout.menuOrder(): null;
@@ -326,5 +270,4 @@ public class ServicesInstallerFromAnnotation extends InstallerAbstract implement
         return listOf(List.class); // ie List<Object.class>, of services
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/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 a326d3a..da2ba1b 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
@@ -18,20 +18,26 @@
  */
 package org.apache.isis.objectstore.jdo.service;
 
+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;
 import com.google.common.base.Predicate;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
-import org.reflections.Reflections;
+import com.google.common.collect.Lists;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.util.ScanUtils;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 
@@ -63,12 +69,10 @@ public class RegisterEntities {
 
     private void registerAllPersistenceCapables() {
 
-        for (final String packagePrefix : Iterables.transform(Splitter.on(",").split(packagePrefixes), trim())) {
-            Reflections reflections = new Reflections(packagePrefix);
-            
-            Set<Class<?>> entityTypes = 
-                    reflections.getTypesAnnotatedWith(PersistenceCapable.class);
-            
+        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)) {
                 throw new IllegalStateException("Could not locate any @PersistenceCapable entities in package " + packagePrefix);
             }
@@ -105,7 +109,7 @@ public class RegisterEntities {
     }
 
     /**
-     * {@link Reflections} seems to return a set with 1 null element if none can be found.
+     * 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();

http://git-wip-us.apache.org/repos/asf/isis/blob/a678b9b5/core/unittestsupport/pom.xml
----------------------------------------------------------------------
diff --git a/core/unittestsupport/pom.xml b/core/unittestsupport/pom.xml
index 3fc1e0c..1440021 100644
--- a/core/unittestsupport/pom.xml
+++ b/core/unittestsupport/pom.xml
@@ -105,15 +105,15 @@
                 <!--<version>1.4</version>-->
             </dependency>
 
-        <dependency>
+            <dependency>
                 <groupId>org.reflections</groupId>
                 <artifactId>reflections</artifactId>
                 <exclusions>
                     <exclusion>
-                        <!-- 
+                        <!--
                         part of JDK 6+
                         the version here does not provide getUserData(), setUserData(),
-                        as needed by xmlsnapshot functionality in isis-core-runtime. 
+                        as needed by xmlsnapshot functionality in isis-core-runtime.
                         -->
                         <groupId>xml-apis</groupId>
                         <artifactId>xml-apis</artifactId>


[9/9] isis git commit: ISIS-1182: further tiny change to migration notes.

Posted by da...@apache.org.
ISIS-1182: further tiny change to migration notes.


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

Branch: refs/heads/master
Commit: 59c3b4942c9729260f09c1a27f4ad810628bdbbf
Parents: fabea33
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 11:59:35 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 11:59:35 2015 +0100

----------------------------------------------------------------------
 ...-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/59c3b494/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
index 88b1a05..0e09b41 100644
--- a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
@@ -18,7 +18,11 @@ Prior to 1.9.0 we used the link:https://github.com/ronmamo/reflections[Reflectio
 
 In 1.9.0 we have changed to using the link:https://github.com/lukehutch/fast-classpath-scanner[Fast-Classpath-Scanner] library, which is altogether more lightweight and has no dependencies.
 
-Generally this change should be transparent, however you should ensure that all domain classes are correctly registered using the `isis.persistor.datanucleus.RegisterEntities.packagePrefix` key.  This should include any domain classes for addon modules.
+Generally this change should be transparent, however there are two points to double-check.
+
+== Ensure dom classes registered
+
+First, you should ensure that all domain classes are correctly registered using the `isis.persistor.datanucleus.RegisterEntities.packagePrefix` key.  This should include any domain classes for addon modules.
 
 For example, the (non-ASF) http://github.com/isisaddons/isis-app-todoapp[Isis addons' todoapp]'s configuration now reads:
 
@@ -39,5 +43,10 @@ isis.persistor.datanucleus.RegisterEntities.packagePrefix=\
 Alternatively, could have just specified `org.isisaddons.module` instead of enumerating every addon.  This would be a bit slower, but more maintainable.
 ====
 
-
 If you fail to do this then DataNucleus will build up its metamodel lazily, rather than validate all classes up-front.  This can call issues: we've seen malformed SQL being submitted when DN wasn't aware of subclasses of a superclass, and we've also seen deadlocks when running against HSQLDB as it attempts to perform a DDL statement intermixed with DML statements.
+
+== Ensure services annotated
+
+In the previous implementation the xref:rg.adoc#_rg_annotations_manpage-DomainService[`@DomainService`] annotation could be applied to a superclass, and would be automatically picked up by any subclasses.
+
+With the new implementation this is no longer the case; every concrete domain service must be annotated with `@DomainService`.


[6/9] isis git commit: ISIS-1182: improving error messages in RegisterEntities. minor update to migration notes.

Posted by da...@apache.org.
ISIS-1182: improving error messages in RegisterEntities.  minor update to migration notes.


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

Branch: refs/heads/master
Commit: b584c787941b778122e9de4390af29b64afa4334
Parents: b83db19
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Jul 31 11:43:00 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Jul 31 11:43:00 2015 +0100

----------------------------------------------------------------------
 ...ion-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc |  8 ++++++++
 .../isis/objectstore/jdo/service/RegisterEntities.java    | 10 ++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b584c787/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
index 72cc639..88b1a05 100644
--- a/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.8.0-to-1.9.0_specify-all-dom-packages.adoc
@@ -33,3 +33,11 @@ isis.persistor.datanucleus.RegisterEntities.packagePrefix=\
                 org.isisaddons.module.audit.dom,\
                 org.isisaddons.module.publishing.dom
 ----
+
+[TIP]
+====
+Alternatively, could have just specified `org.isisaddons.module` instead of enumerating every addon.  This would be a bit slower, but more maintainable.
+====
+
+
+If you fail to do this then DataNucleus will build up its metamodel lazily, rather than validate all classes up-front.  This can call issues: we've seen malformed SQL being submitted when DN wasn't aware of subclasses of a superclass, and we've also seen deadlocks when running against HSQLDB as it attempts to perform a DDL statement intermixed with DML statements.

http://git-wip-us.apache.org/repos/asf/isis/blob/b584c787/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 1892594..09c446f 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
@@ -43,7 +43,9 @@ public class RegisterEntities {
     public RegisterEntities(final Map<String, String> configuration) {
         String packagePrefixes = configuration.get(PACKAGE_PREFIX_KEY);
         if(Strings.isNullOrEmpty(packagePrefixes)) {
-            throw new IllegalStateException("Could not locate '" + PACKAGE_PREFIX_KEY + "' key in property files - aborting");
+            throw new IllegalArgumentException(String.format(
+                    "Could not locate '%s' key in property files - aborting",
+                    PACKAGE_PREFIX_KEY));
         }
 
         domPackages = parseDomPackages(packagePrefixes);
@@ -74,7 +76,11 @@ public class RegisterEntities {
         for (final String packagePrefix : domPackages) {
             final Iterable<String> entityTypes1 = ScanUtils.scanForNamesOfClassesWithAnnotation(domPackages, PersistenceCapable.class);
             if(Iterables.isEmpty(entityTypes1)) {
-                throw new IllegalStateException("Could not locate any @PersistenceCapable entities in package " + packagePrefix);
+                throw new IllegalArgumentException(String.format(
+                        "Bad configuration.\n\nCould not locate any @PersistenceCapable entities in package '%s'\n" +
+                        "Check value of '%s' key in isis.properties etc.\n",
+                        packagePrefix,
+                        PACKAGE_PREFIX_KEY));
             }
             Iterables.addAll(entityTypes, entityTypes1);
         }