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

andysch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git

commit 26ea9fec4ce93cd501ba2b18c1781550618ae742
Author: Andreas Schaefer <[email protected]>
AuthorDate: Sat Mar 27 22:35:14 2021 -0700

    Removed the Setup and made the DDR configurable through the source 
resources through primary type and property
---
 org.apache.sling.ddr/README.md                     |  32 ++
 .../ddr/api/DeclarativeDynamicResourceSetup.java   |  23 --
 org.apache.sling.ddr/core/pom.xml                  |   3 +
 .../DeclarativeDynamicResourceManagerService.java  | 179 +++++++---
 .../DeclarativeDynamicResourceSetupService.java    | 362 ---------------------
 ...g.jcr.repoinit.RepositoryInitializer-ddr.config |   2 -
 .../main/resources/SLING-CONTENT/nodetypes/ddr.cnd |  23 ++
 org.apache.sling.ddr/sample/Readme.md              |  37 +++
 org.apache.sling.ddr/sample/pom.xml                |   1 +
 .../SLING-CONTENT/apps/ddr-dynamic/components.json |   4 +-
 .../resources/SLING-CONTENT/apps/ddr-sample.json   |   4 +-
 ...iveDynamicResourceManagerService-ddrsample.json |   4 -
 ...ativeDynamicResourceSetupService-ddrsample.json |  16 -
 ...repoinit.RepositoryInitializer-ddrsample.config |  38 ---
 .../apps/ddr-static/{container.json => text.json}  |   0
 .../{container/container.html => text/text.html}   |   2 +-
 .../resources/SLING-CONTENT/conf/ddr-sample.json   |   4 +
 .../SLING-CONTENT/conf/ddr-sample/settings.json    |  23 ++
 .../SLING-CONTENT/content/ddr-sample/text.json     |   4 +
 19 files changed, 262 insertions(+), 499 deletions(-)

diff --git a/org.apache.sling.ddr/README.md b/org.apache.sling.ddr/README.md
new file mode 100644
index 0000000..a1822eb
--- /dev/null
+++ b/org.apache.sling.ddr/README.md
@@ -0,0 +1,32 @@
+# Apache Sling Declarative Dynamic Resources
+
+## Introduction
+
+In Peregrine CMS we were facing the fact that each tenant had their own set of 
components that were
+just a redirection through their Sling Resource Super Type to a component 
provided by Peregrine. This
+was the Tenant could maintain their components but Peregrine could add new 
components w/o affecting
+or confusing the tenant.
+In addition, if Peregrine wants to make new components available we face the 
issue of a read-only
+JCR tree in /libs and /apps which would require a new deployment and restart 
of Peregrine.
+
+## Declarative Dynamic Resource
+
+Both of these issues can be solved by creating Synthetic Resources that appear 
in the desired target
+resource but its actual content is provided from another node.
+The Declarative Dynamic Resource (DDR) is composed of these components:
+
+* Declarative Dynamic Resource Manager: listens to DDRs becoming available and 
then creates the Synthetic Resources needed
+* Declarative Dynamic Resource Provider: a Resource Provider for any DDR 
source properly configured
+* Declarative Dynamic Resource: a Synthetic Resource that lives in a given 
node and points to its source for its properties
+* Declarative Dynamic Resource Listener: an interface that informs the 
implementor about newly created DDRs
+
+The DDR is using its own Service User **ddr-serviceuser** that is used to read 
and handle DDRs.
+
+Any source folder needs to set the **jcr:primaryType** to **slingddr:Folder** 
and set the property
+**slingddr:target** to the path of the target folder of its DDR. That path 
needs to be absolute and
+point to an existing resource. Keep in mind that this path points to the 
parent of a DDR as each node
+inside the source is creating a DDR with the path of the target as parent and 
the source name as
+name of the DDR. Keep in mind that **no resource with that name** can existing 
in the target folder
+otherwise it will be shadowed by the existing resource.
+
+Andreas Schaefer, 3/27/2021
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/api/src/main/java/org/apache/sling/ddr/api/DeclarativeDynamicResourceSetup.java
 
b/org.apache.sling.ddr/api/src/main/java/org/apache/sling/ddr/api/DeclarativeDynamicResourceSetup.java
deleted file mode 100644
index dc44211..0000000
--- 
a/org.apache.sling.ddr/api/src/main/java/org/apache/sling/ddr/api/DeclarativeDynamicResourceSetup.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations 
under
- * the License.
- */
-package org.apache.sling.ddr.api;
-
-/**
- * Marker Interface for the Setup Service for Dynamic Source Instances
- */
-public interface DeclarativeDynamicResourceSetup {
-}
diff --git a/org.apache.sling.ddr/core/pom.xml 
b/org.apache.sling.ddr/core/pom.xml
index 550c5d8..738ab6c 100644
--- a/org.apache.sling.ddr/core/pom.xml
+++ b/org.apache.sling.ddr/core/pom.xml
@@ -52,6 +52,9 @@
                             Private-Package,
                             Include-Resource
                         </_removeheaders>
+                        <Sling-Nodetypes>
+                            SLING-CONTENT/nodetypes/ddr.cnd
+                        </Sling-Nodetypes>
                         <Sling-Initial-Content>
                             
SLING-CONTENT/apps/ddr;path:=/apps/ddr;overwrite:=true;overwriteProperties:=true
                         </Sling-Initial-Content>
diff --git 
a/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/DeclarativeDynamicResourceManagerService.java
 
b/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/DeclarativeDynamicResourceManagerService.java
index 1f19d50..fb7b447 100644
--- 
a/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/DeclarativeDynamicResourceManagerService.java
+++ 
b/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/DeclarativeDynamicResourceManagerService.java
@@ -28,17 +28,20 @@ import 
org.apache.sling.serviceusermapping.ServiceUserMapped;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.ConfigurationPolicy;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.osgi.service.component.annotations.ReferencePolicyOption;
-import org.osgi.service.metatype.annotations.AttributeDefinition;
-import org.osgi.service.metatype.annotations.Designate;
-import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.query.Query;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -49,23 +52,24 @@ import static 
org.apache.sling.ddr.api.Constants.JCR_PRIMARY_TYPE;
 import static org.apache.sling.ddr.api.Constants.REP_POLICY;
 
 @Component(
-    service= DeclarativeDynamicResourceManager.class,
-    immediate = true,
-    configurationPolicy = ConfigurationPolicy.REQUIRE
+    service = { DeclarativeDynamicResourceManager.class, EventListener.class },
+    immediate = true
 )
-@Designate(ocd = DeclarativeDynamicResourceManagerService.Configuration.class, 
factory = true)
 public class DeclarativeDynamicResourceManagerService
-    implements DeclarativeDynamicResourceManager
+    implements DeclarativeDynamicResourceManager, EventListener
 {
-    @ObjectClassDefinition(
-        name = "Declarative Dynamic Component Resource Provider",
-        description = "Configuration of the Dynamic Component Resource 
Provider")
-    public @interface Configuration {
-        @AttributeDefinition(
-            name = "Dynamic Component Target Path",
-            description="Path to the Folder where the Dynamic Components will 
added to dynamically")
-        String dynamic_component_target_path();
-    }
+    public static final int EVENT_TYPES =
+        Event.NODE_ADDED |
+        Event.NODE_REMOVED |
+        Event.NODE_MOVED |
+        Event.PROPERTY_ADDED |
+        Event.PROPERTY_CHANGED |
+        Event.PROPERTY_REMOVED;
+
+    public static final String DDR_NODE_TYPE = "slingddr:Folder";
+    public static final String DDR_TARGET_PROPERTY_NAME = "slingddr:target";
+    public static final String[] NODE_TYPES = new String[] { DDR_NODE_TYPE };
+    public static final String CONFIGURATION_ROOT_PATH = "/conf";
 
     @Reference
     private ResourceResolverFactory resourceResolverFactory;
@@ -81,14 +85,82 @@ public class DeclarativeDynamicResourceManagerService
 
     private Map<String, DeclarativeDynamicResourceProvider> registeredServices 
= new HashMap<>();
     private BundleContext bundleContext;
-    private String dynamicTargetPath;
+//    private String dynamicTargetPath;
 
     @Activate
-    private void activate(BundleContext bundleContext, Configuration 
configuration) {
-        log.info("Activate Started, bundle context: '{}'", bundleContext);
+    private void activate(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
-        dynamicTargetPath = configuration.dynamic_component_target_path();
-        log.info("Dynamic Target Path: '{}'", dynamicTargetPath);
+        log.info("Activate Started, bundle context: '{}'", bundleContext);
+        try (ResourceResolver resourceResolver = 
resourceResolverFactory.getServiceResourceResolver(
+            new HashMap<String, Object>() {{ 
put(ResourceResolverFactory.SUBSERVICE, DYNAMIC_COMPONENTS_SERVICE_USER); }}
+        )) {
+            // Register an Event Listener to get informed when
+            Session session = resourceResolver.adaptTo(Session.class);
+            if (session != null) {
+                log.info("Register Event Listener on Path: '{}'", 
CONFIGURATION_ROOT_PATH);
+                
session.getWorkspace().getObservationManager().addEventListener(
+                    this, EVENT_TYPES, CONFIGURATION_ROOT_PATH,
+                    true, null, null, true
+                );
+            } else {
+                log.warn("Resource Resolver could not be adapted to Session");
+            }
+            // To make sure we get all we will query all existing nodes
+            Resource root = 
resourceResolver.getResource(CONFIGURATION_ROOT_PATH);
+            log.info("Manual Check for Existing Nodes in: '{}'", 
CONFIGURATION_ROOT_PATH);
+            if(root != null) {
+                Iterator<Resource> i = resourceResolver.findResources(
+                    "SELECT * FROM [slingddr:Folder]",
+                    Query.JCR_SQL2
+                );
+                while(i.hasNext()) {
+                    Resource item = i.next();
+                    log.info("Handle Found DDR Resource: '{}'", item);
+                    handleDDRResource(item);
+                }
+            }
+        } catch (LoginException e) {
+            log.error("Failed to Activation Resource", e);
+        } catch (UnsupportedRepositoryOperationException e) {
+            log.error("Failed to Activation Resource", e);
+        } catch (RepositoryException e) {
+            log.error("Failed to Activation Resource", e);
+        }
+    }
+
+    private void handleDDRResource(Resource ddrSourceResource) {
+        if(ddrSourceResource != null) {
+            ValueMap properties = ddrSourceResource.getValueMap();
+            String ddrTargetPath = properties.get(DDR_TARGET_PROPERTY_NAME, 
String.class);
+            log.info("Found DDR Target Path: '{}'", ddrTargetPath);
+            if (ddrTargetPath != null) {
+                Resource ddrTargetResource = 
ddrSourceResource.getResourceResolver().getResource(ddrTargetPath);
+                if(ddrTargetResource != null) {
+                    DeclarativeDynamicResourceProviderHandler service = new 
DeclarativeDynamicResourceProviderHandler();
+                    log.info("Dynamic Target: '{}', Dynamic Provider: '{}'", 
ddrSourceResource, ddrSourceResource);
+                    long id = 
service.registerService(bundleContext.getBundle(), ddrTargetPath, 
ddrSourceResource.getPath(), resourceResolverFactory);
+                    log.info("After Registering Tenant RP: service: '{}', id: 
'{}'", service, id);
+                    registeredServices.put(ddrTargetResource.getPath(), 
service);
+                    Iterator<Resource> i = ddrSourceResource.listChildren();
+                    while (i.hasNext()) {
+                        Resource provided = i.next();
+                        String componentName = provided.getName();
+                        if (componentName.equals(REP_POLICY)) {
+                            continue;
+                        }
+                        log.info("Provided Dynamic: '{}'", provided);
+                        ValueMap childProperties = provided.getValueMap();
+                        String primaryType = 
childProperties.get(JCR_PRIMARY_TYPE, String.class);
+                        log.info("Dynamic Child Source: '{}', Primary Type: 
'{}'", componentName, primaryType);
+                        if (componentName != null && !componentName.isEmpty() 
&& dynamicComponentFilterNotifier != null) {
+                            
dynamicComponentFilterNotifier.addDeclarativeDynamicResource(
+                                ddrTargetPath + '/' + componentName, provided
+                            );
+                        }
+                    }
+                }
+            }
+        }
     }
 
     public void update(String dynamicProviderPath) {
@@ -96,32 +168,7 @@ public class DeclarativeDynamicResourceManagerService
             new HashMap<String, Object>() {{ 
put(ResourceResolverFactory.SUBSERVICE, DYNAMIC_COMPONENTS_SERVICE_USER); }}
         )) {
             Resource dynamicProvider = 
resourceResolver.getResource(dynamicProviderPath);
-            Resource dynamicTarget = 
resourceResolver.getResource(dynamicTargetPath);
-            log.info("Dynamic Resource Provider: '{}', Target: '{}'", 
dynamicProvider, dynamicTarget);
-            if(dynamicProvider != null) {
-                DeclarativeDynamicResourceProviderHandler service = new 
DeclarativeDynamicResourceProviderHandler();
-                log.info("Dynamic Target: '{}', Dynamic Provider: '{}'", 
dynamicTarget, dynamicProvider);
-                long id = service.registerService(bundleContext.getBundle(), 
dynamicTargetPath, dynamicProviderPath, resourceResolverFactory);
-                log.info("After Registering Tenant RP: service: '{}', id: 
'{}'", service, id);
-                registeredServices.put(dynamicTarget.getPath(), service);
-                Iterator<Resource> i = dynamicProvider.listChildren();
-                while (i.hasNext()) {
-                    Resource provided = i.next();
-                    String componentName = provided.getName();
-                    if (componentName.equals(REP_POLICY)) {
-                        continue;
-                    }
-                    log.info("Provided Dynamic: '{}'", provided);
-                    ValueMap childProperties = provided.getValueMap();
-                    String primaryType = childProperties.get(JCR_PRIMARY_TYPE, 
String.class);
-                    log.info("Dynamic Child Source: '{}', Primary Type: '{}'", 
componentName, primaryType);
-                    if (componentName != null && !componentName.isEmpty() && 
dynamicComponentFilterNotifier != null) {
-                        
dynamicComponentFilterNotifier.addDeclarativeDynamicResource(
-                            dynamicTargetPath + '/' + componentName, provided
-                        );
-                    }
-                }
-            }
+            handleDDRResource(dynamicProvider);
         } catch (LoginException e) {
             log.error("Was not able to obtain Service Resource Resolver", e);
         }
@@ -135,5 +182,39 @@ public class DeclarativeDynamicResourceManagerService
             log.info("After UnRegistering Tenant RP, service: '{}'", service);
         }
     }
+
+    @Override
+    public void onEvent(EventIterator events) {
+        try (ResourceResolver resourceResolver = 
resourceResolverFactory.getServiceResourceResolver(
+            new HashMap<String, Object>() {{ 
put(ResourceResolverFactory.SUBSERVICE, DYNAMIC_COMPONENTS_SERVICE_USER); }}
+        )) {
+            while (events.hasNext()) {
+                Event event = events.nextEvent();
+                String path = event.getPath();
+                switch (event.getType()) {
+                    case Event.PROPERTY_ADDED:
+                    case Event.PROPERTY_CHANGED:
+                        int index = path.lastIndexOf('/');
+                        if(index > 0) {
+                            path = path.substring(0, index -1);
+                        }
+                    case Event.NODE_ADDED:
+                        Resource source = resourceResolver.getResource(path);
+                        if(source != null) {
+                            handleDDRResource(source);
+                        }
+                        break;
+                    case Event.NODE_MOVED:
+                        //AS TODO: Handle later
+                        break;
+                    case Event.PROPERTY_REMOVED:
+                        //AS TODO: Handle later
+//                        break;
+                }
+            }
+        } catch (LoginException | RepositoryException e) {
+            log.error("Failed to Handle Events", e);
+        }
+    }
 }
 
diff --git 
a/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/setup/DeclarativeDynamicResourceSetupService.java
 
b/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/setup/DeclarativeDynamicResourceSetupService.java
deleted file mode 100644
index eb132de..0000000
--- 
a/org.apache.sling.ddr/core/src/main/java/org/apache/sling/ddr/core/setup/DeclarativeDynamicResourceSetupService.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations 
under
- * the License.
- */
-package org.apache.sling.ddr.core.setup;
-
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.ddr.api.DeclarativeDynamicResourceSetup;
-import org.apache.sling.ddr.api.DeclarativeDynamicResourceManager;
-import org.apache.sling.serviceusermapping.ServiceUserMapped;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferencePolicyOption;
-import org.osgi.service.metatype.annotations.AttributeDefinition;
-import org.osgi.service.metatype.annotations.Designate;
-import org.osgi.service.metatype.annotations.ObjectClassDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.sling.ddr.api.Constants.CLOSING_MULTIPLE;
-import static org.apache.sling.ddr.api.Constants.COMPONENT_GROUP;
-import static 
org.apache.sling.ddr.api.Constants.DYNAMIC_COMPONENTS_SERVICE_USER;
-import static org.apache.sling.ddr.api.Constants.DYNAMIC_COMPONENT_FOLDER_NAME;
-import static org.apache.sling.ddr.api.Constants.EQUALS;
-import static org.apache.sling.ddr.api.Constants.JCR_PRIMARY_TYPE;
-import static org.apache.sling.ddr.api.Constants.JCR_TITLE;
-import static org.apache.sling.ddr.api.Constants.MULTI_SEPARATOR;
-import static org.apache.sling.ddr.api.Constants.NT_UNSTRUCTURED;
-import static org.apache.sling.ddr.api.Constants.OPENING_MULTIPLE;
-import static org.apache.sling.ddr.api.Constants.REFERENCE_PROPERTY_NAME;
-import static org.apache.sling.ddr.api.Constants.REP_POLICY;
-import static org.apache.sling.ddr.api.Constants.SLING_FOLDER;
-import static 
org.apache.sling.ddr.api.Constants.SLING_RESOURCE_SUPER_TYPE_PROPERTY;
-import static org.apache.sling.ddr.api.Constants.VERTICAL_LINE;
-
-@Component(
-    service= { DeclarativeDynamicResourceSetup.class, EventListener.class },
-    immediate = true
-)
-@Designate(ocd = DeclarativeDynamicResourceSetupService.Configuration.class, 
factory = true)
-public class DeclarativeDynamicResourceSetupService
-    implements DeclarativeDynamicResourceSetup, EventListener
-{
-
-    @ObjectClassDefinition(
-        name = "Declarative Dynamic Resource Setup",
-        description = "Configuration of the Setup for Declarative Dynamic 
Resource Provider")
-    public @interface Configuration {
-        @AttributeDefinition(
-            name = "Dynamic Target Path",
-            description = "The Location where the DDR are made available")
-        String dynamic_component_target_path() default "/apps/wknd/components";
-        @AttributeDefinition(
-            name = "Dynamic Source Root Path",
-            description = "The Location of the Source for the DDRs")
-        String dynamic_component_root_path() default "/conf/wknd/settings";
-        @AttributeDefinition(
-            name = "Component Group of the Dynamic Components",
-            description = "Component Group Name")
-        String dynamic_component_group() default "WKND.Content";
-        @AttributeDefinition(
-            name = "Primary Group",
-            description = "Component Primary Type")
-        String dynamic_component_primary_type() default "cq:Component";
-        @AttributeDefinition(
-            name = "List of Dynamic Components",
-            description = "Dynamic Component Definitions in format: 
<name>=<title>:<super resource type>")
-        String[] dynamic_component_names() default 
"button=Button-default:core/wcm/components/button/v1/button";
-        @AttributeDefinition(
-            name = "Additional Properties for Dynamic Components",
-            description = "Dynamic Component Additional Properties in format: 
<name>=<property name>|<property value>")
-        String[] dynamic_component_additional_properties() default "";
-        @AttributeDefinition(
-            name = "References for Dynamic Components",
-            description = "Dynamic Component Reference in format: 
<name>=<path>")
-        String[] dynamic_component_refs() default "";
-    }
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Reference
-    private ResourceResolverFactory resourceResolverFactory;
-
-    @Reference
-    DeclarativeDynamicResourceManager dynamicComponentResourceManager;
-
-    // Make sure that the Service User Mapping is available before obtaining 
the Service Resource Resolver
-    @Reference(policyOption= ReferencePolicyOption.GREEDY, target="(" + 
ServiceUserMapped.SUBSERVICENAME + EQUALS + DYNAMIC_COMPONENTS_SERVICE_USER + 
")")
-    private ServiceUserMapped serviceUserMapped;
-
-    private BundleContext bundleContext;
-    private String rootPath;
-    private String targetRootPath;
-
-    @Activate
-    private void activate(BundleContext bundleContext, Configuration 
configuration) {
-        log.info("Activate Started, bundle context: '{}'", bundleContext);
-        this.bundleContext = bundleContext;
-        rootPath = configuration.dynamic_component_root_path();
-        targetRootPath = configuration.dynamic_component_target_path();
-        final String group = configuration.dynamic_component_group();
-        final String primaryType = 
configuration.dynamic_component_primary_type();
-        try (ResourceResolver resourceResolver = 
resourceResolverFactory.getServiceResourceResolver(
-            new HashMap<String, Object>() {{ 
put(ResourceResolverFactory.SUBSERVICE, DYNAMIC_COMPONENTS_SERVICE_USER); }}
-        )) {
-            Resource root = resourceResolver.getResource(rootPath);
-            if(root == null) {
-                throw new IllegalArgumentException("Root Path: '" + rootPath + 
"' does not exist");
-            }
-            Resource target = root.getChild(DYNAMIC_COMPONENT_FOLDER_NAME);
-            log.info("Dynamic Folder looked up: '{}'", target);
-            if(target == null) {
-                target = resourceResolver.create(root, 
DYNAMIC_COMPONENT_FOLDER_NAME, new HashMap<String, Object>() {{
-                        put(JCR_PRIMARY_TYPE, SLING_FOLDER);
-                    }}
-                );
-                resourceResolver.commit();
-                log.info("Dynamic Folder created: '{}'", target);
-            } else {
-                // Remove any existing children
-                Iterator<Resource> i = target.listChildren();
-                while(i.hasNext()) {
-                    Resource child = i.next();
-                    if(!child.getName().equals(REP_POLICY)) {
-                        log.info("Delete Existing Resource: '{}'", child);
-                        resourceResolver.delete(child);
-                    }
-                }
-                resourceResolver.commit();
-            }
-            Map<String, List<Property>> additionalProperties = new HashMap<>();
-            for(String additionalProperty: 
configuration.dynamic_component_additional_properties()) {
-                Property component = new Property(additionalProperty, "Dynamic 
Additional Property");
-                if(!component.isComponent()) {
-                    throw new IllegalArgumentException("Addition Properties is 
not a component: '" + additionalProperty + "'");
-                }
-                addItemToListMap(additionalProperties, component);
-            }
-            Map<String, List<Property>> dynamicRefs = new HashMap<>();
-            for(String ref: configuration.dynamic_component_refs()) {
-                Property component = new Property(ref, "Dynamic Ref");
-                if(!component.isComponent()) {
-                    throw new IllegalArgumentException("Dynamic Ref is not a 
component: '" + ref + "'");
-                }
-                addItemToListMap(dynamicRefs, component);
-            }
-            log.info("Dynamic Refs: '{}'", dynamicRefs);
-            for (String dynamicComponentName : 
configuration.dynamic_component_names()) {
-                final Property dynamicComponent = new 
Property(dynamicComponentName, "Dynamic Component");
-                if(!dynamicComponent.isComponent()) {
-                    throw new IllegalArgumentException("Dynamic Configuration 
Name is invalid (split on = does not yield 2 tokens): " + dynamicComponentName);
-                }
-                Map<String, Object> props = new HashMap<String, Object>() {{
-                    put(COMPONENT_GROUP, group);
-                    put(JCR_PRIMARY_TYPE, primaryType);
-                    put(JCR_TITLE, dynamicComponent.getName());
-                    put(SLING_RESOURCE_SUPER_TYPE_PROPERTY, 
dynamicComponent.getValue());
-                }};
-                List<Property> propertyList = 
additionalProperties.get(dynamicComponent.getComponent());
-                log.info("Component: '{}', property list: '{}'", 
dynamicComponent.getComponent(), propertyList);
-                if(propertyList != null) {
-                    for (Property property : propertyList) {
-                        if(property.isSingle()) {
-                            props.put(property.getName(), property.getValue());
-                        } else {
-                            log.info("Add Property as Multi-Value: '{}'", 
property.getValues());
-                            props.put(property.getName(), 
property.getValues().toArray());
-                        }
-                    }
-                }
-                log.info("Props for to be created Node: '{}'", props);
-                Resource newTarget = resourceResolver.create(target, 
dynamicComponent.getComponent(), props);
-                log.info("Newly Created Target: '{}'", newTarget);
-                // Add Dynamic Refs
-                List<Property> refs = 
dynamicRefs.get(dynamicComponent.getComponent());
-                if(refs != null) {
-                    for (final Property ref : refs) {
-                        Map<String, Object> refProps = new HashMap<String, 
Object>() {{
-                            put(JCR_PRIMARY_TYPE, NT_UNSTRUCTURED);
-                            put(JCR_TITLE, ref.getName());
-                            put(REFERENCE_PROPERTY_NAME, ref.getValue());
-                        }};
-                        Resource newRef = resourceResolver.create(
-                            newTarget, ref.getName(), refProps
-                        );
-                    }
-                }
-            }
-            resourceResolver.commit();
-            Resource componentResource = 
resourceResolver.getResource(targetRootPath);
-            log.info("Target Root Path: '{}', resource: '{}'", targetRootPath, 
componentResource);
-            if(componentResource == null) {
-                Session session = resourceResolver.adaptTo(Session.class);
-                if (session != null) {
-                    final int eventTypes = Event.NODE_ADDED;
-                    final boolean isDeep = false;
-                    final boolean noLocal = true;
-                    
session.getWorkspace().getObservationManager().addEventListener(
-                        this, eventTypes, targetRootPath,
-                        isDeep, null, null, noLocal
-                    );
-                } else {
-                    log.warn("Resource Resolver could not be adapted to 
Session");
-                }
-            } else {
-                targetAvailable();
-            }
-        } catch (LoginException e) {
-            log.error("2. Cannot Access Resource Resolver", e);
-        } catch (PersistenceException e) {
-            log.error("Failed to create Dynamic Component", e);
-        } catch (UnsupportedRepositoryOperationException e) {
-            log.error("Could not register Event Listener", e);
-        } catch (RepositoryException e) {
-            log.error("Could not get Observation Manager to register Event 
Listener", e);
-        }
-    }
-
-    @Override
-    public void onEvent(EventIterator events) {
-        targetAvailable();
-    }
-
-    private void targetAvailable() {
-        log.info("Target Available Called");
-        try (ResourceResolver resourceResolver = 
resourceResolverFactory.getServiceResourceResolver(
-            new HashMap<String, Object>() {{ 
put(ResourceResolverFactory.SUBSERVICE, DYNAMIC_COMPONENTS_SERVICE_USER); }}
-        )) {
-            Resource root = resourceResolver.getResource(rootPath);
-            if (root == null) {
-                throw new IllegalArgumentException("Root Path: '" + rootPath + 
"' does not exist");
-            }
-            Resource target = root.getChild(DYNAMIC_COMPONENT_FOLDER_NAME);
-            log.info("Update the Dynamic Component Resource Manager with 
Provider Path: '{}'", target);
-            dynamicComponentResourceManager.update(target.getPath());
-            log.info("Update the Dynamic Component Resource Manager done");
-
-            // Now test the setup
-            Resource button1 = resourceResolver.getResource(targetRootPath + 
"/" + "button1");
-            log.info("Dynamic Button 1: '{}'", button1);
-            Resource container1 = resourceResolver.getResource(targetRootPath 
+ "/" + "container1");
-            log.info("Dynamic Container 1: '{}'", container1);
-            if(container1 != null) {
-                Iterator<Resource> i = 
resourceResolver.listChildren(container1.getParent());
-                int index = 0;
-                while (i.hasNext()) {
-                    log.info("{}. Entry: '{}'", index++, i.next());
-                }
-            }
-        } catch (LoginException e) {
-            log.error("2. Cannot Access Resource Resolver", e);
-        }
-    }
-
-    private void addItemToListMap(Map<String, List<Property>> target, Property 
value) {
-        String componentName = value.getComponent();
-        List<Property> propertyList = target.get(componentName);
-        if(propertyList == null) {
-            propertyList = new ArrayList<>();
-            target.put(componentName, propertyList);
-        }
-        propertyList.add(value);
-    }
-
-    private static class Property {
-        private String component;
-        private String name;
-        private List<String> values = new ArrayList<>();
-
-        public Property(String line, String messageTitle) {
-            String[] split = line.split(EQUALS);
-            if(split.length != 2) {
-                throw new IllegalArgumentException(messageTitle + " is invalid 
(split on '" + EQUALS + "' does not yield 2 tokens): " + line);
-            }
-            String tempName = split[0];
-            String tempValue = split[1];
-            int index = tempValue.indexOf(VERTICAL_LINE);
-            if( index > 0 && index < tempValue.length() - 1) {
-                String[] splitTemp = tempValue.split("\\" + VERTICAL_LINE);
-                this.component = tempName;
-                this.name = splitTemp[0];
-                tempValue = splitTemp[1];
-                if(tempValue.charAt(0) == OPENING_MULTIPLE && 
tempValue.charAt(tempValue.length() - 1) == CLOSING_MULTIPLE) {
-                    tempValue = tempValue.substring(1, tempValue.length() - 1);
-                    splitTemp = tempValue.split(MULTI_SEPARATOR);
-                    values.addAll(Arrays.asList(splitTemp));
-                } else {
-                    values.add(tempValue);
-                }
-            } else {
-                this.name = tempName;
-                if(tempValue.charAt(0) == OPENING_MULTIPLE && 
tempValue.charAt(tempValue.length() - 1) == CLOSING_MULTIPLE) {
-                    tempValue = tempValue.substring(1, tempValue.length() - 1);
-                    String[] splitTemp = tempValue.split(MULTI_SEPARATOR);
-                    values.addAll(Arrays.asList(splitTemp));
-                } else {
-                    values.add(tempValue);
-                }
-            }
-        }
-
-        public boolean isComponent() { return component != null; }
-        public boolean isEmpty() { return values.isEmpty(); }
-        public boolean isSingle() { return values.size() == 1; }
-
-        public String getComponent() {
-            return component;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getValue() {
-            return values.isEmpty() ? null : values.get(0);
-        }
-
-        public List<String> getValues() {
-            return new ArrayList<>(values);
-        }
-
-        @Override
-        public String toString() {
-            return "Property{" +
-                "component-name='" + component + '\'' +
-                ", name='" + name + '\'' +
-                ", values=" + values +
-                '}';
-        }
-    }
-}
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/apps/ddr/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddr.config
 
b/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/apps/ddr/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddr.config
index 95066c1..39a45b1 100644
--- 
a/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/apps/ddr/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddr.config
+++ 
b/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/apps/ddr/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddr.config
@@ -15,7 +15,6 @@
 #
 scripts=[\
 "
-
 # Create the Service User needed for Declarative Dynamic Resources
 
     create service user ddr-serviceuser with path /home/users/system/dynamic
@@ -25,7 +24,6 @@ scripts=[\
     set ACL for ddr-serviceuser
         allow jcr:read on /
     end
-
 "\
 ]
 
diff --git 
a/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/nodetypes/ddr.cnd 
b/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/nodetypes/ddr.cnd
new file mode 100644
index 0000000..7d151d5
--- /dev/null
+++ 
b/org.apache.sling.ddr/core/src/main/resources/SLING-CONTENT/nodetypes/ddr.cnd
@@ -0,0 +1,23 @@
+//
+//  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.
+//
+
+<slingddr='http://sling.apache.org/jcr/ddr/1.0'>
+
+[slingddr:Folder] > sling:Folder
+  - slingddr:target (string)
diff --git a/org.apache.sling.ddr/sample/Readme.md 
b/org.apache.sling.ddr/sample/Readme.md
new file mode 100644
index 0000000..fb66989
--- /dev/null
+++ b/org.apache.sling.ddr/sample/Readme.md
@@ -0,0 +1,37 @@
+# Declarative Dynamic Resource Sample
+
+This is a sample project to showcase the use of DDRs in Sling. It requires a 
Sling 12
+instance to be installed on.
+
+## Design
+
+These are the components of the Sample:
+
+* **/apps/ddr-dynamic/components**: the DDR target folder which is empty
+* **/apps/ddr-sample/config**: runmode configuration for this Sample
+* **/apps/ddr-static**: the base component **button** and **text**
+* **/conf/ddr-sample/settings/dynamic**: the source DDR components that points 
to the DDR target of **/apps/ddr-dynamic/components and contains an updated 
version of Button and Text
+* **/content/ddr-sample**: content that show the usage of enhanced Button and 
Text
+
+## What Happens
+
+After the DDR Sample is installed the DDR Manager will discover that 
*/conf/ddr-sample/settings/dynamic*
+is a DDR source (by its primary type) and then read out the DDR target path. 
Then it will register that
+folder as DDR Source / Target pair with the DDR Provider. Whenever now a user 
requests a resource from that
+folder the DDR Provider will look it up and if:
+
+* it finds an existing resource in that folder -> return that resource
+* it finds a resource in the DDR source with that name -> return a Synthetic 
Resource that contains the properties of the DDR source with the same name
+
+## Review
+
+After the installation open Sling in a browser and then go to **composum** 
browser.
+Here go to **/apps/ddr-dynamic** and you will find two child nodes **button1** 
and **text1**.
+These resources are fully dynamic mean that they would go away if the DDR core 
is disabled.
+Try this by going to the System Console **Bundles** and stop the 
**org.apache.sling.ddr.core** bundle.
+Refershing the **/apps/ddr-dynamic** folder in composum will not display any 
child resources. Restart
+the bundle now again and make sure the child resources are there again.
+Now we want to see these components but open the content on 
**/ddr-sample/button.html**. This will
+show *Hello Button: * followed by the path of the resource.
+
+Andreas Schaefer: 3/27/2021
\ No newline at end of file
diff --git a/org.apache.sling.ddr/sample/pom.xml 
b/org.apache.sling.ddr/sample/pom.xml
index 3999060..4578bb1 100644
--- a/org.apache.sling.ddr/sample/pom.xml
+++ b/org.apache.sling.ddr/sample/pom.xml
@@ -57,6 +57,7 @@
                             
SLING-CONTENT/apps/ddr-sample;path:=/apps/ddr-sample;overwrite:=true;overwriteProperties:=true,
                             
SLING-CONTENT/apps/ddr-dynamic;path:=/apps/ddr-dynamic;overwrite:=true;overwriteProperties:=true,
                             
SLING-CONTENT/apps/ddr-static;path:=/apps/ddr-static;overwrite:=true;overwriteProperties:=true,
+                            
SLING-CONTENT/conf/ddr-sample;path:=/conf/ddr-sample;overwrite:=true;overwriteProperties:=true,
                             
SLING-CONTENT/content/ddr-sample;path:=/content/ddr-sample;overwrite:=true;overwriteProperties:=true
                         </Sling-Initial-Content>
                     </instructions>
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-dynamic/components.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-dynamic/components.json
index 3c7b6bf..41c83f6 100644
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-dynamic/components.json
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-dynamic/components.json
@@ -1,5 +1,5 @@
 {
+  "jcr:description": "Root Folder of the Declarative Dynamic Resources 
(Target)",
   "jcr:primaryType": "sling:Folder",
-  "jcr:title": "Declarative Dynamic Resource Folder",
-  "jcr:description": "Root Folder of the Declarative Dynamic Resources 
(Target)"
+  "jcr:title": "Declarative Dynamic Resource Folder"
 }
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample.json
index 152abde..4cee809 100644
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample.json
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample.json
@@ -1,5 +1,5 @@
 {
   "jcr:primaryType": "sling:Folder",
-  "jcr:title": "Declarative Dynamic Resource Root",
-  "jcr:description": "Declarative Dynamic Resource Apps Root folder"
+  "jcr:title": "Declarative Dynamic Sample Resource Root",
+  "jcr:description": "Declarative Dynamic Sample Resource Apps Root folder"
 }
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.DeclarativeDynamicResourceManagerService-ddrsample.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.DeclarativeDynamicResourceManagerService-ddrsample.json
deleted file mode 100644
index 5d0b6c2..0000000
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.DeclarativeDynamicResourceManagerService-ddrsample.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "jcr:primaryType": "sling:OsgiConfig",
-  "dynamic.component.target.path": "/apps/ddr-dynamic/components"
-}
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.setup.DeclarativeDynamicResourceSetupService-ddrsample.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.setup.DeclarativeDynamicResourceSetupService-ddrsample.json
deleted file mode 100644
index 5dab22e..0000000
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.ddr.core.setup.DeclarativeDynamicResourceSetupService-ddrsample.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "jcr:primaryType": "sling:OsgiConfig",
-  "dynamic.component.root.path": "/conf/ddr-sample/settings",
-  "dynamic.component.target.path": "/apps/ddr-dynamic/components",
-  "dynamic.component.group": "Dynamic.Content",
-  "dynamic.component.primary.type": "sling:Folder",
-  "dynamic.component.names": [
-    "button1=Button-1|ddr-static/button",
-    "container1=Container-1|ddr-static/container"
-  ],
-  "dynamic.component.additional.properties": [
-    "button1=jcr:description|Dynamic Test Button",
-    
"container1=cq:styleElements|{div;section;article;main;aside;header;footer}"
-  ],
-  "dynamic.component.refs": []
-}
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddrsample.config
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddrsample.config
deleted file mode 100644
index 8f79a87..0000000
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-sample/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-ddrsample.config
+++ /dev/null
@@ -1,38 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with this
-# work for additional information regarding copyright ownership. The ASF
-# licenses this file to You under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-#
-scripts=[\
-"
-# This Repoinit Script is here to make sure that during an upgrade the 
necessary users
-# and permissions are available
-
-# Create the Folders for Dynamic Components
-
-    create path /conf(sling:Folder)
-    create path /conf/ddr-sample(sling:Folder)
-    create path /conf/ddr-sample/settings(sling:Folder)
-    create path /conf/ddr-sample/settings/dynamic(sling:Folder)
-
-    create service user ddr-serviceuser with path /home/users/system/dynamic
-
-# Set Permission for Dynamic Components Service User
-
-    set ACL for ddr-serviceuser
-        allow jcr:all on /conf/ddr-sample/settings/dynamic
-    end
-"\
-]
-
-references=[]
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/container.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/text.json
similarity index 100%
rename from 
org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/container.json
rename to 
org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/text.json
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/container/container.html
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/text/text.html
similarity index 97%
rename from 
org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/container/container.html
rename to 
org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/text/text.html
index 24f58ce..de65ea5 100644
--- 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/container/container.html
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/apps/ddr-static/text/text.html
@@ -16,4 +16,4 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<p>Container</p>
\ No newline at end of file
+<p>Hello Text</p>
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample.json
new file mode 100644
index 0000000..7e04c89
--- /dev/null
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample.json
@@ -0,0 +1,4 @@
+{
+  "jcr:primaryType": "sling:Folder",
+  "jcr:title": "DDR Sample Configuration Folder"
+}
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample/settings.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample/settings.json
new file mode 100644
index 0000000..d79a772
--- /dev/null
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/conf/ddr-sample/settings.json
@@ -0,0 +1,23 @@
+{
+  "jcr:primaryType": "sling:Folder",
+  "dynamic": {
+    "jcr:mixinTypes": [
+      "rep:AccessControllable"
+    ],
+    "jcr:primaryType": "slingddr:Folder",
+    "slingddr:target": "/apps/ddr-dynamic/components",
+    "button1": {
+      "componentGroup": "Dynamic.Content",
+      "jcr:description": "Dynamic Test Button",
+      "jcr:primaryType": "sling:Folder",
+      "jcr:title": "Button-1",
+      "sling:resourceSuperType": "ddr-static/button"
+    },
+    "text1": {
+      "componentGroup": "Dynamic.Content",
+      "jcr:primaryType": "sling:Folder",
+      "jcr:title": "Text-1",
+      "sling:resourceSuperType": "ddr-static/text"
+    }
+  }
+}
\ No newline at end of file
diff --git 
a/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/content/ddr-sample/text.json
 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/content/ddr-sample/text.json
new file mode 100644
index 0000000..8bd5484
--- /dev/null
+++ 
b/org.apache.sling.ddr/sample/src/main/resources/SLING-CONTENT/content/ddr-sample/text.json
@@ -0,0 +1,4 @@
+{
+  "jcr:primaryType": "sling:Folder",
+  "sling:resourceSuperType": "ddr-dynamic/components/text1"
+}

Reply via email to