You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cs...@apache.org on 2019/09/11 13:15:49 UTC

[aries-jax-rs-whiteboard] 08/10: [ARIES-1928] Track extensions per application

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

csierra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-jax-rs-whiteboard.git

commit b2149355f401c4f6bc4f774cc6ed1a3e3442fa48
Author: Carlos Sierra <cs...@apache.org>
AuthorDate: Tue Sep 10 19:07:50 2019 +0200

    [ARIES-1928] Track extensions per application
    
    Before there was a global registry for extensions. The presence or
    absence of an extension does not mean anything until it is initialized
    inside an application. An application depending on extensions should not
    be deployed until its dependencies have been checked to work.
    
    Also, instead of registering the CxfJaxrsServiceRegistrator, we now
    register the application in a internal registry, which simplifies the
    extension attaching.
---
 .../internal/ApplicationExtensionRegistry.java     | 183 -----------------
 .../internal/AriesJaxrsServiceRuntime.java         |   8 +-
 .../rs/whiteboard/internal/FilteredPublisher.java  |  33 ++--
 .../aries/jax/rs/whiteboard/internal/Registry.java | 134 +++++++++++++
 ...java => ServiceReferenceFilteredPublisher.java} |   4 +-
 ...Registry.java => ServiceReferenceRegistry.java} |  47 +++--
 .../jax/rs/whiteboard/internal/Whiteboard.java     | 219 +++++++++------------
 .../internal/cxf/CxfJaxrsServiceRegistrator.java   |  37 +++-
 8 files changed, 297 insertions(+), 368 deletions(-)

diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ApplicationExtensionRegistry.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ApplicationExtensionRegistry.java
deleted file mode 100644
index e8322e1..0000000
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ApplicationExtensionRegistry.java
+++ /dev/null
@@ -1,183 +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.aries.jax.rs.whiteboard.internal;
-
-import org.apache.aries.component.dsl.CachingServiceReference;
-import org.apache.aries.component.dsl.OSGi;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-
-import static org.apache.aries.component.dsl.OSGi.fromOsgiRunnable;
-
-public class ApplicationExtensionRegistry implements AutoCloseable {
-
-    public ApplicationExtensionRegistry() {
-        _applicationPublishers = new HashMap<>();
-        _applicationRegisteredExtensions = new HashMap<>();
-    }
-
-    public void close() {
-        _applicationPublishers.forEach(
-            (__, aeps) -> aeps.forEach(FilteredPublisher::close)
-        );
-    }
-
-    public OSGi<CachingServiceReference<?>> waitForApplicationExtension(
-            String applicationName, String extensionFilter) {
-
-        Filter filter;
-
-        try {
-            filter = FrameworkUtil.createFilter(extensionFilter);
-        }
-        catch (InvalidSyntaxException e) {
-            throw new RuntimeException();
-        }
-
-        return fromOsgiRunnable((bc, p) -> {
-            synchronized (ApplicationExtensionRegistry.this) {
-                FilteredPublisher aep =
-                    new FilteredPublisher(p, filter);
-
-                _applicationPublishers.compute(
-                    applicationName,
-                    (__, set) -> {
-                        if (set == null) {
-                            set = new HashSet<>();
-                        }
-
-                        set.add(aep);
-
-                        return set;
-                    });
-
-                Collection<CachingServiceReference<?>> extensions =
-                    _applicationRegisteredExtensions.get(applicationName);
-
-                if (extensions != null) {
-                    for (CachingServiceReference<?> extension :
-                        new HashSet<>(extensions)) {
-
-                        aep.publishIfMatched(extension);
-                    }
-                }
-
-                return () -> {
-                    synchronized (ApplicationExtensionRegistry.this) {
-                        Collection<FilteredPublisher> set =
-                            _applicationPublishers.get(applicationName);
-
-                        set.remove(aep);
-
-                        if (extensions != null) {
-                            for (CachingServiceReference<?> extension :
-                                new HashSet<>(extensions)) {
-
-                                aep.retractIfMatched(extension);
-                            }
-                        }
-                    }
-                };
-            }
-
-        });
-    }
-
-    public void registerExtensionInApplication(
-        String applicationName, CachingServiceReference<?> extension) {
-
-        synchronized (ApplicationExtensionRegistry.this) {
-            Collection<FilteredPublisher> publishers =
-                _applicationPublishers.get(applicationName);
-
-            if (publishers != null) {
-                for (FilteredPublisher publisher : new HashSet<>(publishers)) {
-                    publisher.publishIfMatched(extension);
-                }
-            }
-
-            _applicationRegisteredExtensions.compute(
-                applicationName,
-                (__, set) -> {
-                    if (set == null) {
-                        set = new HashSet<>();
-                    }
-
-                    set.add(extension);
-
-                    return set;
-                }
-            );
-        }
-    }
-
-    public void unregisterExtensionInApplication(
-        String applicationName, CachingServiceReference<?> extension) {
-
-        synchronized (ApplicationExtensionRegistry.this) {
-            Collection<FilteredPublisher> publishers =
-                _applicationPublishers.get(applicationName);
-
-            if (publishers != null) {
-                for (FilteredPublisher publisher : new HashSet<>(publishers)) {
-                    publisher.retractIfMatched(extension);
-                }
-            }
-
-            _applicationRegisteredExtensions.compute(
-                applicationName,
-                (__, set) -> {
-                    if (set == null) {
-                        set = new HashSet<>();
-                    }
-
-                    set.remove(extension);
-
-                    return set;
-                }
-            );
-        }
-    }
-
-    public void unregisterApplication(String applicationName) {
-        synchronized (ApplicationExtensionRegistry.this) {
-            _applicationRegisteredExtensions.remove(applicationName);
-
-            Collection<FilteredPublisher> publishers =
-                _applicationPublishers.remove(applicationName);
-
-            if (publishers != null) {
-                for (FilteredPublisher publisher : new HashSet<>(publishers)) {
-                    publisher.close();
-                }
-            }
-        }
-    }
-
-    private final HashMap
-        <String, Collection<FilteredPublisher>>
-            _applicationPublishers;
-    private final HashMap<String, Collection<CachingServiceReference<?>>>
-        _applicationRegisteredExtensions;
-
-}
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxrsServiceRuntime.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxrsServiceRuntime.java
index ff2cb20..b24f026 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxrsServiceRuntime.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxrsServiceRuntime.java
@@ -207,11 +207,11 @@ public class AriesJaxrsServiceRuntime implements JaxrsServiceRuntime {
     }
 
     public void addDependentExtensionInApplication(
-        CachingServiceReference applicationReference,
+        Map<String, ?> applicationReference,
         CachingServiceReference<?> cachingServiceReference) {
 
         _dependentExtensions.compute(
-            getServiceName(applicationReference::getProperty),
+            getServiceName(applicationReference::get),
             merger(cachingServiceReference));
     }
 
@@ -584,11 +584,11 @@ public class AriesJaxrsServiceRuntime implements JaxrsServiceRuntime {
     }
 
     public void removeDependentExtensionFromApplication(
-        CachingServiceReference applicationReference,
+        Map<String, ?> properties,
         CachingServiceReference<?> cachingServiceReference) {
 
         _dependentExtensions.compute(
-            getServiceName(applicationReference::getProperty),
+            getServiceName(properties::get),
             remover(cachingServiceReference));
     }
 
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java
index 9458d3e..6f19dec 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java
@@ -17,21 +17,17 @@
 
 package org.apache.aries.jax.rs.whiteboard.internal;
 
-import org.apache.aries.component.dsl.CachingServiceReference;
 import org.apache.aries.component.dsl.OSGiResult;
 import org.apache.aries.component.dsl.Publisher;
 import org.osgi.framework.Filter;
 
-import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class FilteredPublisher implements AutoCloseable {
-
-    public FilteredPublisher(
-        Publisher<? super CachingServiceReference<?>> publisher,
-        Filter filter) {
+public class FilteredPublisher<T> implements AutoCloseable {
 
+    public FilteredPublisher(Publisher<? super T> publisher, Filter filter) {
         _publisher = publisher;
         _filter = filter;
     }
@@ -44,15 +40,15 @@ public class FilteredPublisher implements AutoCloseable {
         }
     }
 
-    public void publishIfMatched(CachingServiceReference<?> serviceReference) {
+    public void publishIfMatched(T t, Map<String, ?> properties) {
         if (_closed.get()) {
             return;
         }
 
-        if (_filter.match(serviceReference.getServiceReference())) {
-            OSGiResult result = _publisher.publish(serviceReference);
+        if (_filter.matches(properties)) {
+            OSGiResult result = _publisher.publish(t);
 
-            OSGiResult old = _results.put(serviceReference, result);
+            OSGiResult old = _results.put(t, result);
 
             if (old != null) {
                 old.close();
@@ -64,24 +60,21 @@ public class FilteredPublisher implements AutoCloseable {
         }
     }
 
-    public void retractIfMatched(CachingServiceReference<?> serviceReference) {
+    public void retract(T t) {
         if (_closed.get()) {
             return;
         }
 
-        if (_filter.match(serviceReference.getServiceReference())) {
-            OSGiResult result = _results.remove(serviceReference);
+        OSGiResult result = _results.remove(t);
 
-            if (result != null) {
-                result.close();
-            }
+        if (result != null) {
+            result.close();
         }
     }
 
-    private Publisher<? super CachingServiceReference<?>> _publisher;
+    private Publisher<? super T> _publisher;
     private Filter _filter;
     private AtomicBoolean _closed = new AtomicBoolean(false);
-    private Map<CachingServiceReference<?>, OSGiResult> _results =
-        new HashMap<>();
+    private IdentityHashMap<T, OSGiResult> _results = new IdentityHashMap<>();
 
 }
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Registry.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Registry.java
new file mode 100644
index 0000000..f2c1cba
--- /dev/null
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Registry.java
@@ -0,0 +1,134 @@
+/*
+ * 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.aries.jax.rs.whiteboard.internal;
+
+import org.apache.aries.component.dsl.OSGi;
+import org.apache.aries.component.dsl.OSGiResult;
+import org.apache.aries.component.dsl.internal.ConcurrentDoublyLinkedList;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+
+import static org.apache.aries.component.dsl.OSGi.fromOsgiRunnable;
+
+public class Registry<T> implements AutoCloseable {
+
+    public Registry() {
+        _publishers = new HashSet<>();
+        _servicesWithPropertiesList = new ConcurrentDoublyLinkedList<>();
+    }
+
+    @Override
+    public void close() {
+        for (FilteredPublisher publisher : new HashSet<>(_publishers)) {
+            publisher.close();
+        }
+    }
+
+    public OSGi<T> waitForService(String filterString) {
+        Filter filter;
+
+        try {
+            filter = FrameworkUtil.createFilter(filterString);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new RuntimeException();
+        }
+
+        return fromOsgiRunnable((bc, p) -> {
+            synchronized (Registry.this) {
+                FilteredPublisher<T> ep = new FilteredPublisher<>(p, filter);
+
+                _publishers.add(ep);
+
+                for (ServiceWithProperties<T> serviceWithProperties :
+                    new ArrayList<>(_servicesWithPropertiesList)) {
+
+                    ep.publishIfMatched(
+                        serviceWithProperties.service,
+                        serviceWithProperties.properties);
+                }
+
+                return () -> {
+                    synchronized (Registry.this) {
+                        _publishers.remove(ep);
+
+                        for (ServiceWithProperties<T> serviceWithProperties :
+                            new ArrayList<>(_servicesWithPropertiesList)) {
+
+                            ep.retract(serviceWithProperties.service);
+                        }
+                    }
+                };
+            }
+
+        });
+    }
+
+    public OSGi<T> registerService(T service, Map<String, ?> properties) {
+        return (bc, p) -> {
+            synchronized (Registry.this) {
+                ConcurrentDoublyLinkedList.Node node =
+                    _servicesWithPropertiesList.addLast(
+                        new ServiceWithProperties<>(service, properties));
+
+                OSGiResult result = p.publish(service);
+
+                for (FilteredPublisher<T> publisher :
+                    new HashSet<>(_publishers)) {
+
+                    publisher.publishIfMatched(service, properties);
+                }
+
+                return () -> {
+                    synchronized (Registry.this) {
+                        for (FilteredPublisher<T> publisher :
+                            new HashSet<>(_publishers)) {
+
+                            publisher.retract(service);
+                        }
+
+                        result.close();
+                        node.remove();
+                    }
+                };
+            }
+        };
+    }
+
+
+    private final HashSet<FilteredPublisher<T>> _publishers;
+    private final ConcurrentDoublyLinkedList<ServiceWithProperties<T>>
+        _servicesWithPropertiesList;
+
+    private static class ServiceWithProperties<T> {
+
+        T service;
+        Map<String, ?> properties;
+
+        ServiceWithProperties(T service, Map<String, ?> properties) {
+            this.service = service;
+            this.properties = properties;
+        }
+    }
+
+}
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceFilteredPublisher.java
similarity index 95%
copy from jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java
copy to jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceFilteredPublisher.java
index 9458d3e..db8513a 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/FilteredPublisher.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceFilteredPublisher.java
@@ -26,9 +26,9 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class FilteredPublisher implements AutoCloseable {
+public class ServiceReferenceFilteredPublisher implements AutoCloseable {
 
-    public FilteredPublisher(
+    public ServiceReferenceFilteredPublisher(
         Publisher<? super CachingServiceReference<?>> publisher,
         Filter filter) {
 
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ExtensionRegistry.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceRegistry.java
similarity index 65%
rename from jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ExtensionRegistry.java
rename to jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceRegistry.java
index e67ce23..32b37e8 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ExtensionRegistry.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/ServiceReferenceRegistry.java
@@ -19,6 +19,7 @@ package org.apache.aries.jax.rs.whiteboard.internal;
 
 import org.apache.aries.component.dsl.CachingServiceReference;
 import org.apache.aries.component.dsl.OSGi;
+import org.apache.aries.component.dsl.OSGiResult;
 import org.osgi.framework.Filter;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -27,37 +28,36 @@ import java.util.HashSet;
 
 import static org.apache.aries.component.dsl.OSGi.fromOsgiRunnable;
 
-public class ExtensionRegistry implements AutoCloseable {
+public class ServiceReferenceRegistry implements AutoCloseable {
 
-    public ExtensionRegistry() {
+    public ServiceReferenceRegistry() {
         _extensionPublishers = new HashSet<>();
         _registeredExtensions = new HashSet<>();
     }
 
     @Override
     public void close() {
-        for (FilteredPublisher extensionPublisher :
+        for (ServiceReferenceFilteredPublisher extensionPublisher :
             new HashSet<>(_extensionPublishers)) {
 
             extensionPublisher.close();
         }
     }
 
-    public OSGi<CachingServiceReference<?>> waitForExtension(
-        String extensionFilter) {
-
+    public OSGi<CachingServiceReference<?>> waitFor(String filterString) {
         Filter filter;
 
         try {
-            filter = FrameworkUtil.createFilter(extensionFilter);
+            filter = FrameworkUtil.createFilter(filterString);
         }
         catch (InvalidSyntaxException e) {
             throw new RuntimeException();
         }
 
         return fromOsgiRunnable((bc, p) -> {
-            synchronized (ExtensionRegistry.this) {
-                FilteredPublisher ep = new FilteredPublisher(p, filter);
+            synchronized (ServiceReferenceRegistry.this) {
+                ServiceReferenceFilteredPublisher ep =
+                    new ServiceReferenceFilteredPublisher(p, filter);
 
                 _extensionPublishers.add(ep);
 
@@ -68,7 +68,7 @@ public class ExtensionRegistry implements AutoCloseable {
                 }
 
                 return () -> {
-                    synchronized (ExtensionRegistry.this) {
+                    synchronized (ServiceReferenceRegistry.this) {
                         _extensionPublishers.remove(ep);
 
                         for (CachingServiceReference<?> extension :
@@ -83,35 +83,32 @@ public class ExtensionRegistry implements AutoCloseable {
         });
     }
 
-    public void registerExtension(
-        CachingServiceReference<?> extension) {
-
-        synchronized (ExtensionRegistry.this) {
-            for (FilteredPublisher publisher :
+    public void register(CachingServiceReference<?> serviceReference) {
+        synchronized (ServiceReferenceRegistry.this) {
+            for (ServiceReferenceFilteredPublisher publisher :
                 new HashSet<>(_extensionPublishers)) {
 
-                publisher.publishIfMatched(extension);
+                publisher.publishIfMatched(serviceReference);
             }
 
-            _registeredExtensions.add(extension);
+            _registeredExtensions.add(serviceReference);
         }
     }
 
-    public void unregisterExtension(
-        CachingServiceReference<?> extension) {
-
-        synchronized (ExtensionRegistry.this) {
-            for (FilteredPublisher publisher :
+    public void unregister(CachingServiceReference<?> serviceReference) {
+        synchronized (ServiceReferenceRegistry.this) {
+            for (ServiceReferenceFilteredPublisher publisher :
                 new HashSet<>(_extensionPublishers)) {
 
-                publisher.retractIfMatched(extension);
+                publisher.retractIfMatched(serviceReference);
             }
 
-            _registeredExtensions.remove(extension);
+            _registeredExtensions.remove(serviceReference);
         }
     }
 
-    private final HashSet<FilteredPublisher> _extensionPublishers;
+    private final HashSet<ServiceReferenceFilteredPublisher>
+        _extensionPublishers;
     private final HashSet<CachingServiceReference<?>> _registeredExtensions;
 
 }
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
index d2ec77d..188513e 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
@@ -83,7 +83,6 @@ import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.getString;
 import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.highestPer;
 import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.mergePropertyMaps;
 import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.onlyGettables;
-import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.service;
 import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.updateProperty;
 import static org.apache.aries.component.dsl.OSGi.NOOP;
 import static org.apache.aries.component.dsl.OSGi.all;
@@ -143,8 +142,8 @@ public class Whiteboard {
     private static final Logger _log = LoggerFactory.getLogger(
         Whiteboard.class);
     private final String _applicationBasePrefix;
-    private final ApplicationExtensionRegistry _applicationExtensionRegistry;
-    private final ExtensionRegistry _extensionRegistry;
+    private final Registry<CxfJaxrsServiceRegistrator> _applicationRegistry =
+        new Registry<>();
 
     private final AriesJaxrsServiceRuntime _runtime;
     private final Map<String, ?> _configurationMap;
@@ -152,7 +151,7 @@ public class Whiteboard {
     private volatile ServiceRegistrationChangeCounter _counter;
     private volatile ServiceReference<JaxrsServiceRuntime> _runtimeReference;
     private final OSGi<Void> _program;
-    private final List<Object> _endpoints;
+    private final List<Object> _endpoints = new ArrayList<>();
     private volatile ServiceRegistration<JaxrsServiceRuntime>
         _runtimeRegistration;
     private OSGiResult _osgiResult;
@@ -160,10 +159,7 @@ public class Whiteboard {
     private Whiteboard(Dictionary<String, ?> configuration) {
         _runtime = new AriesJaxrsServiceRuntime(this);
         _configurationMap = Maps.from(configuration);
-        _endpoints = new ArrayList<>();
 
-        _applicationExtensionRegistry = new ApplicationExtensionRegistry();
-        _extensionRegistry = new ExtensionRegistry();
         _applicationBasePrefix = canonicalizeAddress(
             getString(_configurationMap.get("application.base.prefix")));
 
@@ -192,8 +188,7 @@ public class Whiteboard {
     public void stop() {
         _osgiResult.close();
         _runtimeRegistration.unregister();
-        _applicationExtensionRegistry.close();
-        _extensionRegistry.close();
+        _applicationRegistry.close();
     }
 
     public void addHttpEndpoints(List<String> endpoints) {
@@ -220,29 +215,24 @@ public class Whiteboard {
                         _runtime::removeInvalidExtension),
                     _runtime::addInvalidExtension,
                     _runtime::removeInvalidExtension).
-                effects(
-                    _extensionRegistry::registerExtension,
-                    _extensionRegistry::unregisterExtension).
                 flatMap(extensionReference ->
             chooseApplication(
                     extensionReference,
                     _runtime::addApplicationDependentExtension,
                     _runtime::removeApplicationDependentExtension).
-                flatMap(registratorReference ->
-            service(registratorReference).flatMap(registrator ->
+                flatMap(registrator ->
             waitForExtensionDependencies(
-                    extensionReference, registratorReference,
+                    extensionReference,
+                    registrator,
                     er ->
                         _runtime.addDependentExtensionInApplication(
-                            registratorReference, er),
+                            registrator.getProperties(), er),
                     er ->
                         _runtime.removeDependentExtensionFromApplication(
-                            registratorReference, er)).
+                            registrator.getProperties(), er)).
                 then(
-            safeRegisterExtension(
-                extensionReference, registratorReference::getProperty,
-                registrator)
-        ))));
+            safeRegisterExtension(extensionReference, registrator)
+        )));
     }
 
     private OSGi<?> applicationResources(
@@ -257,17 +247,14 @@ public class Whiteboard {
                     resourceReference,
                     _runtime::addApplicationDependentResource,
                     _runtime::removeApplicationDependentResource).
-                flatMap(registratorReference ->
-            service(registratorReference).flatMap(registrator ->
+                flatMap(registrator ->
             waitForExtensionDependencies(
-                    resourceReference, registratorReference,
+                    resourceReference, registrator,
                     _runtime::addDependentService,
                     _runtime::removeDependentService).
             then(
-                safeRegisterEndpoint(
-                    resourceReference, registratorReference::getProperty,
-                    registrator)
-            ))));
+                safeRegisterEndpoint(resourceReference, registrator)
+            )));
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -515,9 +502,8 @@ public class Whiteboard {
 
         return highestRankedPerPath.flatMap(application ->
             onlyGettables(
-                    waitForReadyService(
-                    waitForApplicationDependencies(
-                        just(application.getApplicationReference()))),
+                waitForReadyService(
+                    just(application.getApplicationReference())),
                 _runtime::addNotGettableApplication,
                 _runtime::removeNotGettableApplication, _log).
             recoverWith(
@@ -611,56 +597,42 @@ public class Whiteboard {
             cachingServiceReference = tuple.getCachingServiceReference();
 
         _runtime.unregisterApplicationExtensions(cachingServiceReference);
-        _applicationExtensionRegistry.unregisterApplication(
-                getServiceName(cachingServiceReference::getProperty));
     }
 
-    private OSGi<CachingServiceReference<CxfJaxrsServiceRegistrator>>
-        applicationMatching(String filter) {
+    private OSGi<CxfJaxrsServiceRegistrator> applicationMatching(
+        String filter) {
 
-        return serviceReferences(
-            CxfJaxrsServiceRegistrator.class, filter
-        ).filter(
-            this::matchesWhiteboard
-        );
+        return _applicationRegistry.waitForService(filter);
     }
 
     private OSGi<CxfJaxrsServiceRegistrator> deployApplication(
         ServiceTuple<Application> tuple,
         CachingServiceReference<ServletContextHelper> contextReference) {
 
-        Supplier<Map<String, ?>> properties = () -> {
-            CachingServiceReference<Application> serviceReference =
-                tuple.getCachingServiceReference();
+        CachingServiceReference<Application> serviceReference =
+            tuple.getCachingServiceReference();
 
-            Map<String, Object> props = getApplicationProperties(
-                serviceReference);
-
-            props.put(
-                "original.service.id",
-                serviceReference.getProperty("service.id"));
-
-            props.put(
-                "original.service.bundleid",
-                serviceReference.getProperty("service.bundleid"));
-
-            return props;
-        };
+        Map<String, Object> properties = getApplicationProperties(
+            serviceReference);
 
         return
             getCxfExtensions(tuple.getCachingServiceReference()).
                 flatMap(extensions ->
             createRegistrator(extensions, tuple, properties).
                 flatMap(registrator ->
+            waitForApplicationDependencies(
+                tuple.getCachingServiceReference(),
+                _applicationRegistry.registerService(
+                    registrator, registrator.getProperties())).
+                then(
             registerCXFServletService(
                     registrator.getBus(), properties, contextReference).
                 then(
             register(
-                    CxfJaxrsServiceRegistrator.class,
-                    () -> registrator, properties).
+                    CxfJaxrsServiceRegistrator.class, registrator, properties).
                 then(
             just(registrator)
-        ))));
+        )))));
     }
 
     public OSGi<Map<String, ServiceTuple<Object>>> getCxfExtensions(
@@ -713,12 +685,11 @@ public class Whiteboard {
 
     private OSGi<CxfJaxrsServiceRegistrator> createRegistrator(
         Map<String, ServiceTuple<Object>> extensions,
-        ServiceTuple<Application> tuple, Supplier<Map<String, ?>> props) {
+        ServiceTuple<Application> tuple, Map<String, Object> props) {
 
         return
             just(() -> new CxfJaxrsServiceRegistrator(
-                    createBus(extensions), tuple, props.get(),
-                _applicationExtensionRegistry, _runtime)).
+                    createBus(extensions), tuple, props, _runtime)).
             effects(
                 __ -> {},
                 CxfJaxrsServiceRegistrator::enable,
@@ -834,11 +805,12 @@ public class Whiteboard {
 
     private <T> OSGi<?> safeRegisterEndpoint(
         CachingServiceReference<T> serviceReference,
-        PropertyHolder registratorProperties,
         CxfJaxrsServiceRegistrator registrator) {
 
+        Map registratorProperties = registrator.getProperties();
+
         Bundle originalBundle = _bundleContext.getBundle(
-            (long)registratorProperties.get("original.service.bundleid"));
+            (long)registratorProperties.get("service.bundleid"));
 
         return
             changeContext(
@@ -871,10 +843,12 @@ public class Whiteboard {
                     Utils::getResourceProvider
                 ).effects(
                     rp -> _runtime.addApplicationEndpoint(
-                        registratorProperties, st.getCachingServiceReference(),
+                        registratorProperties::get,
+                        st.getCachingServiceReference(),
                         registrator.getBus(), st.getService().getClass()),
                     rp -> _runtime.removeApplicationEndpoint(
-                        registratorProperties, st.getCachingServiceReference())
+                        registratorProperties::get,
+                        st.getCachingServiceReference())
                 ).effects(
                     registrator::add,
                     registrator::remove
@@ -884,14 +858,14 @@ public class Whiteboard {
                         () -> "Registered endpoint " +
                             st.getCachingServiceReference().
                                 getServiceReference() + " into application " +
-                                getServiceName(registratorProperties)
+                                getServiceName(registratorProperties::get)
                     ),
                     ifDebugEnabled(
                         _log,
                         () -> "Unregistered endpoint " +
                             st.getCachingServiceReference().
                                 getServiceReference() + " from application " +
-                                getServiceName(registratorProperties)
+                                getServiceName(registratorProperties::get)
                     )
 
                 )
@@ -900,14 +874,15 @@ public class Whiteboard {
 
     private OSGi<?> safeRegisterExtension(
         CachingServiceReference<?> serviceReference,
-        PropertyHolder registratorProperties,
         CxfJaxrsServiceRegistrator registrator) {
 
+        Map properties = registrator.getProperties();
+
         Bundle originalBundle = _bundleContext.getBundle(
-            (long)registratorProperties.get("original.service.bundleid"));
+            (long)properties.get("service.bundleid"));
 
         return
-            just(() -> getServiceName(registratorProperties)).
+            just(() -> getServiceName(properties::get)).
                 flatMap(applicationName ->
             changeContext(
                 originalBundle.getBundleContext(),
@@ -941,10 +916,10 @@ public class Whiteboard {
                 registrator::removeProvider
             ).effects(
                 t -> _runtime.addApplicationExtension(
-                    registratorProperties, serviceReference,
+                    properties::get, serviceReference,
                     t.getService().getClass()),
                 __ -> _runtime.removeApplicationExtension(
-                    registratorProperties, serviceReference)
+                    properties::get, serviceReference)
             ).
             effects(
                 ifDebugEnabled(
@@ -953,7 +928,7 @@ public class Whiteboard {
                         "Registered extension " +
                             serviceReference.getServiceReference() +
                                 " into application " +
-                            getServiceName(registratorProperties)
+                            getServiceName(properties::get)
                 ),
                 ifDebugEnabled(
                     _log,
@@ -961,34 +936,30 @@ public class Whiteboard {
                         "Unregistered extension  " +
                             serviceReference.getServiceReference() +
                             " from application " +
-                            getServiceName(registratorProperties)
+                            getServiceName(properties::get)
                 )
 
             ).
             effects(
-                __ ->
-                    _applicationExtensionRegistry.
-                        registerExtensionInApplication(
-                            applicationName, serviceReference),
-                __ ->
-                    _applicationExtensionRegistry.
-                        unregisterExtensionInApplication(
-                            applicationName, serviceReference)
+                __ -> registrator.registerExtension(
+                    serviceReference),
+                __ -> registrator.unregisterExtension(
+                    serviceReference)
             ));
     }
 
 
 
-    private OSGi<CachingServiceReference<Application>>
+    private OSGi<CxfJaxrsServiceRegistrator>
         waitForApplicationDependencies(
-            OSGi<CachingServiceReference<Application>> references) {
+            CachingServiceReference<Application> applicationReference,
+            OSGi<CxfJaxrsServiceRegistrator> registrators) {
 
-        return references.flatMap(reference -> {
+        return registrators.flatMap(registrator -> {
             String[] extensionDependencies = canonicalize(
-                reference.getProperty(JAX_RS_EXTENSION_SELECT));
+                applicationReference.getProperty(JAX_RS_EXTENSION_SELECT));
 
-            OSGi<CachingServiceReference<Application>> program = just(
-                reference);
+            OSGi<CxfJaxrsServiceRegistrator> program = just(registrator);
 
             if (extensionDependencies.length == 0) {
                 return program;
@@ -998,7 +969,7 @@ public class Whiteboard {
                 if  (_log.isDebugEnabled()) {
                     _log.debug(
                         "Application {} has a dependency on {}",
-                        reference, extensionDependency);
+                        registrator, extensionDependency);
                 }
 
                 try {
@@ -1023,17 +994,19 @@ public class Whiteboard {
                                 _log,
                                 () -> String.format(
                                     "Application %s has invalid dependency %s",
-                                    reference, extensionDependency)),
+                                    registrator, extensionDependency)),
                             ifErrorEnabled(
                                 _log,
                                 () -> String.format(
                                     "Application %s with invalid dependency " +
                                         "has left",
-                                    reference))
+                                    registrator))
                         ).
                         effects(
-                            _runtime::addErroredApplication,
-                            _runtime::removeErroredApplication
+                            __ -> _runtime.addErroredApplication(
+                                applicationReference),
+                            __ -> _runtime.removeErroredApplication(
+                                applicationReference)
                         ).then(
                             nothing()
                         );
@@ -1041,15 +1014,14 @@ public class Whiteboard {
 
                 program =
                     once(
-                        _extensionRegistry.waitForExtension(
-                            extensionDependency).
+                        registrator.waitForExtension(extensionDependency).
                         flatMap(
                             sr -> {
                                 Object applicationSelectProperty =
                                     sr.getProperty(JAX_RS_APPLICATION_SELECT);
 
                                 if (applicationSelectProperty == null) {
-                                    return just(reference);
+                                    return just(registrator);
                                 }
 
                                 Filter filter;
@@ -1062,10 +1034,11 @@ public class Whiteboard {
                                     return nothing();
                                 }
 
-                                if (filter.matches(
-                                    getApplicationProperties(reference))) {
+                                if (filter.match(
+                                    applicationReference.
+                                        getServiceReference())) {
 
-                                    return just(reference);
+                                    return just(registrator);
                                 }
 
                                 return nothing();
@@ -1073,17 +1046,17 @@ public class Whiteboard {
                         )).effects(
                                 __ -> {},
                                 __ -> _runtime.addDependentApplication(
-                                    reference)
+                                    applicationReference)
                         ).
                         effects(
                             ifDebugEnabled(
                                 _log,
-                                () -> "Application "+ reference +
+                                () -> "Application "+ registrator +
                                     " dependency " + extensionDependency +
                                         " has been fullfiled"),
                             ifDebugEnabled(
                                 _log,
-                                () -> "Application "+ reference +
+                                () -> "Application "+ registrator +
                                     " dependency " + extensionDependency +
                                         " has gone")
                         ).
@@ -1091,12 +1064,12 @@ public class Whiteboard {
             }
 
             program = effects(
-                () -> _runtime.addDependentApplication(reference),
-                () -> _runtime.removeDependentApplication(reference)
+                () -> _runtime.addDependentApplication(applicationReference),
+                () -> _runtime.removeDependentApplication(applicationReference)
             ).then(program);
 
             program = program.effects(
-                __ -> _runtime.removeDependentApplication(reference),
+                __ -> _runtime.removeDependentApplication(applicationReference),
                 __ -> {}
             );
 
@@ -1145,13 +1118,12 @@ public class Whiteboard {
 
     private OSGi<?> waitForExtensionDependencies(
         CachingServiceReference<?> reference,
-        CachingServiceReference<CxfJaxrsServiceRegistrator>
-            applicationRegistratorReference,
+        CxfJaxrsServiceRegistrator cxfJaxrsServiceRegistrator,
         Consumer<CachingServiceReference<?>> onAddingDependent,
         Consumer<CachingServiceReference<?>> onRemovingDependent) {
 
-        String applicationName = getServiceName(
-            applicationRegistratorReference::getProperty);
+        Map<String, ?> applicationRegistratorProperties =
+            cxfJaxrsServiceRegistrator.getProperties();
 
         String[] extensionDependencies = canonicalize(
             reference.getProperty(JAX_RS_EXTENSION_SELECT));
@@ -1176,21 +1148,22 @@ public class Whiteboard {
                 Filter extensionFilter = _bundleContext.createFilter(
                     finalExtensionDependency);
 
-                if (
-                    extensionFilter.match(_runtimeReference) ||
-                    extensionFilter.match(
-                        applicationRegistratorReference.getServiceReference()))
+                if (extensionFilter.match(_runtimeReference) ||
+                    extensionFilter.matches(
+                        applicationRegistratorProperties))
                 {
                     continue;
                 }
 
                 program =
-                    once(_applicationExtensionRegistry.waitForApplicationExtension(
-                        applicationName, extensionDependency).effects(
-                        __ -> {},
-                        __ -> onAddingDependent.accept(reference)
-                    )).
-                    effects(
+                    once(
+                        cxfJaxrsServiceRegistrator.waitForExtension(
+                            extensionDependency).
+                        effects(
+                            __ -> {},
+                            __ -> onAddingDependent.accept(reference)
+                        )
+                    ).effects(
                         ifDebugEnabled(
                             _log,
                             () -> "Extension " + reference +
@@ -1227,7 +1200,7 @@ public class Whiteboard {
             properties.get(JAX_RS_APPLICATION_BASE));
     }
 
-    private OSGi<CachingServiceReference<CxfJaxrsServiceRegistrator>>
+    private OSGi<CxfJaxrsServiceRegistrator>
         chooseApplication(
             CachingServiceReference<?> serviceReference,
             Consumer<CachingServiceReference<?>> onWaiting,
@@ -1310,11 +1283,9 @@ public class Whiteboard {
     }
 
     private OSGi<ServiceRegistration<Servlet>> registerCXFServletService(
-        Bus bus, Supplier<Map<String, ?>> servicePropertiesSup,
+        Bus bus, Map<String, Object> serviceProperties,
         CachingServiceReference<ServletContextHelper> contextReference) {
 
-        Map<String, ?> serviceProperties = servicePropertiesSup.get();
-
         String address = canonicalizeAddress(
             getApplicationBase(serviceProperties::get));
 
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/cxf/CxfJaxrsServiceRegistrator.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/cxf/CxfJaxrsServiceRegistrator.java
index 2c51445..5ccbff8 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/cxf/CxfJaxrsServiceRegistrator.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/cxf/CxfJaxrsServiceRegistrator.java
@@ -21,7 +21,6 @@ import static java.util.stream.Collectors.toMap;
 import static org.apache.aries.jax.rs.whiteboard.internal.Whiteboard.SUPPORTED_EXTENSION_INTERFACES;
 import static org.apache.aries.jax.rs.whiteboard.internal.utils.Utils.canonicalize;
 import static org.apache.cxf.jaxrs.provider.ProviderFactory.DEFAULT_FILTER_NAME_BINDING;
-import static org.osgi.service.jaxrs.whiteboard.JaxrsWhiteboardConstants.JAX_RS_NAME;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -43,8 +42,9 @@ import javax.ws.rs.core.FeatureContext;
 import javax.ws.rs.ext.RuntimeDelegate;
 
 import org.apache.aries.component.dsl.CachingServiceReference;
-import org.apache.aries.jax.rs.whiteboard.internal.ApplicationExtensionRegistry;
+import org.apache.aries.component.dsl.OSGi;
 import org.apache.aries.jax.rs.whiteboard.internal.AriesJaxrsServiceRuntime;
+import org.apache.aries.jax.rs.whiteboard.internal.ServiceReferenceRegistry;
 import org.apache.aries.jax.rs.whiteboard.internal.utils.ServiceTuple;
 import org.apache.cxf.Bus;
 import org.apache.cxf.common.util.ClassHelper;
@@ -65,19 +65,19 @@ import org.apache.cxf.jaxrs.utils.AnnotationUtils;
 
 public class CxfJaxrsServiceRegistrator {
 
+    public Map<String, ?> getProperties() {
+        return _properties;
+    }
+
     public CxfJaxrsServiceRegistrator(
         Bus bus, ServiceTuple<Application> applicationTuple,
         Map<String, ?> properties,
-        ApplicationExtensionRegistry applicationExtensionRegistry,
         AriesJaxrsServiceRuntime ariesJaxrsServiceRuntime) {
 
         _bus = bus;
         _applicationTuple = applicationTuple;
         _properties = Collections.unmodifiableMap(new HashMap<>(properties));
         _ariesJaxrsServiceRuntime = ariesJaxrsServiceRuntime;
-        _applicationName = AriesJaxrsServiceRuntime.getServiceName(
-            _properties::get);
-        _applicationExtensionRegistry = applicationExtensionRegistry;
 
         Comparator<ServiceTuple<?>> comparing = Comparator.comparing(
             ServiceTuple::getCachingServiceReference);
@@ -85,6 +85,7 @@ public class CxfJaxrsServiceRegistrator {
         _providers = new TreeSet<>(comparing);
         _erroredProviders = new ArrayList<>();
         _erroredServices = new ArrayList<>();
+        _serviceReferenceRegistry = new ServiceReferenceRegistry();
     }
 
     public synchronized void add(ResourceProvider resourceProvider) {
@@ -155,8 +156,7 @@ public class CxfJaxrsServiceRegistrator {
                 _providers.remove(erroredProvider);
                 _ariesJaxrsServiceRuntime.addErroredExtension(
                     cachingServiceReference);
-                _applicationExtensionRegistry.unregisterExtensionInApplication(
-                    _applicationName, cachingServiceReference);
+                _serviceReferenceRegistry.unregister(cachingServiceReference);
             }
             for (ResourceProvider erroredService : _erroredServices) {
                 _services.remove(erroredService);
@@ -236,6 +236,12 @@ public class CxfJaxrsServiceRegistrator {
         return classes;
     }
 
+    public void registerExtension(
+        CachingServiceReference<?> serviceReference) {
+
+        _serviceReferenceRegistry.register(serviceReference);
+    }
+
     public synchronized void remove(ResourceProvider resourceProvider) {
         if (_erroredServices.remove(resourceProvider)) {
             _ariesJaxrsServiceRuntime.removeErroredEndpoint(
@@ -263,7 +269,18 @@ public class CxfJaxrsServiceRegistrator {
         doRewire(_providers, _services);
     }
 
-    private final String _applicationName;
+    public void unregisterExtension(
+        CachingServiceReference<?> serviceReference) {
+
+        _serviceReferenceRegistry.unregister(serviceReference);
+    }
+
+    public OSGi<CachingServiceReference<?>> waitForExtension(
+        String extensionDependency) {
+
+        return _serviceReferenceRegistry.waitFor(extensionDependency);
+    }
+
     private ArrayList<ServiceTuple<?>> _erroredProviders;
     private ArrayList<ResourceProvider> _erroredServices;
 
@@ -469,7 +486,7 @@ public class CxfJaxrsServiceRegistrator {
     private JAXRSServerFactoryBean _jaxRsServerFactoryBean;
     private Map<String, Object> _properties;
     private AriesJaxrsServiceRuntime _ariesJaxrsServiceRuntime;
-    private ApplicationExtensionRegistry _applicationExtensionRegistry;
+    private ServiceReferenceRegistry _serviceReferenceRegistry;
     private Server _server;
 
     private static Set<String> getFilterNameBindings(