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/11/25 00:35:59 UTC

[isis] branch 2039-Redesign_of_Config updated: ISIS-2039: solving the AppManifest lookup problem independently of the configuration bootstrapping

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

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


The following commit(s) were added to refs/heads/2039-Redesign_of_Config by this push:
     new afa5712  ISIS-2039: solving the AppManifest lookup problem independently of the configuration bootstrapping
afa5712 is described below

commit afa571282b45bb9a9a3f9d1d9141661acf96e80c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Nov 25 01:35:54 2018 +0100

    ISIS-2039: solving the AppManifest lookup problem independently of the
    configuration bootstrapping
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2039
---
 .../org/apache/isis/applib/PropertyResource.java   | 41 +++++++----
 core/config/pom.xml                                |  7 +-
 .../org/apache/isis/config/internal/_Config.java   | 18 -----
 .../config/internal/_Config_LifecycleResource.java |  5 +-
 .../apache/isis/core/commons/config/AppConfig.java | 27 +++----
 .../isis/core/commons/config/AppConfigLocator.java | 27 +++++++
 .../core/commons/config/AppManifestFinder.java     | 83 ++++++++++++++++++++++
 .../commons/config/ConfigurationConstants.java     |  7 ++
 .../core/commons/config/IsisConfiguration.java     | 42 +++++++++++
 .../configbuilder/IsisConfigurationBuilder.java    | 21 ++++++
 .../IsisConfigurationBuilderDefault.java           | 71 +++++++++++++-----
 .../configbuilder/IsisConfigurationDefault.java    | 22 +++++-
 .../resource/ResourceStreamSource_UsingClass.java  | 35 +++++----
 .../isis/core/runtime/headless/IsisSystem.java     | 28 +++-----
 .../runner/opts/OptionHandlerAppManifest.java      | 10 +--
 .../isis/core/runtime/system/SystemConstants.java  |  6 --
 .../IsisComponentProvider.java                     | 19 ++---
 .../isis/core/webapp/IsisWebAppConfigHelper.java   |  2 -
 .../objectstore/jdo/service/RegisterEntities.java  |  6 --
 .../viewer/integration/isis/IsisInjectModule.java  | 71 +++---------------
 .../org.apache.isis.core.commons.config.AppConfig  |  1 +
 .../domainapp/application/HelloWorldAppConfig.java | 23 ++----
 .../application/HelloWorldAppManifest.java         |  3 -
 .../application/HelloWorldAppConfigTest.java       | 34 +++++++++
 24 files changed, 389 insertions(+), 220 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/PropertyResource.java b/core/applib/src/main/java/org/apache/isis/applib/PropertyResource.java
index f701c03..34d1f9a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/PropertyResource.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/PropertyResource.java
@@ -22,28 +22,41 @@ import java.io.InputStream;
 import java.util.Map;
 import java.util.Properties;
 
-public class PropertyResource {
-    private final Class<?> propertiesFileContext;
-    private final String propertiesFile;
+public final class PropertyResource {
+    private final Class<?> resourceContext;
+    private final String resourceName;
 
-    PropertyResource(final Class<?> propertiesFileContext, final String propertiesFile) {
-        this.propertiesFileContext = propertiesFileContext;
-        this.propertiesFile = propertiesFile;
+    /**
+     * @since 2.0.0-M2
+     */
+    public static PropertyResource ofClassContext(final Class<?> resourceContext, final String resourceName) {
+        return new PropertyResource(resourceContext, resourceName);
+    }
+    
+    PropertyResource(final Class<?> resourceContext, final String resourceName) {
+        this.resourceContext = resourceContext;
+        this.resourceName = resourceName;
     }
 
-    Class<?> getPropertiesFileContext() {
-        return propertiesFileContext;
+    /**
+     * @since 2.0.0-M2
+     */
+    public Class<?> getResourceContext() {
+        return resourceContext;
     }
 
-    String getPropertiesFile() {
-        return propertiesFile;
+    /**
+     * @since 2.0.0-M2
+     */
+    public String getResourceName() {
+        return resourceName;
     }
 
-    void loadPropsInto(
-            final Map<String, String> props) {
+    void loadPropsInto(final Map<String, String> props) {
+        
         final Properties properties = new Properties();
         try {
-            try (final InputStream stream = propertiesFileContext.getResourceAsStream(propertiesFile)) {
+            try (final InputStream stream = resourceContext.getResourceAsStream(resourceName)) {
                 properties.load(stream);
                 for (Object key : properties.keySet()) {
                     final Object value = properties.get(key);
@@ -54,7 +67,7 @@ public class PropertyResource {
             }
         } catch (Exception e) {
             throw new RuntimeException(
-                    String.format("Failed to load '%s' file relative to %s", getPropertiesFile(), getPropertiesFileContext().getName()), e);
+                    String.format("Failed to load '%s' file relative to %s", getResourceName(), getResourceContext().getName()), e);
         }
     }
 }
diff --git a/core/config/pom.xml b/core/config/pom.xml
index b47875e..e5f03f3 100644
--- a/core/config/pom.xml
+++ b/core/config/pom.xml
@@ -61,7 +61,7 @@
     
     	<dependency>
             <groupId>org.apache.isis.core</groupId>
-            <artifactId>isis-core-commons</artifactId>
+            <artifactId>isis-core-applib</artifactId>
         </dependency>
     
         <!-- TESTS -->
@@ -82,6 +82,11 @@
             </exclusions>
         </dependency>
 
+        <dependency>
+        	<groupId>org.apache.isis.core</groupId>
+        	<artifactId>isis-core-applib</artifactId>
+        	<type>test-jar</type>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git a/core/config/src/main/java/org/apache/isis/config/internal/_Config.java b/core/config/src/main/java/org/apache/isis/config/internal/_Config.java
index 6463557..00aeec5 100644
--- a/core/config/src/main/java/org/apache/isis/config/internal/_Config.java
+++ b/core/config/src/main/java/org/apache/isis/config/internal/_Config.java
@@ -118,24 +118,6 @@ public class _Config {
     private static _Config_LifecycleResource createLifecycleResource() {
         return new _Config_LifecycleResource(createBuilder());
     }
-
-//    /**
-//     * Sets the current context's configuration supplier via provided parameter. Will not override
-//     * any ConfigSupplier instance, that is already registered with the current context, 
-//     * because the ConfigSupplier is expected to be a singleton within an application's 
-//     * life-cycle.
-//     */
-//    public static void registerConfigurationSupplierIfNotAlready(ConfigSupplier configSupplier) {
-//        requires(configSupplier, "configSupplier");
-//        _Context.computeIfAbsent(ConfigSupplier.class, __->configSupplier);
-//    }
-//    
-//    public static IsisConfigurationBuilder configurationBuilderForTesting() {
-//        final IsisConfigurationBuilder builder = new IsisConfigurationBuilder();
-//        final ConfigSupplier configSupplier = new _Config_SupplierUsingBuilder(builder);
-//        registerConfigurationSupplierIfNotAlready(configSupplier);
-//        return builder; 
-//    }
     
     
 }
diff --git a/core/config/src/main/java/org/apache/isis/config/internal/_Config_LifecycleResource.java b/core/config/src/main/java/org/apache/isis/config/internal/_Config_LifecycleResource.java
index 1aeeca0..cda5fe8 100644
--- a/core/config/src/main/java/org/apache/isis/config/internal/_Config_LifecycleResource.java
+++ b/core/config/src/main/java/org/apache/isis/config/internal/_Config_LifecycleResource.java
@@ -20,6 +20,8 @@ package org.apache.isis.config.internal;
 
 import java.util.Optional;
 
+import org.slf4j.LoggerFactory;
+
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
@@ -59,7 +61,8 @@ class _Config_LifecycleResource {
             this.configurationBuildStacktrace = e;
         }
         
-        System.err.println("!!!!!!! IsisConfiguration BUILT");
+        // Logging in the context of IsisConfiguration
+        LoggerFactory.getLogger(IsisConfiguration.class).info("=== BUILT/DONE ===");
         
         return builder.build();
         
diff --git a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java b/core/config/src/main/java/org/apache/isis/core/commons/config/AppConfig.java
similarity index 53%
copy from example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
copy to core/config/src/main/java/org/apache/isis/core/commons/config/AppConfig.java
index e18f930..dd4d1c3 100644
--- a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/config/AppConfig.java
@@ -16,27 +16,16 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package domainapp.application;
-
-import org.apache.isis.applib.AppManifestAbstract2;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
-
-import domainapp.dom.HelloWorldModule;
+package org.apache.isis.core.commons.config;
 
 /**
- * Bootstrap the application.
+ * Entry-point for Application Bootstrapping
+ *  
+ * @since 2.0.0-M2
  */
-public class HelloWorldAppManifest extends AppManifestAbstract2 {
-
-    public static final Builder BUILDER = Builder
-            .forModule(new HelloWorldModule())
-            .withConfigurationPropertiesFile(HelloWorldAppManifest.class, "isis-non-changing.properties")
-            .withAuthMechanism("shiro");
-
-    public HelloWorldAppManifest() {
-        super(BUILDER);
-        System.err.println("!!!!!!! HelloWorldAppManifest");
-        _Exceptions.dumpStackTrace(System.err, 0, 1000);
-    }
+@FunctionalInterface
+public interface AppConfig {
 
+    public IsisConfiguration isisConfiguration();
+    
 }
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/config/AppConfigLocator.java b/core/config/src/main/java/org/apache/isis/core/commons/config/AppConfigLocator.java
new file mode 100644
index 0000000..600997b
--- /dev/null
+++ b/core/config/src/main/java/org/apache/isis/core/commons/config/AppConfigLocator.java
@@ -0,0 +1,27 @@
+package org.apache.isis.core.commons.config;
+
+import org.apache.isis.commons.internal.context._Context;
+import org.apache.isis.commons.internal.context._Plugin;
+
+public final class AppConfigLocator {
+    
+    private AppConfigLocator() { }
+    
+    public static AppConfig getAppConfig() {
+        return _Context.computeIfAbsent(AppConfig.class, __->lookupAppConfig());
+    }
+    
+    // -- HELPER
+    
+    private static AppConfig lookupAppConfig() {
+        return _Plugin.getOrElse(AppConfig.class,
+                ambiguousPlugins->{
+                    throw _Plugin.ambiguityNonRecoverable(AppConfig.class, ambiguousPlugins);
+                },
+                ()->{
+                    return IsisConfiguration::loadDefault;
+                });
+    }
+    
+
+}
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/config/AppManifestFinder.java b/core/config/src/main/java/org/apache/isis/core/commons/config/AppManifestFinder.java
new file mode 100644
index 0000000..d7a1930
--- /dev/null
+++ b/core/config/src/main/java/org/apache/isis/core/commons/config/AppManifestFinder.java
@@ -0,0 +1,83 @@
+/*
+ *  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.core.commons.config;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.AppManifest;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.context._Context;
+
+import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
+import static org.apache.isis.commons.internal.base._Strings.isNullOrEmpty;
+
+/**
+ * 
+ * @since 2.0.0-M2
+ * 
+ * @deprecated does not work, use {@link AppManifestLocator instead}
+ */
+class AppManifestFinder {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(AppManifestFinder.class);
+
+    static AppManifest findAppMainfestOrThrow() {
+        
+        // lookup all sorts of places for 'isis.properties' and other;
+        // see if we can find an entry 'isis.appManifest=xxx'
+        // that points to the AppManifest to use
+        
+        final String manifestKey = ConfigurationConstants.APP_MANIFEST_KEY;
+        
+        final String appManifestClassName = 
+            _Strings.read(_Context.getDefaultClassLoader().getResourceAsStream("/META-INF/app.manifest"), 
+                    StandardCharsets.UTF_8);
+        
+        //final String appManifestClassName = _Config.peekAtString(manifestKey);
+        if(isNullOrEmpty(appManifestClassName)) {
+            throw new IsisConfigurationException(
+                    String.format("Failed to find AppManifest from config properties. No value for key '%s' found.", 
+                            manifestKey));
+        }
+        Object appManifest;
+        try {
+            appManifest = _Context.loadClassAndInitialize(appManifestClassName);
+        } catch (ClassNotFoundException e) {
+            throw new IsisConfigurationException(
+                    String.format("Failed to instantiate AppManifest from config value '%s'.", 
+                            appManifestClassName));
+        }
+        return uncheckedCast(appManifest);
+    }
+    
+    static Optional<AppManifest> findAppMainfest() {
+        try {
+            return Optional.ofNullable(findAppMainfestOrThrow());
+        } catch (Exception e) {
+            LOG.warn(e.getMessage());
+            return Optional.empty();
+        }
+    }
+    
+    
+}
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/config/ConfigurationConstants.java b/core/config/src/main/java/org/apache/isis/core/commons/config/ConfigurationConstants.java
index 702afc2..283f666 100644
--- a/core/config/src/main/java/org/apache/isis/core/commons/config/ConfigurationConstants.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/config/ConfigurationConstants.java
@@ -21,12 +21,19 @@ package org.apache.isis.core.commons.config;
 
 import java.util.List;
 
+import org.apache.isis.applib.AppManifest;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 
 public final class ConfigurationConstants {
     
     public static final String ROOT = "isis.";
+    
+    /**
+     * Key used to lookup {@link AppManifest} (if any) from the {@link IsisConfiguration}.
+     */
+    public static final String APP_MANIFEST_KEY = ConfigurationConstants.ROOT + "appManifest";
+
 
     public static final String LIST_SEPARATOR = ",";
     public static final String DELIMITER = ".";
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
index fbeb6f1..b373e03 100644
--- a/core/config/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
@@ -24,9 +24,17 @@ import java.awt.Font;
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.isis.applib.AppManifest;
+import org.apache.isis.applib.Module;
+import org.apache.isis.applib.PropertyResource;
 import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
 import org.apache.isis.core.commons.resource.ResourceStreamSource;
 
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+import static org.apache.isis.config.internal._Config.acceptBuilder;
+import static org.apache.isis.config.internal._Config.clear;
+import static org.apache.isis.config.internal._Config.getConfiguration;
+
 /**
  * Immutable set of properties representing the configuration of the running
  * system.
@@ -61,6 +69,39 @@ public interface IsisConfiguration {
         EXCEPTION
     }
     
+    /**
+     * 
+     * @param topModule
+     * @param additionalPropertyResources
+     * @return
+     * @since 2.0.0-M2
+     */
+    static IsisConfiguration buildFromModuleTree(Module topModule, PropertyResource ... additionalPropertyResources) {
+        clear();
+        acceptBuilder(builder->{
+            stream(additionalPropertyResources)
+            .forEach(builder::addPropertyResource);
+            builder.addTopModule(topModule);
+        });
+        return getConfiguration();
+    }
+    
+    /**
+     * 
+     * @param topModule
+     * @param additionalPropertyResources
+     * @return
+     * @since 2.0.0-M2
+     */
+    static IsisConfiguration buildFromAppManifest(AppManifest appManifest) {
+        clear();
+        acceptBuilder(builder->{
+            builder.addAppManifest(appManifest);
+        });
+        return getConfiguration();
+    }
+    
+    public AppManifest getAppManifest();
 
     /**
      * Creates a new IsisConfiguration containing the properties starting with
@@ -218,6 +259,7 @@ public interface IsisConfiguration {
         return getBoolean("isis.reflector.explicitAnnotations.action");
     }
 
+    @Deprecated /* experimental */
     static IsisConfiguration loadDefault() {
         // TODO Auto-generated method stub
         return null;
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilder.java b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilder.java
index 4a6b99b..172286b 100644
--- a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilder.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilder.java
@@ -20,6 +20,9 @@ package org.apache.isis.core.commons.configbuilder;
 
 import java.util.List;
 
+import org.apache.isis.applib.AppManifest;
+import org.apache.isis.applib.Module;
+import org.apache.isis.applib.PropertyResource;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.config.NotFoundPolicy;
 import org.apache.isis.core.commons.resource.ResourceStreamSource;
@@ -27,6 +30,8 @@ import org.apache.isis.core.commons.resource.ResourceStreamSource;
 public interface IsisConfigurationBuilder {
     
     void addDefaultConfigurationResourcesAndPrimers();
+    
+    void addPropertyResource(PropertyResource propertyResource);
 
     void addResourceStreamSource(ResourceStreamSource resourceStreamSource);
     void addResourceStreamSources(ResourceStreamSource... resourceStreamSources);
@@ -62,6 +67,20 @@ public interface IsisConfigurationBuilder {
     boolean peekAtBoolean(String key, boolean defaultValue);
 
     String[] peekAtList(String key);
+    
+    /**
+     * Walks the module tree starting at the topModule to resolve all key/value pairs that 
+     * contribute to the configuration.
+     * @param topModule
+     * @since 2.0.0-M2
+     */
+    void addTopModule(Module topModule);
+    
+    /**
+     * @param appManifest
+     * @since 2.0.0-M2
+     */
+    void addAppManifest(AppManifest appManifest);
 
     /** internal only **/
     IsisConfiguration build();
@@ -83,4 +102,6 @@ public interface IsisConfigurationBuilder {
         return new IsisConfigurationBuilderDefault();
     }
 
+    
+
 }
\ No newline at end of file
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilderDefault.java b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilderDefault.java
index e541939..a43b345 100644
--- a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilderDefault.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationBuilderDefault.java
@@ -22,21 +22,24 @@ package org.apache.isis.core.commons.configbuilder;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Properties;
 import java.util.Set;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.isis.applib.AppManifest;
+import org.apache.isis.applib.AppManifestAbstract2;
+import org.apache.isis.applib.Module;
+import org.apache.isis.applib.PropertyResource;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.commons.config.IsisConfiguration.ContainsPolicy;
 import org.apache.isis.core.commons.config.NotFoundPolicy;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.resource.ResourceStreamSource;
 import org.apache.isis.core.commons.resource.ResourceStreamSourceChainOfResponsibility;
 import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
+import org.apache.isis.core.commons.resource.ResourceStreamSource_UsingClass;
 
 /**
  * Holds a mutable set of properties representing the configuration.
@@ -260,6 +263,35 @@ final class IsisConfigurationBuilderDefault implements IsisConfigurationBuilder
         LOG.debug("priming configurations for '{}'", primer);
         primer.prime(this);
     }
+    
+    // -- LOAD MODULE TREE
+    
+    @Override
+    public void addTopModule(Module topModule) {
+        final AppManifestAbstract2.Builder manifestBuilder = AppManifestAbstract2.Builder
+                .forModule(topModule);
+        final AppManifestAbstract2 manifest = new AppManifestAbstract2(manifestBuilder) {};
+        addAppManifest(manifest);
+    }
+    
+    @Override
+    public void addAppManifest(AppManifest appManifest) {
+        configuration.setAppManifest(appManifest);
+        appManifest.getConfigurationProperties().forEach((k, v)->{
+            put(k, v);
+        });
+    }
+        
+    // -- LOAD SINGLE RESOURCE
+        
+    @Override
+    public void addPropertyResource(PropertyResource propertyResource) {
+        IsisConfigurationDefault.ContainsPolicy ignorePolicy = IsisConfigurationDefault.ContainsPolicy.IGNORE;
+        NotFoundPolicy continuePolicy = NotFoundPolicy.CONTINUE;
+        
+        addResourceStreamSource(new ResourceStreamSource_UsingClass(propertyResource.getResourceContext()));
+        addConfigurationResource(propertyResource.getResourceName(), continuePolicy, ignorePolicy);
+    }
 
     // -- PEEKING
     
@@ -293,16 +325,21 @@ final class IsisConfigurationBuilderDefault implements IsisConfigurationBuilder
     @Override
     public IsisConfiguration build() {
         
-        dumpResourcesToLog();
+        if (LOG.isDebugEnabled()) {
+            dumpResourcesToLog();    
+        }
+
+        final IsisConfigurationDefault ref = configuration;
 
-        final IsisConfigurationDefault copy = new IsisConfigurationDefault(resourceStreamSourceChain);
-        final Properties props = new Properties();
-        props.putAll(configuration.asMap());
-        copy.add(props, ContainsPolicy.OVERWRITE);
+//TODO[2039] no need to copy        
+//        final IsisConfigurationDefault copy = new IsisConfigurationDefault(resourceStreamSourceChain);
+//        final Properties props = new Properties();
+//        props.putAll(configuration.asMap());
+//        copy.add(props, ContainsPolicy.OVERWRITE);
 
         configuration = null; // once built this builder is no longer usable
         
-        return copy;
+        return ref;
     }
 
     // -- dumpResourcesToLog, toString
@@ -312,20 +349,16 @@ final class IsisConfigurationBuilderDefault implements IsisConfigurationBuilder
      */
     @Override
     public void dumpResourcesToLog() {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Configuration resources FOUND:");
-            for (String resource : configurationResourcesFound) {
-                LOG.debug("*  {}", resource);
-            }
-            LOG.debug("Configuration resources NOT FOUND (but not needed):");
-            for (String resource : configurationResourcesNotFound) {
-                LOG.debug("*  {}", resource);
-            }
+        LOG.info("Configuration resources FOUND:");
+        for (String resource : configurationResourcesFound) {
+            LOG.info("*  {}", resource);
+        }
+        LOG.info("Configuration resources NOT FOUND (but not needed):");
+        for (String resource : configurationResourcesNotFound) {
+            LOG.info("*  {}", resource);
         }
     }
 
-    
-
     //TODO[2039]
     //    private final static ToString<IsisConfigurationBuilder> toString =
     //            ToString.<IsisConfigurationBuilder>
diff --git a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationDefault.java b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationDefault.java
index 8f11e51..6899f23 100644
--- a/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationDefault.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/configbuilder/IsisConfigurationDefault.java
@@ -31,6 +31,7 @@ import java.util.StringTokenizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.isis.applib.AppManifest;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
@@ -59,6 +60,7 @@ class IsisConfigurationDefault implements IsisConfiguration {
      * derived lazily from {@link #properties}.
      */
     private Properties applicationProperties;
+    private AppManifest appManifest;
 
     // ////////////////////////////////////////////////
     // Constructor
@@ -78,6 +80,20 @@ class IsisConfigurationDefault implements IsisConfiguration {
     }
 
     // ////////////////////////////////////////////////
+    // Property - Manifest
+    // ////////////////////////////////////////////////
+    
+    @Override
+    public AppManifest getAppManifest() {
+        return appManifest;
+    }
+    
+    public void setAppManifest(AppManifest appManifest) {
+        this.appManifest = appManifest;
+    }
+    
+    
+    // ////////////////////////////////////////////////
     // ResourceStreamSource
     // ////////////////////////////////////////////////
 
@@ -140,10 +156,10 @@ class IsisConfigurationDefault implements IsisConfiguration {
         if (properties.containsKey(key)) {
             switch (policy) {
             case IGNORE:
-                LOG.info("ignoring {}={} as value already set (with {})", key, value, properties.get(key));
+                LOG.info("ignoring '{}' = '{}' as value already set (with {})", key, value, properties.get(key));
                 break;
             case OVERWRITE:
-                LOG.info("overwriting {}={} (previous value was {})", key, value, properties.get(key));
+                LOG.info("overwriting '{}' = '{}' (previous value was {})", key, value, properties.get(key));
                 properties.put(key, value);
                 break;
             case EXCEPTION:
@@ -151,7 +167,7 @@ class IsisConfigurationDefault implements IsisConfiguration {
                         "Configuration already has a key {}, value of {}%s, value of %s", key, properties.get(key)));
             }
         } else {
-            LOG.info("adding {} = {}", key , ConfigurationConstants.maskIfProtected(key, value));
+            LOG.info("adding '{}' = '{}'", key , ConfigurationConstants.maskIfProtected(key, value));
             properties.put(key, value);
         }
     }
diff --git a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java b/core/config/src/main/java/org/apache/isis/core/commons/resource/ResourceStreamSource_UsingClass.java
similarity index 52%
copy from example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
copy to core/config/src/main/java/org/apache/isis/core/commons/resource/ResourceStreamSource_UsingClass.java
index e18f930..c0eb0e9 100644
--- a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
+++ b/core/config/src/main/java/org/apache/isis/core/commons/resource/ResourceStreamSource_UsingClass.java
@@ -16,27 +16,34 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package domainapp.application;
 
-import org.apache.isis.applib.AppManifestAbstract2;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
+package org.apache.isis.core.commons.resource;
 
-import domainapp.dom.HelloWorldModule;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.isis.commons.internal.resources._Resources;
 
 /**
- * Bootstrap the application.
+ * Load relative to the class-path context of the specified class.
+ * @since 2.0.0-M2
  */
-public class HelloWorldAppManifest extends AppManifestAbstract2 {
+public class ResourceStreamSource_UsingClass extends ResourceStreamSourceAbstract {
+
+    private final Class<?> contextClass;
+    
+    public ResourceStreamSource_UsingClass(Class<?> contextClass) {
+        this.contextClass = contextClass;
+    }
 
-    public static final Builder BUILDER = Builder
-            .forModule(new HelloWorldModule())
-            .withConfigurationPropertiesFile(HelloWorldAppManifest.class, "isis-non-changing.properties")
-            .withAuthMechanism("shiro");
+    @Override
+    protected InputStream doReadResource(final String resourcePath) throws IOException {
+        return _Resources.load(contextClass, resourcePath);
+    }
 
-    public HelloWorldAppManifest() {
-        super(BUILDER);
-        System.err.println("!!!!!!! HelloWorldAppManifest");
-        _Exceptions.dumpStackTrace(System.err, 0, 1000);
+    @Override
+    public String getName() {
+        return "classpath of '" + contextClass.getName() + "'";
     }
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/headless/IsisSystem.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/headless/IsisSystem.java
index 450a4e1..24b3416 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/headless/IsisSystem.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/headless/IsisSystem.java
@@ -27,7 +27,6 @@ import org.apache.isis.applib.fixtures.FixtureClock;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.config.internal._Config;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelInvalidException;
 import org.apache.isis.core.runtime.authentication.AuthenticationManager;
@@ -77,14 +76,7 @@ public class IsisSystem {
 
         protected AuthenticationRequest authenticationRequest = new AuthenticationRequestNameOnly("tester");
 
-        protected IsisConfigurationBuilder configurationBuilder = IsisConfigurationBuilder.empty();
-
-        protected AppManifest appManifestIfAny;
-
-        public T with(IsisConfigurationBuilder configurationBuilder) {
-            this.configurationBuilder = configurationBuilder;
-            return uncheckedCast(this);
-        }
+        protected AppManifest appManifest;
 
         public T with(AuthenticationRequest authenticationRequest) {
             this.authenticationRequest = authenticationRequest;
@@ -92,15 +84,14 @@ public class IsisSystem {
         }
 
         public T with(AppManifest appManifest) {
-            this.appManifestIfAny = appManifest;
+            this.appManifest = appManifest;
             return uncheckedCast(this);
         }
 
         public S build() {
             final IsisSystem isisSystem =
                     new IsisSystem(
-                            appManifestIfAny,
-                            configurationBuilder,
+                            appManifest != null ? appManifest : AppManifest.noop(),
                             authenticationRequest);
             return configure(uncheckedCast(isisSystem));
         }
@@ -137,19 +128,16 @@ public class IsisSystem {
     // -- constructor, fields
 
     // these fields 'xxxForComponentProvider' are used to initialize the IsisComponentProvider, but shouldn't be used thereafter.
-    protected final AppManifest appManifestIfAny;
-    protected final IsisConfigurationBuilder configurationBuilder;
+    protected final AppManifest appManifest;
 
     protected final AuthenticationRequest authenticationRequestIfAny;
     protected AuthenticationSession authenticationSession;
 
 
     protected IsisSystem(
-            final AppManifest appManifestIfAny,
-            final IsisConfigurationBuilder configurationBuilder,
+            final AppManifest appManifest,
             final AuthenticationRequest authenticationRequestIfAny) {
-        this.appManifestIfAny = appManifestIfAny;
-        this.configurationBuilder = configurationBuilder;
+        this.appManifest = appManifest;
         this.authenticationRequestIfAny = authenticationRequestIfAny;
     }
 
@@ -182,13 +170,13 @@ public class IsisSystem {
         if(firstTime) {
 
             componentProvider = IsisComponentProvider.builder()
-                    .appManifest(appManifestIfAny)
+                    .appManifest(appManifest)
                     .build();
             
             _Config.acceptBuilder(IsisContext.EnvironmentPrimer::primeEnvironment);
 
             final IsisSessionFactoryBuilder isisSessionFactoryBuilder = 
-                    new IsisSessionFactoryBuilder(componentProvider, appManifestIfAny);
+                    new IsisSessionFactoryBuilder(componentProvider, appManifest);
 
             // ensures that a FixtureClock is installed as the singleton underpinning the ClockService
             FixtureClock.initialize();
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/runner/opts/OptionHandlerAppManifest.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/runner/opts/OptionHandlerAppManifest.java
index 0ae5d33..d7ae476 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/runner/opts/OptionHandlerAppManifest.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/runner/opts/OptionHandlerAppManifest.java
@@ -19,9 +19,6 @@
 
 package org.apache.isis.core.runtime.runner.opts;
 
-import static org.apache.isis.core.runtime.runner.Constants.APP_MANIFEST_LONG_OPT;
-import static org.apache.isis.core.runtime.runner.Constants.APP_MANIFEST_OPT;
-
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionBuilder;
@@ -29,11 +26,14 @@ import org.apache.commons.cli.Options;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
 import org.apache.isis.core.runtime.optionhandler.BootPrinter;
 import org.apache.isis.core.runtime.optionhandler.OptionHandlerAbstract;
 import org.apache.isis.core.runtime.runner.Constants;
-import org.apache.isis.core.runtime.system.SystemConstants;
+
+import static org.apache.isis.core.runtime.runner.Constants.APP_MANIFEST_LONG_OPT;
+import static org.apache.isis.core.runtime.runner.Constants.APP_MANIFEST_OPT;
 
 public class OptionHandlerAppManifest extends OptionHandlerAbstract {
 
@@ -66,7 +66,7 @@ public class OptionHandlerAppManifest extends OptionHandlerAbstract {
         if (appManifestClassName == null) {
             return;
         }
-        prime(isisConfigurationBuilder, SystemConstants.APP_MANIFEST_KEY, appManifestClassName);
+        prime(isisConfigurationBuilder, ConfigurationConstants.APP_MANIFEST_KEY, appManifestClassName);
     }
 
     static void prime(IsisConfigurationBuilder isisConfigurationBuilder, String key, String value) {
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/SystemConstants.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/SystemConstants.java
index 8d16678..bf4699c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/SystemConstants.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/SystemConstants.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.core.runtime.system;
 
-import org.apache.isis.applib.AppManifest;
 import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.runtime.authentication.AuthenticationManager;
@@ -34,11 +33,6 @@ public final class SystemConstants {
     public static final String MSG_CANCEL = "Cancel";
 
     /**
-     * Key used to lookup {@link AppManifest} (if any) from the {@link IsisConfiguration}.
-     */
-    public static final String APP_MANIFEST_KEY = ConfigurationConstants.ROOT + "appManifest";
-
-    /**
      * Key used to lookup {@link AuthenticationManager authentication manager}
      * in {@link IsisConfiguration}, and root for any
      * {@link AuthenticationManagerInstaller authentication manager}-specific
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
index 2611587..a98e668 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
@@ -46,6 +46,7 @@ import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.config.internal._Config;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.configbuilder.IsisConfigurationBuilder;
 import org.apache.isis.core.commons.factory.InstanceUtil;
 import org.apache.isis.core.commons.lang.ClassFunctions;
@@ -66,8 +67,6 @@ import org.apache.isis.core.runtime.services.ServicesInstallerFromAnnotation;
 import org.apache.isis.core.runtime.services.ServicesInstallerFromConfiguration;
 import org.apache.isis.core.runtime.services.ServicesInstallerFromConfigurationAndAnnotation;
 import org.apache.isis.core.runtime.system.IsisSystemException;
-import org.apache.isis.core.runtime.system.SystemConstants;
-import org.apache.isis.objectstore.jdo.service.RegisterEntities;
 import org.apache.isis.progmodels.dflt.JavaReflectorHelper;
 import org.apache.isis.progmodels.dflt.ProgrammingModelFacetsJava5;
 
@@ -140,7 +139,7 @@ public final class IsisComponentProvider {
         // required to prevent RegisterEntities validation from complaining
         // if it can't find any @PersistenceCapable entities in a module
         // that contains only services.
-        _Config.put(SystemConstants.APP_MANIFEST_KEY, appManifest.getClass().getName() );
+        _Config.put(ConfigurationConstants.APP_MANIFEST_KEY, appManifest.getClass().getName() );
     }
 
     private void findAndRegisterTypes(final AppManifest appManifest) {
@@ -253,7 +252,6 @@ public final class IsisComponentProvider {
 
         acceptBuilder(builder->{
             builder.add(ServicesInstallerFromAnnotation.PACKAGE_PREFIX_KEY, packageNamesCsv);
-            builder.add(RegisterEntities.PACKAGE_PREFIX_KEY, packageNamesCsv);    
         });
 
         final List<Class<?>> additionalServices = appManifest.getAdditionalServices();
@@ -314,16 +312,19 @@ public final class IsisComponentProvider {
     private void addToConfigurationUsing(final AppManifest appManifest) {
         final Map<String, String> configurationProperties = appManifest.getConfigurationProperties();
         
+        if (configurationProperties == null) {
+            return;
+        }
+        
         acceptBuilder(builder->{
         
-            if (configurationProperties != null) {
-                for (Map.Entry<String, String> configProp : configurationProperties.entrySet()) {
-                    builder.add(configProp.getKey(), configProp.getValue());
-                }
+            for (Map.Entry<String, String> configProp : configurationProperties.entrySet()) {
+                builder.add(configProp.getKey(), configProp.getValue());
             }
-            
+        
         });
         
+        
     }
 
     // -- provideAuth*
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppConfigHelper.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppConfigHelper.java
index 844ce08..048c7de 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppConfigHelper.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppConfigHelper.java
@@ -40,8 +40,6 @@ public final class IsisWebAppConfigHelper {
     private static final Logger LOG = LoggerFactory.getLogger(IsisWebAppConfigHelper.class);
     private IsisWebAppConfigHelper() {}
     
-    //private final Map<String, String> additionalConfig = _Maps.newHashMap();
-    
     /**
      * Initializes the IsisConfiguration subsystem with all currently available configuration values. 
      * @param servletContext
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 f57955f..e03ec78 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
@@ -40,12 +40,6 @@ public class RegisterEntities {
     @SuppressWarnings("unused")
     private final static Logger LOG = LoggerFactory.getLogger(RegisterEntities.class);
 
-    /**
-     * @deprecated - no longer used; instead an AppManifest must be specified.
-     */
-    @Deprecated
-    public final static String PACKAGE_PREFIX_KEY = "isis.persistor.datanucleus.RegisterEntities.packagePrefix";
-
     private final _Lazy<Set<String>> entityTypes = _Lazy.threadSafe(this::findEntityTypes);
 
     public Set<String> getEntityTypes() {
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/isis/IsisInjectModule.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/isis/IsisInjectModule.java
index c1e3b79..68c0f9f 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/isis/IsisInjectModule.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/isis/IsisInjectModule.java
@@ -19,72 +19,44 @@
 
 package org.apache.isis.viewer.wicket.viewer.integration.isis;
 
-import java.util.List;
-import java.util.Map;
-
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Singleton;
 
 import org.apache.isis.applib.AppManifest;
-import org.apache.isis.applib.fixturescripts.FixtureScript;
-import org.apache.isis.commons.internal.base._With;
 import org.apache.isis.config.internal._Config;
-import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.commons.config.AppConfigLocator;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
-import org.apache.isis.core.runtime.system.SystemConstants;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactoryBuilder;
 import org.apache.isis.core.runtime.systemusinginstallers.IsisComponentProvider;
 
-import static org.apache.isis.commons.internal.base._With.computeIfAbsent;
-
 public class IsisInjectModule extends AbstractModule {
 
-    /**
-     * Placeholder for no {@link AppManifest}.
-     *
-     * <p>
-     *     This is bound in by default in <tt>IsisWicketModule</tt>, but is replaced with null when the system is
-     *     {@link #provideIsisSessionFactory(AppManifest)} created} .
-     * </p>
-     */
-    private static final AppManifest APP_MANIFEST_NOOP = AppManifest.noop();
-
-    /**
-     * Allows the {@link AppManifest} to be programmatically bound in.
-     *
-     * <p>
-     *     For example, this can be done in override of
-     *     <code>IsisWicketApplication#newIsisWicketModule</code>.
-     * </p>
-     */
     @Override
     protected void configure() {
-        bind(AppManifest.class).toInstance(APP_MANIFEST_NOOP);
+        AppConfigLocator.getAppConfig().isisConfiguration();
     }
 
     @Provides
     @com.google.inject.Inject
     @Singleton
-    protected IsisSessionFactory provideIsisSessionFactory(final AppManifest boundAppManifest) {
+    protected IsisSessionFactory provideIsisSessionFactory() {
         
-        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 1 "+Thread.currentThread().getName());
+        AppManifest appManifest = _Config.getConfiguration().getAppManifest();
         
-        final AppManifest appManifestToUse = determineAppManifest(boundAppManifest);
+        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 1 "+Thread.currentThread().getName());
 
-        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 2 "+Thread.currentThread().getName());
-        
         final IsisComponentProvider componentProvider = IsisComponentProvider
-                .builderUsingInstallers(appManifestToUse)
+                .builderUsingInstallers(appManifest)
                 .build();
         
-        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 3 "+Thread.currentThread().getName());
+        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 2 "+Thread.currentThread().getName());
 
         final IsisSessionFactoryBuilder builder =
-                new IsisSessionFactoryBuilder(componentProvider, componentProvider.getAppManifest());
+                new IsisSessionFactoryBuilder(componentProvider, appManifest);
         
-        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 4 "+Thread.currentThread().getName());
+        System.err.println("!!!!!!!!!! provideIsisSessionFactory STAGE 3 "+Thread.currentThread().getName());
 
         // as a side-effect, if the metamodel turns out to be invalid, then
         // this will push the MetaModelInvalidException into IsisContext.
@@ -102,30 +74,5 @@ public class IsisInjectModule extends AbstractModule {
         return isisSessionFactory.getServicesInjector();
     }
 
-    // -- HELPER
-    
-    /**
-     * If an {@link AppManifest} was explicitly provided (eg from the Guice <tt>IsisWicketModule</tt> when running
-     * unde the Wicket viewer) then use that; otherwise read the <tt>isis.properties</tt> config file and look
-     * for an <tt>isis.appManifest</tt> entry instead.
-     */
-    private AppManifest determineAppManifest(final AppManifest boundAppManifest) {
-        final AppManifest appManifest =
-                boundAppManifest != APP_MANIFEST_NOOP
-                ? boundAppManifest
-                        : null;
-
-        return computeIfAbsent(appManifest, IsisInjectModule::getAppManifestFromConfig);
-    }
-
-    private static AppManifest getAppManifestFromConfig() {
-
-        System.err.println("WARNING: accessing Configuration prior to it being built"); //TODO[2039] ... use logger 
-        final String appManifestFromConfiguration = _Config.peekAtString(SystemConstants.APP_MANIFEST_KEY);
-        return appManifestFromConfiguration != null
-                ? InstanceUtil.createInstance(appManifestFromConfiguration, AppManifest.class)
-                        : null;
-    }
-
 
 }
diff --git a/example/application/helloworld/src/main/java/META-INF/services/org.apache.isis.core.commons.config.AppConfig b/example/application/helloworld/src/main/java/META-INF/services/org.apache.isis.core.commons.config.AppConfig
new file mode 100644
index 0000000..6730008
--- /dev/null
+++ b/example/application/helloworld/src/main/java/META-INF/services/org.apache.isis.core.commons.config.AppConfig
@@ -0,0 +1 @@
+domainapp.application.HelloWorldAppConfig
\ No newline at end of file
diff --git a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppConfig.java b/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppConfig.java
index 4f00a90..948a356 100644
--- a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppConfig.java
+++ b/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppConfig.java
@@ -20,31 +20,18 @@ package domainapp.application;
 
 import javax.enterprise.inject.Produces;
 
-import org.apache.isis.applib.Module;
-import org.apache.isis.config.internal._Config;
+import org.apache.isis.core.commons.config.AppConfig;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 
 /**
- * Bootstrap the application.
+ * Tells the ServiceLoader which AppManifest to use to bootstrap the Application.  
  */
-public class HelloWorldAppConfig {  // <<< managed and discovered by IoC container
+public class HelloWorldAppConfig implements AppConfig {
 
     @Produces
     public IsisConfiguration isisConfiguration () {
-        
-     // code contributed by user ...
-        
-        //ResourceStreamSource resourceStreamSource = ResourceStreamSourceCurrentClassClassPath
-        //_Config.acceptBuilder(builder->builder.addResourceStreamSource(resourceStreamSource));
-        return _Config.getConfiguration();        
-                //. FromConfig("isis.properties");
-    }
-
-
-    @Produces
-    public Module appModule() {
-        // code contributed by user ...
-        return new HelloWorldAppManifest().getModule(); 
+        return IsisConfiguration.buildFromAppManifest(new HelloWorldAppManifest());
     }
+    
 }
 
diff --git a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java b/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
index e18f930..1e5baa9 100644
--- a/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
+++ b/example/application/helloworld/src/main/java/domainapp/application/HelloWorldAppManifest.java
@@ -19,7 +19,6 @@
 package domainapp.application;
 
 import org.apache.isis.applib.AppManifestAbstract2;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
 
 import domainapp.dom.HelloWorldModule;
 
@@ -35,8 +34,6 @@ public class HelloWorldAppManifest extends AppManifestAbstract2 {
 
     public HelloWorldAppManifest() {
         super(BUILDER);
-        System.err.println("!!!!!!! HelloWorldAppManifest");
-        _Exceptions.dumpStackTrace(System.err, 0, 1000);
     }
 
 }
diff --git a/example/application/helloworld/src/test/java/domainapp/application/HelloWorldAppConfigTest.java b/example/application/helloworld/src/test/java/domainapp/application/HelloWorldAppConfigTest.java
new file mode 100644
index 0000000..6a62e37
--- /dev/null
+++ b/example/application/helloworld/src/test/java/domainapp/application/HelloWorldAppConfigTest.java
@@ -0,0 +1,34 @@
+package domainapp.application;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.apache.isis.core.commons.config.AppConfigLocator;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+
+class HelloWorldAppConfigTest {
+
+    @BeforeEach
+    void setUp() throws Exception {
+    }
+
+    @AfterEach
+    void tearDown() throws Exception {
+    }
+
+    @Test
+    void test() {
+        
+        IsisConfiguration isisConfiguration = AppConfigLocator.getAppConfig().isisConfiguration();
+        Assertions.assertNotNull(isisConfiguration);
+        
+        Map<String, String> config = isisConfiguration.asMap();
+        Assertions.assertNotNull(config);
+        Assertions.assertTrue(config.size()>20);
+    }
+
+}