You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/12/21 17:16:14 UTC

[isis] 02/02: ISIS-2033: thread-safety for MetaModelContext

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch 2033-IoC
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 2dfd9745d520a51e9ac194642ce9c48302500c0a
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 21 18:16:05 2018 +0100

    ISIS-2033: thread-safety for MetaModelContext
    
    also let MetaModelContext cache its getters
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2033
---
 .../applib/services/registry/ServiceRegistry.java  |  12 +-
 .../apache/isis/commons/internal/base/_Timing.java |  11 +
 .../isis/core/metamodel/MetaModelContext.java      |   2 +-
 .../isis/core/metamodel/MetaModelContexts.java     | 114 +++++----
 .../isis/core/metamodel/facets/Annotations.java    |  25 +-
 .../services/registry/ServiceRegistryDefault.java  |   8 -
 .../metamodel/specloader/SpecificationLoader.java  |  38 +--
 .../facets/AbstractFacetFactoryJUnit4TestCase.java |  12 +-
 ...etDerivedFromDomainServiceFacetFactoryTest.java |   3 +-
 .../ServiceInjectorBuilder_forTesting.java         |   3 +
 .../ServiceRegistryBuilder_forTesting.java         |   2 +-
 .../SpecificationLoaderTestAbstract.java           |   2 +
 .../specloader/SpecificationLoaderTest_array.java  |   9 +
 core/plugins/ioc-weld/pom.xml                      |   6 +-
 core/pom.xml                                       |  19 +-
 core/unittestsupport/pom.xml                       |   5 +
 migration-notes.md                                 | 261 ---------------------
 17 files changed, 161 insertions(+), 371 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java b/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
index 9aef775..164b27d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/registry/ServiceRegistry.java
@@ -38,9 +38,6 @@ import org.apache.isis.commons.internal.cdi._CDI;
 @ApplicationScoped
 public interface ServiceRegistry {
 
-    @Deprecated
-    void registerServiceInstance(Object serviceInstance);
-    
     /**
      * Whether or not the given type is a application-scoped singleton, that
      * qualifies as a service to be managed by the framework. 
@@ -64,7 +61,7 @@ public interface ServiceRegistry {
     }
     
     /**
-     * Obtains a child Instance for the given required type and additional required qualifiers. 
+     * Obtains a managed bean for the given required type and additional required qualifiers. 
      * @param type
      * @param annotations
      * @return an optional, empty if passed two instances of the same qualifier type, or an 
@@ -105,7 +102,8 @@ public interface ServiceRegistry {
      *
      * <p>
      * Typically there will only ever be one domain service implementing a given type,
-     * (eg {@link org.apache.isis.applib.services.repository.RepositoryService}), but for some services there can be
+     * (eg {@link org.apache.isis.applib.services.repository.RepositoryService}), 
+     * but for some services there can be
      * more than one (eg {@link ExceptionRecognizer}).
      */
     public <T> Optional<T> lookupService(final Class<T> serviceClass);
@@ -123,8 +121,8 @@ public interface ServiceRegistry {
     boolean isRegisteredService(Class<?> cls);
     
     /**
-     * @param cls
-     * @return whether the exact object is registered as service
+     * @param pojo
+     * @return whether the pojo equals one of the registered service instances
      */
     boolean isRegisteredServiceInstance(Object pojo);
 
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Timing.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Timing.java
index 5f9183b..02da6b8 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Timing.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Timing.java
@@ -20,6 +20,7 @@
 package org.apache.isis.commons.internal.base;
 
 import java.util.Locale;
+import java.util.function.Supplier;
 
 /**
  * <h1>- internal use only -</h1>
@@ -114,6 +115,16 @@ public final class _Timing {
         System.out.println(String
                 .format(Locale.US, "Running '%s' took %.2f ms", label, watch.getMillis()));
     }
+    
+    public static <T> T callVerbose(String label, Supplier<T> callable) {
+        System.out.println(String.format("Calling '%s'", label));
+        final StopWatch watch = now();
+        T result = callable.get();
+        watch.stop();
+        System.out.println(String
+                .format(Locale.US, "Calling '%s' took %.2f ms", label, watch.getMillis()));
+        return result;
+    }
 
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContext.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContext.java
index 78eb934..9de1c1a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContext.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContext.java
@@ -75,7 +75,7 @@ public interface MetaModelContext {
     
     static MetaModelContext current() {
         return _Context.computeIfAbsent(MetaModelContext.class, 
-                __->MetaModelContexts.usingCDI); // default
+                __->MetaModelContexts.usingCDI()); // default
     }
     
     static void preset(MetaModelContext metaModelContext) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContexts.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContexts.java
index b4083e3..585a2b0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContexts.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/MetaModelContexts.java
@@ -35,6 +35,8 @@ import org.apache.isis.core.security.authentication.AuthenticationSessionProvide
 import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
 import org.apache.isis.core.security.authorization.manager.AuthorizationManager;
 
+import lombok.Getter;
+
 /**
  * 
  * @since 2.0.0-M2
@@ -43,79 +45,71 @@ import org.apache.isis.core.security.authorization.manager.AuthorizationManager;
 public final class MetaModelContexts {
 
     static class MetaModelContextUsingCDI implements MetaModelContext {
-        
-        @Override
-        public final IsisConfiguration getConfiguration() {
-            return _Config.getConfiguration();
-        }
-        
-        @Override
-        public final ObjectAdapterProvider getObjectAdapterProvider() {
-            return _CDI.getSingleton(ObjectAdapterProvider.class);
-        }
-        
-        @Override
-        public final ServiceInjector getServiceInjector() {
-            return _CDI.getSingleton(ServiceInjector.class);
-        }
 
-        @Override
-        public final ServiceRegistry getServiceRegistry() {
-            return _CDI.getSingleton(ServiceRegistry.class);
-        }
-        
-        @Override
-        public final SpecificationLoader getSpecificationLoader() {
-            return _CDI.getSingleton(SpecificationLoader.class);
-        }
+        @Getter(lazy=true) 
+        private final IsisConfiguration configuration = 
+        _Config.getConfiguration();
+
+        @Getter(lazy=true) 
+        private final ObjectAdapterProvider objectAdapterProvider =
+        _CDI.getSingleton(ObjectAdapterProvider.class);
+
+        @Getter(lazy=true) 
+        private final ServiceInjector serviceInjector =
+        _CDI.getSingleton(ServiceInjector.class);
+
+        @Getter(lazy=true) 
+        private final ServiceRegistry serviceRegistry =
+        _CDI.getSingleton(ServiceRegistry.class);
+
+        @Getter(lazy=true) 
+        private final SpecificationLoader specificationLoader = 
+        _CDI.getSingleton(SpecificationLoader.class);
+
+        @Getter(lazy=true) 
+        private final AuthenticationSessionProvider authenticationSessionProvider =
+        _CDI.getSingleton(AuthenticationSessionProvider.class);
+
+        @Getter(lazy=true) 
+        private final TranslationService translationService =
+        _CDI.getSingleton(TranslationService.class);
+
+        @Getter(lazy=true) 
+        private final AuthorizationManager authorizationManager =
+        _CDI.getSingleton(AuthorizationManager.class); 
+
+        @Getter(lazy=true) 
+        private final AuthenticationManager authenticationManager =
+        _CDI.getSingleton(AuthenticationManager.class);
+
+        @Getter(lazy=true) 
+        private final TitleService titleService =
+        _CDI.getSingleton(TitleService.class);
+
+        @Getter(lazy=true) 
+        private final PersistenceSessionServiceInternal persistenceSessionServiceInternal =
+        _CDI.getSingleton(PersistenceSessionServiceInternal.class);
+
 
-        @Override
-        public final AuthenticationSessionProvider getAuthenticationSessionProvider() {
-            return _CDI.getSingleton(AuthenticationSessionProvider.class);
-        }
-        
-        @Override
-        public final TranslationService getTranslationService() {
-            return _CDI.getSingleton(TranslationService.class);
-        }
-        
         @Override
         public final AuthenticationSession getAuthenticationSession() {
             return getAuthenticationSessionProvider().getAuthenticationSession();
         }
-        
-        @Override
-        public final AuthorizationManager getAuthorizationManager() {
-            return _CDI.getSingleton(AuthorizationManager.class); 
-        }
-        
-        @Override
-        public final AuthenticationManager getAuthenticationManager() {
-            return _CDI.getSingleton(AuthenticationManager.class); 
-        }
-        
-        @Override
-        public final TitleService getTitleService() {
-            return getServiceRegistry().lookupServiceElseFail(TitleService.class);
-        }
-        
+
         @Override
         public final ObjectSpecification getSpecification(final Class<?> type) {
             return type != null ? getSpecificationLoader().loadSpecification(type) : null;
         }
 
         @Override
-        public PersistenceSessionServiceInternal getPersistenceSessionServiceInternal() {
-            return _CDI.getSingleton(PersistenceSessionServiceInternal.class);
-        }
-
-        @Override
-        public TransactionState getTransactionState() {
+        public final TransactionState getTransactionState() {
             return getPersistenceSessionServiceInternal().getTransactionState();
         }
-        
+
     }
-    
-    final static MetaModelContext usingCDI = new MetaModelContextUsingCDI();
-    
+
+    final static MetaModelContext usingCDI() {
+        return new MetaModelContextUsingCDI();
+    }
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
index 75a73ff..5de035d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
@@ -218,7 +218,8 @@ public final class Annotations  {
             return annotation;
         }
 
-
+        //TODO [2033] too much heap pollution due to lots of stacktraces produced ...
+        
         // search for field
         if ( shouldSearchForField(annotationClass) ) {
 
@@ -613,6 +614,13 @@ public final class Annotations  {
 
         final Class<?> methodDeclaringClass = method.getDeclaringClass();
 
+        //TODO [2033] too much heap pollution due to lots of stacktraces produced
+        // suggested replacement ...
+//        return
+//        _Reflect.streamAllMethods(methodDeclaringClass)
+//        .filter(m->methodEquals(method, m))
+//        .anyMatch(m->m.isAnnotationPresent(annotationClass));
+    
         // search superclasses
         final Class<?> superclass = methodDeclaringClass.getSuperclass();
         if (superclass != null) {
@@ -664,5 +672,20 @@ public final class Annotations  {
 
         return Collections.emptyList();
     }
+    
+    //used by code that is commented out above
+    private static boolean methodEquals(Method m, Method superM) {
+        if(!m.getName().equals(superM.getName())) {
+            return false;
+        }
+        if(!m.getReturnType().isAssignableFrom(superM.getReturnType())) {
+            return false;
+        }
+        if(!Arrays.equals(m.getParameterTypes(), superM.getParameterTypes())) {
+            return false;
+        }
+        return true;
+        
+    }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
index 90e22a1..9a19c63 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryDefault.java
@@ -72,12 +72,6 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
     private final SetMultimap<Class<?>, Object> servicesAssignableToType = _Multimaps.newSetMultimap();
     private final _Lazy<Map<Class<?>, Object>> serviceByConcreteType = _Lazy.of(this::initServiceByConcreteType);
 
-
-    @Override
-    public void registerServiceInstance(Object serviceInstance) {
-        //registeredServiceInstances.add(serviceInstance);
-        //serviceByConcreteType.clear(); // invalidate
-    }
     
     @Override
     public <T> Optional<T> lookupService(Class<T> serviceClass) {
@@ -181,8 +175,6 @@ public final class ServiceRegistryDefault implements ServiceRegistry {
         final ListMultimap<String, Object> servicesById = _Multimaps.newListMultimap();
         serviceInstances.forEach(serviceInstance->{
             String id = ServiceUtil.idOfPojo(serviceInstance);
-            System.out.println("!!! id="+id);
-            
             servicesById.putElement(id, serviceInstance);
         });
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index 5de7135..a6c308a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -19,9 +19,9 @@ package org.apache.isis.core.metamodel.specloader;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Callable;
-import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 
+import javax.ejb.Singleton;
 import javax.enterprise.context.ApplicationScoped;
 
 import org.slf4j.Logger;
@@ -33,7 +33,6 @@ import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.config.internal._Config;
 import org.apache.isis.core.commons.ensure.Assert;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.ClassUtil;
@@ -54,7 +53,6 @@ import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificati
 import org.apache.isis.core.metamodel.specloader.specimpl.standalonelist.ObjectSpecificationOnStandaloneList;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
-import org.apache.isis.core.runtime.threadpool.ThreadPoolSupport;
 import org.apache.isis.progmodels.dflt.ProgrammingModelFacetsJava5;
 import org.apache.isis.schema.utils.CommonDtoUtils;
 
@@ -81,7 +79,7 @@ import org.apache.isis.schema.utils.CommonDtoUtils;
  * </p>
  *
  */
-@ApplicationScoped
+@Singleton @ApplicationScoped
 public class SpecificationLoader {
 
     private final static Logger LOG = LoggerFactory.getLogger(SpecificationLoader.class);
@@ -208,16 +206,28 @@ public class SpecificationLoader {
             };
             callables.add(callable);
         }
-        ThreadPoolSupport threadPoolSupport = ThreadPoolSupport.getInstance();
-        final boolean parallelize = _Config.getConfiguration()
-                .getBoolean(INTROSPECTOR_PARALLELIZE_KEY, INTROSPECTOR_PARALLELIZE_DEFAULT);
-        List<Future<Object>> futures;
-        if(parallelize) {
-            futures = threadPoolSupport.invokeAll(callables);
-        } else {
-            futures = threadPoolSupport.invokeAllSequential(callables);
-        }
-        threadPoolSupport.joinGatherFailures(futures);
+        
+        System.out.println("!!! calling callables size="+callables.size());
+        
+//        ThreadPoolSupport threadPoolSupport = ThreadPoolSupport.getInstance();
+//        final boolean parallelize = _Config.getConfiguration()
+//                .getBoolean(INTROSPECTOR_PARALLELIZE_KEY, INTROSPECTOR_PARALLELIZE_DEFAULT);
+//        List<Future<Object>> futures;
+//        if(parallelize) {
+//            futures = threadPoolSupport.invokeAll(callables);
+//        } else {
+//            futures = threadPoolSupport.invokeAllSequential(callables);
+//        }
+//        threadPoolSupport.joinGatherFailures(futures);
+        
+        callables.forEach(c->{
+            try {
+                c.call();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        });
+        
 
 
         // for debugging only
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryJUnit4TestCase.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryJUnit4TestCase.java
index 138e8d3..6d2697f 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryJUnit4TestCase.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryJUnit4TestCase.java
@@ -33,6 +33,7 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.i18n.TranslationService;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.internal.context._Context;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -105,28 +106,19 @@ public abstract class AbstractFacetFactoryJUnit4TestCase {
 
     @Before
     public void setUpFacetedMethodAndParameter() throws Exception {
-
+        
         // PRODUCTION
         
         context.checking(new Expectations() {{
 
-//            allowing(mockServicesInjector).getPersistenceSessionServiceInternal();
-//            will(returnValue(mockPersistenceSessionServiceInternal));
-
             allowing(mockServicesInjector).lookupService(TranslationService.class);
             will(returnValue(Optional.of(mockTranslationService)));
 
-//            allowing(mockServicesInjector).getAuthenticationSessionProvider();
-//            will(returnValue(mockAuthenticationSessionProvider));
-
             allowing(mockServicesInjector).lookupService(AuthenticationSessionProvider.class);
             will(returnValue(mockAuthenticationSessionProvider));
 
             allowing(mockServicesInjector).lookupServiceElseFail(EventBusService.class);
             will(returnValue(mockEventBusService));
-            
-//            allowing(mockServicesInjector).getSpecificationLoader();
-//            will(returnValue(mockSpecificationLoader));
 
         }});
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
index 2d72b61..d5aea69 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
@@ -39,7 +39,8 @@ import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 
-public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
+public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest 
+extends AbstractFacetFactoryJUnit4TestCase {
 
     private NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory facetFactory;
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServiceInjectorBuilder_forTesting.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServiceInjectorBuilder_forTesting.java
index 9a4a23e..e28e999 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServiceInjectorBuilder_forTesting.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/ServiceInjectorBuilder_forTesting.java
@@ -27,6 +27,9 @@ import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
+/**
+ * @deprecated Only introduced to support existing tests, don't use for new tests
+ */
 @RequiredArgsConstructor(staticName="of")
 public class ServiceInjectorBuilder_forTesting {
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryBuilder_forTesting.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryBuilder_forTesting.java
index 93d8a67..0b548e1 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryBuilder_forTesting.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/registry/ServiceRegistryBuilder_forTesting.java
@@ -49,7 +49,7 @@ public class ServiceRegistryBuilder_forTesting {
         val registry = new ServiceRegistryDefault();
         
         stream(services)
-        .forEach(registry::registerServiceInstance);
+        .forEach(mockeryContext::put);
         
         mockeryContext.put(registry);
         
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
index 040b45d..ac9239c 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
@@ -160,12 +160,14 @@ abstract class SpecificationLoaderTestAbstract {
         assertNull(facet);
     }
 
+    
     @Test
     public void testTypeOfFacet() throws Exception {
         final TypeOfFacet facet = specification.getFacet(TypeOfFacet.class);
         assertNull(facet);
     }
 
+
     @Test
     public void testNamedFaced() throws Exception {
         final Facet facet = specification.getFacet(NamedFacet.class);
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTest_array.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTest_array.java
index 30f2926..e7d00cb 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTest_array.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTest_array.java
@@ -62,4 +62,13 @@ class SpecificationLoaderTest_array extends SpecificationLoaderTestAbstract {
         assertEquals(ReflectorTestPojo.class, facet.value());
     }
 
+//[2033] performance testing the spec loader
+//    @Test @RepeatedTest(1000)
+//    public void testTypeOfFacet1000(TestInfo testInfo) throws Exception {
+//        final TypeOfFacet facet =
+//        _Timing.callVerbose("!!! Loop " + testInfo.getDisplayName(), ()->specification.getFacet(TypeOfFacet.class));
+//        assertNull(facet);
+//    }
+
+
 }
diff --git a/core/plugins/ioc-weld/pom.xml b/core/plugins/ioc-weld/pom.xml
index 47b3405..06180d6 100644
--- a/core/plugins/ioc-weld/pom.xml
+++ b/core/plugins/ioc-weld/pom.xml
@@ -35,14 +35,11 @@
     </description>
 
     <properties>
-    
-    	<weld.version>3.0.5.Final</weld.version>
-    
         <jar-plugin.automaticModuleName>org.apache.isis.plugins.ioc-weld</jar-plugin.automaticModuleName>
 		<git-plugin.propertiesDir>org/apache/isis/plugins/ioc-weld</git-plugin.propertiesDir>
     </properties>
 
-    	<build>
+    <build>
 		<resources>
 			<resource>
 				<filtering>false</filtering>
@@ -74,7 +71,6 @@
         <dependency>
         	<groupId>org.jboss.weld.se</groupId>
         	<artifactId>weld-se-shaded</artifactId>
-        	<version>${weld.version}</version>
         </dependency>
 
 	</dependencies>
diff --git a/core/pom.xml b/core/pom.xml
index b3c70c9..34e85be 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -92,6 +92,10 @@
 
         <!-- JDO API -->
         <jdo-api.version>3.1</jdo-api.version>
+        
+        <!-- CDI -->
+        <weld.version>3.0.5.Final</weld.version>
+        <weld-junit.version>1.3.1.Final</weld-junit.version>		    
 
         <!-- Isis Datanucleus JDO Plugin dn5 -->
 	    <dn5-jdo-api.version>3.2.0-m10</dn5-jdo-api.version>
@@ -179,7 +183,6 @@
         <htmlparser.version>2.1</htmlparser.version>
 
         <junit.version>5.3.2</junit.version>
-        <weld-junit.version>1.3.1.Final</weld-junit.version>
         <mockito.version>2.23.4</mockito.version>
         
         <!-- 2.8.1 depends on cglib-nodep 3.1 whereas axonframework depends on 2.2.2 -->
@@ -1164,6 +1167,14 @@ ${license.additional-notes}
                 <artifactId>javaee-api</artifactId>
                 <version>${javaee.version}</version>
             </dependency>
+            
+            <!-- CDI -->
+            <dependency>
+	        	<groupId>org.jboss.weld.se</groupId>
+	        	<artifactId>weld-se-shaded</artifactId>
+	        	<version>${weld.version}</version>
+	        </dependency>
+	        
 			
             <!-- JDO API -->
 <!-- not managed, because scope=provided can not be overwritten by plugins that are 
@@ -1978,13 +1989,17 @@ ${license.additional-notes}
                 <version>${junit.version}</version>
             </dependency>
             
-            <!-- WELD -->
+            <!-- CDI TESTING -->
 			<dependency>
 				<groupId>org.jboss.weld</groupId>
 				<artifactId>weld-junit5</artifactId>
 				<version>${weld-junit.version}</version>
 				<exclusions>
 					<exclusion>
+			        	<groupId>org.jboss.weld.se</groupId>
+			        	<artifactId>weld-se-core</artifactId>
+					</exclusion>
+					<exclusion>
 						<!-- also provided by weld-se -->
 						<groupId>org.jboss.logging</groupId>
 						<artifactId>jboss-logging</artifactId>
diff --git a/core/unittestsupport/pom.xml b/core/unittestsupport/pom.xml
index 73ba930..9f73da4 100644
--- a/core/unittestsupport/pom.xml
+++ b/core/unittestsupport/pom.xml
@@ -82,6 +82,11 @@
 			<groupId>org.jboss.weld</groupId>
 			<artifactId>weld-junit5</artifactId>
 		</dependency>
+		<dependency>
+        	<groupId>org.jboss.weld.se</groupId>
+        	<artifactId>weld-se-core</artifactId>
+        	<version>${weld.version}</version>
+	    </dependency>
 		
 		<dependency>
 		  <groupId>org.mockito</groupId>
diff --git a/migration-notes.md b/migration-notes.md
deleted file mode 100644
index c04b2c1..0000000
--- a/migration-notes.md
+++ /dev/null
@@ -1,261 +0,0 @@
-Migration Notes:
- * @MemberGroupLayout was removed
- * Axon Eventbus Plugin: switching from axon 2.x to 3.x which involves that axon's *EventHandler* annotation has moved: org.axonframework.eventhandling.annotation.EventHandler -> org.axonframework.eventhandling.EventHandler
- * _IsisMatchers_ is no longer part of the 'core' API, but still available within test-scope.
- * _Ensure_ as part of the 'core' API now accepts Java Predicates instead of hamcrest Matchers
- * deployment types SERVER_EXPLORATION, UNIT_TESTING have been removed
- * Some ways of setting the DeploymentType (using web.xml or WebServer cmd-line flags -t or --type) have been removed. Instead running in PROTOTYPING (exemplified with Jetty) can be done in following ways:
-{code:java}
- export PROTOTYPING=true ; mvn jetty:run
- mvn -DPROTOTYPING=true jetty:run
- mvn -Disis.deploymentType=PROTOTYPING jetty:run
-{code}
-We also introduced a SPI to customize this behavior. This issue is tracked by https://issues.apache.org/jira/browse/ISIS-1991
-
- * web.xml: no longer required to install listeners, filters and servlets; but is still required to configure the welcome page; _org.apache.isis.core.webapp.IsisWebAppContextListener_ acts as the single application entry-point to setup the dynamic part of the ServletContext.
- ** ResourceCachingFilter is now configured via annotations (Servlet 3.0 spec), no longer needed to be declared in web.xml
- ** ResourceServlet is now configured via annotations (Servlet 3.0 spec), no longer needed to be declared in web.xml
- ** IsisTransactionFilterForRestfulObjects is now configured via annotations (Servlet 3.0 spec), no longer needed to be declared in web.xml
- ** webjars Servlet was removed, no longer needed to be declared in web.xml
- ** Shiro Environment, no longer needs to be declared in web.xml
- ** Wicket Environment, no longer needs to be declared in web.xml
- ** RestEasy Environment, no longer needs to be declared in web.xml
- ** IsisSessionFilter is now part of the RestEasy WebModule, no longer needs to be declared in web.xml
- ** LogOnExceptionLogger, no longer needs to be declared in web.xml
- * web.xml apart from the new WebContextListener we introduce new web-specific (optional) config values, nothing else needs to configured here:
-{code:xml}
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
-	id="WebApp_ID" version="3.1">
-	<display-name>My App</display-name>
-
-	<welcome-file-list>
-		<welcome-file>about/index.html</welcome-file>
-	</welcome-file-list>
-
-	<!-- unique bootstrapping entry-point for web-applications -->
-        <listener>
-		<listener-class>org.apache.isis.core.webapp.IsisWebAppContextListener</listener-class>
-	</listener>
-
-	<!-- optional for overriding default 'wicket' -->
-	<context-param>
-		<param-name>isis.viewer.wicket.basePath</param-name>
-		<param-value>my-wicket</param-value>
-	</context-param>
-
-	<!-- optional for overriding default 'org.apache.isis.viewer.wicket.viewer.IsisWicketApplication' -->
-	<context-param>
-		<param-name>isis.viewer.wicket.app</param-name>
-		<param-value>domainapp.webapp.MyDomainApplication</param-value>
-	</context-param>
-	
-	<!-- optional for overriding default 'restful' -->
-	<context-param>
-		<param-name>isis.viewer.restfulobjects.basePath</param-name>
-		<param-value>my-restful</param-value>
-	</context-param>
-
-</web-app>
-{code}
-
- * module 'shiro' moved from `/core` to `/core/plugins` and its maven artifactId changed, to be in line with the other core-plugins:
-{code:xml}
-<dependency>
-	<groupId>org.apache.isis.core</groupId>
-	<artifactId>isis-core-plugins-security-shiro</artifactId>
-</dependency>
-{code}
-
- * ObjectAdapter is no longer holding a reference to an ObjectSpecification for the element type of collections. ObjectAdapter#getElementSpecification() moved to ObjectSpecification#getElementSpecification().
- * ServicesInjector does now implement interface ServiceRegistry, where the service lookup method changed:
-{code:java}
-// previous
-<T> T lookupService(final Class<T> serviceClass);
-// new with 2.0.0-M2
-<T> Optional<T> lookupService(final Class<T> serviceClass);
-{code}
-
- * We do now provide JAXB XmlAdapters for Java built-in temporal types in 'applib': org.apache.isis.applib.adapters.JaxbAdapters
- * Wicket-Viewer: Instead of browser built-in tooltip rendering, the framework now provides tooltips using Javascript and CSS, currently with following stylesheet defaults:
-{noformat}
-.ui-tooltip {
-    max-width: 300px;
-    background-color: WhiteSmoke;
-    text-align: center;
-    padding: 5px 10px;
-    border-radius: 4px;
-    font-size: 12px;
-    box-shadow: 0 0 7px black;
- 
-    position: absolute;
-    z-index: 9999;
-}
-
-span.isis-component-with-tooltip, 
-label.isis-component-with-tooltip, 
-.isis-component-with-tooltip label, 
-strong.isis-component-with-tooltip  {
-   text-decoration: underline dashed;
-}
-
-.ui-helper-hidden-accessible { display:none; } /* accessibility support disabled */
-{noformat}
-
- * Rest Viewer: The content negotiation parameter 'suppress' does now allow more control on which '$$..' properties one wants to suppress. New options are
-{code:java}
-public static enum SuppressionType {
-    /** suppress '$$RO', RO Spec representation*/
-    RO,
-    
-    /** suppress '$$href', hyperlink to the representation*/
-    HREF,
-    
-    /** suppress '$$instanceId', instance id of the domain object*/
-    ID,
-
-    /** suppress '$$domainType', object spec of the domain object */
-    DOMAIN_TYPE,    
-
-    /** suppress '$$title', title of the domain object*/
-    TITLE,
-    
-    /** suppress all '$$...' entries*/
-    ALL
-}{code}
-where these are case-insensitive and may be combined to a comma-separated set.
- Eg. to suppress $$title and $$href one could simply request
-{noformat}
-application/json;profile=urn:org.apache.isis/v1;suppress=title,href
-{noformat}
-We do not break the previous behavior with 'suppress=true' being equivalent to 'suppress=ro'
-
- * Adds a new JAX-RS 2.0 compliant RestfulClient to core-applib:
- Client-Side Setup:
-{code:xml}
-<dependency>
-	<groupId>org.apache.isis.core</groupId>
-	<artifactId>isis-core-applib</artifactId>
-	<version>2.0.0-M2-SNAPSHOT</version>
-</dependency>
-<dependency>
-	<groupId>javax.ws.rs</groupId>
-	<artifactId>javax.ws.rs-api</artifactId>
-	<version>2.1.1</version>
-</dependency>
-<dependency>
-	<groupId>org.glassfish.jersey.core</groupId>
-	<artifactId>jersey-client</artifactId>
-	<version>2.25.1</version>
-</dependency>
-<dependency>
-	<groupId>org.eclipse.persistence</groupId>
-	<artifactId>org.eclipse.persistence.moxy</artifactId>
-	<version>2.6.0</version>
-</dependency>
-{code}
-Synchronous example with Basic-Auth:
-{code:java}
-RestfulClientConfig clientConfig = new RestfulClientConfig();
-clientConfig.setRestfulBase("http://localhost:8080/helloworld/restful/");
-// setup basic-auth
-clientConfig.setUseBasicAuth(true);
-clientConfig.setRestfulAuthUser("sven");
-clientConfig.setRestfulAuthPassword("pass");
-
-RestfulClient client = RestfulClient.ofConfig(clientConfig);
-
-Builder request = client.request(
-				"services/myService/actions/lookupMyObjectById/invoke", 
-				SuppressionType.setOf(SuppressionType.RO));
-
-Entity<String> args = client.arguments()
-		.addActionParameter("id", "12345")
-		.build();
-
-Response response = request.post(args);
-
-ResponseDigest<MyObject> digest = client.digest(response, MyObject.class);
-
-if(digest.isSuccess()) {
-	System.out.println("result: "+ digest.get().get$$instanceId());
-} else {
-	digest.getFailureCause().printStackTrace();
-}
-{code}
-Asynchronous example with Basic-Auth:
-{code:java}
-RestfulClientConfig clientConfig = new RestfulClientConfig();
-clientConfig.setRestfulBase("http://localhost:8080/helloworld/restful/");
-// setup basic-auth
-clientConfig.setUseBasicAuth(true);
-clientConfig.setRestfulAuthUser("sven");
-clientConfig.setRestfulAuthPassword("pass");
-
-RestfulClient client = RestfulClient.ofConfig(clientConfig);
-
-Builder request = client.request(
-                "services/myService/actions/lookupMyObjectById/invoke", 
-                SuppressionType.setOf(SuppressionType.RO));
-
-Entity<String> args = client.arguments()
-        .addActionParameter("id", "12345")
-        .build();
-
-Future<Response> asyncResponse = request
-        .async()
-        .post(args);
-
-CompletableFuture<ResponseDigest<MyObject>> digestFuture = 
-                client.digest(asyncResponse, MyObject.class);
-        
-ResponseDigest<MyObject> digest = digestFuture.get(); // blocking
-
-if(digest.isSuccess()) {
-    System.out.println("result: "+ digest.get().get$$instanceId());
-} else {
-    digest.getFailureCause().printStackTrace();
-}
-{code}
-
- * Support for concurrent computation within an open session utilizing a ForkJoinPool
-{code:java}
-Supplier<T> computation = ()->doSomeComputation(); 
-CompletableFuture<T> completableFuture = IsisContext.compute(computation);
-
-T result = completableFuture.get(); // blocking call
-{code}
-
- * ConfigurationService and its internal implementation(s) were removed, instead use IsisConfiguration, which can be retrieved either via injection or static method:
-{code:java}
-@Inject IsisConfiguration configuration;
-// or
-IsisConfiguration configuration = IsisContext.getConfiguration();
-{code}
-The Configuration Menu within the UI now uses its own (and completely separated) interface, that handles masking of sensitive values (eg. passwords):
-{code:java}
-package org.apache.isis.applib.services.confview;
-
-public interface ConfigurationViewService {
-    /**
-     * Returns all properties, each as an instance of {@link ConfigurationProperty} (a view model).
-     * Mask sensitive values if required.
-     */
-    Set<ConfigurationProperty> allProperties();
-}
-{code}
-_@PostConstuct_ methods declared with domain objects no longer get passed over the IsisConfiguration. For now only zero-arg initializers are supported. (We might re-add parameter support, this is work in progress)
-
- * Wicket-Viewer: Customize the ThemeChooser by providing your own implementation of IsisWicketThemeSupport
-{code:java}
-public interface IsisWicketThemeSupport {
-    ThemeProvider getThemeProvider();
-    List<String> getEnabledThemeNames();
-}
-{code}
-to be configured using
-{noformat}
-isis.viewer.wicket.themes.provider=org.my.IsisWicketThemeSupport
-{noformat}