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 2017/08/29 18:27:27 UTC

[3/3] aries-jax-rs-whiteboard git commit: Add support for applications with extensions

Add support for applications with extensions

Applications that depend on extension in the runtime


Project: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/repo
Commit: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/commit/449f090b
Tree: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/tree/449f090b
Diff: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/diff/449f090b

Branch: refs/heads/master
Commit: 449f090b340e4bd59078bab84609defa4697737b
Parents: f75ef62
Author: Carlos Sierra <cs...@apache.org>
Authored: Tue Aug 29 20:26:31 2017 +0200
Committer: Carlos Sierra <cs...@apache.org>
Committed: Tue Aug 29 20:26:31 2017 +0200

----------------------------------------------------------------------
 jax-rs.itests/src/main/java/test/JaxrsTest.java | 593 ++++++++++++-------
 .../internal/AriesJaxRSServiceRuntime.java      |  26 +-
 .../aries/jax/rs/whiteboard/internal/Utils.java |   4 +
 .../jax/rs/whiteboard/internal/Whiteboard.java  | 124 +++-
 4 files changed, 498 insertions(+), 249 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/449f090b/jax-rs.itests/src/main/java/test/JaxrsTest.java
----------------------------------------------------------------------
diff --git a/jax-rs.itests/src/main/java/test/JaxrsTest.java b/jax-rs.itests/src/main/java/test/JaxrsTest.java
index 6aa409a..0661a62 100644
--- a/jax-rs.itests/src/main/java/test/JaxrsTest.java
+++ b/jax-rs.itests/src/main/java/test/JaxrsTest.java
@@ -118,48 +118,50 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
-    public void testApplicationWithError() throws InterruptedException {
-        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
+    public void testApplicationChangeCount() throws Exception {
+        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime>
+            runtimeTracker = new ServiceTracker<>(
+                bundleContext, JaxRSServiceRuntime.class, null);
 
-        assertNotNull(runtime);
+        try {
+            runtimeTracker.open();
 
-        RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
+            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(
+                SERVICE_TIMEOUT);
 
-        assertEquals(0, runtimeDTO.applicationDTOs.length);
-        assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
+            assertNotNull(runtime);
 
-        ServiceRegistration<?> serviceRegistration = registerApplication(
-            new TestApplication() {
+            ServiceReference<JaxRSServiceRuntime> serviceReference =
+                runtimeTracker.getServiceReference();
 
-                @Override
-                public Set<Object> getSingletons() {
-                    throw new RuntimeException();
-                }
+            Long changeCount = (Long)serviceReference.getProperty(
+                "service.changecount");
 
-            });
+            Dictionary<String, Object> properties = new Hashtable<>();
 
-        runtimeDTO = runtime.getRuntimeDTO();
+            properties.put(JAX_RS_APPLICATION_BASE, "/test-counter");
 
-        assertEquals(0, runtimeDTO.applicationDTOs.length);
-        assertEquals(1, runtimeDTO.failedApplicationDTOs.length);
-        assertEquals(
-            DTOConstants.FAILURE_REASON_UNKNOWN,
-            runtimeDTO.failedApplicationDTOs[0].failureReason);
+            ServiceRegistration<?> serviceRegistration =
+                bundleContext.registerService(
+                    Application.class, new TestApplication(), properties);
 
-        Client client = createClient();
+            Long newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
 
-        WebTarget webTarget = client.
-            target("http://localhost:65532").
-            path("/test-application");
+            assertTrue(changeCount < newCount);
 
-        assertEquals(404, webTarget.request().get().getStatus());
+            changeCount = newCount;
 
-        serviceRegistration.unregister();
+            serviceRegistration.unregister();
 
-        runtimeDTO = runtime.getRuntimeDTO();
+            newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
 
-        assertEquals(0, runtimeDTO.applicationDTOs.length);
-        assertEquals(0, runtimeDTO.failedApplicationDTOs.length);
+            assertTrue(changeCount < newCount);
+        }
+        finally {
+            runtimeTracker.close();
+        }
     }
 
     @Test
@@ -425,110 +427,183 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
-    public void testApplicationChangeCount() throws Exception {
-        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime>
-            runtimeTracker = new ServiceTracker<>(
-                bundleContext, JaxRSServiceRuntime.class, null);
+    public void testApplicationWithDedicatedExtension()
+        throws InterruptedException {
 
-        try {
-            runtimeTracker.open();
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
 
-            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(
-                SERVICE_TIMEOUT);
+        assertNotNull(runtime);
 
-            assertNotNull(runtime);
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
 
-            ServiceReference<JaxRSServiceRuntime> serviceReference =
-                runtimeTracker.getServiceReference();
+        registerApplication(
+            new TestApplication(),
+            JAX_RS_EXTENSION_SELECT,
+            String.format("(%s=%s)", JAX_RS_NAME, "Filter"),
+            "propertyKey", "propertyValue");
 
-            Long changeCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
 
-            Dictionary<String, Object> properties = new Hashtable<>();
+        Client client = createClient();
 
-            properties.put(JAX_RS_APPLICATION_BASE, "/test-counter");
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("/test-application");
 
-            ServiceRegistration<?> serviceRegistration =
-                bundleContext.registerService(
-                    Application.class, new TestApplication(), properties);
+        Response response = webTarget.request().get();
 
-            Long newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        assertEquals(404, response.getStatus());
 
-            assertTrue(changeCount < newCount);
+        ServiceRegistration<?> filterRegistration = registerExtension(
+            "Filter", JAX_RS_APPLICATION_SELECT, "(propertyKey=propertyValue)");
 
-            changeCount = newCount;
+        assertEquals(1, runtime.getRuntimeDTO().applicationDTOs.length);
 
-            serviceRegistration.unregister();
+        response = webTarget.request().get();
 
-            newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        assertEquals("Hello application", response.readEntity(String.class));
 
-            assertTrue(changeCount < newCount);
-        }
-        finally {
-            runtimeTracker.close();
-        }
+        filterRegistration.unregister();
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
     }
 
     @Test
-    public void testResourcesChangeCount() throws Exception {
-        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime>
-            runtimeTracker = new ServiceTracker<>(
-                bundleContext, JaxRSServiceRuntime.class, null);
+    public void testApplicationWithError() throws InterruptedException {
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
 
-        try {
-            runtimeTracker.open();
+        assertNotNull(runtime);
 
-            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(15000L);
+        RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
 
-            assertNotNull(runtime);
+        assertEquals(0, runtimeDTO.applicationDTOs.length);
+        assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
 
-            ServiceReference<JaxRSServiceRuntime> serviceReference =
-                runtimeTracker.getServiceReference();
+        ServiceRegistration<?> serviceRegistration = registerApplication(
+            new TestApplication() {
 
-            Long changeCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+                @Override
+                public Set<Object> getSingletons() {
+                    throw new RuntimeException();
+                }
 
-            ServiceRegistration<?> serviceRegistration =
-                registerAddon(new TestAddon());
+            });
 
-            Long newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        runtimeDTO = runtime.getRuntimeDTO();
 
-            assertTrue(changeCount < newCount);
+        assertEquals(0, runtimeDTO.applicationDTOs.length);
+        assertEquals(1, runtimeDTO.failedApplicationDTOs.length);
+        assertEquals(
+            DTOConstants.FAILURE_REASON_UNKNOWN,
+            runtimeDTO.failedApplicationDTOs[0].failureReason);
 
-            changeCount = newCount;
+        Client client = createClient();
 
-            ServiceRegistration<?> serviceRegistration2 =
-                registerAddon(new TestAddon());
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("/test-application");
 
-            newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        assertEquals(404, webTarget.request().get().getStatus());
 
-            assertTrue(changeCount < newCount);
+        serviceRegistration.unregister();
 
-            changeCount = newCount;
+        runtimeDTO = runtime.getRuntimeDTO();
 
-            serviceRegistration.unregister();
+        assertEquals(0, runtimeDTO.applicationDTOs.length);
+        assertEquals(0, runtimeDTO.failedApplicationDTOs.length);
+    }
 
-            newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+    @Test
+    public void testApplicationWithExtensionDryRun()
+        throws InterruptedException {
 
-            assertTrue(changeCount < newCount);
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
 
-            changeCount = newCount;
+        assertNotNull(runtime);
 
-            serviceRegistration2.unregister();
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
 
-            newCount = (Long)serviceReference.getProperty(
-                "service.changecount");
+        registerApplication(
+            new TestApplication(),
+            JAX_RS_EXTENSION_SELECT,
+            String.format("(%s=%s)", JAX_RS_NAME, "Filter"));
 
-            assertTrue(changeCount < newCount);
-        }
-        finally {
-            runtimeTracker.close();
-        }
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("/test-application");
+
+        Response response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
+
+        ServiceRegistration<?> filterRegistration = registerExtension(
+            "Filter", JAX_RS_APPLICATION_SELECT, "(unexistent=application)");
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
+
+        filterRegistration.unregister();
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
+    }
+
+    @Test
+    public void testApplicationWithGenericExtension()
+        throws InterruptedException {
+
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
+
+        assertNotNull(runtime);
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        registerApplication(
+            new TestApplication(),
+            JAX_RS_EXTENSION_SELECT,
+            String.format("(%s=%s)", JAX_RS_NAME, "Filter"));
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("/test-application");
+
+        Response response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
+
+        ServiceRegistration<?> filterRegistration = registerExtension("Filter");
+
+        assertEquals(1, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        response = webTarget.request().get();
+
+        assertEquals("Hello application", response.readEntity(String.class));
+
+        filterRegistration.unregister();
+
+        assertEquals(0, runtime.getRuntimeDTO().applicationDTOs.length);
+
+        response = webTarget.request().get();
+
+        assertEquals(404, response.getStatus());
     }
 
     @Test
@@ -566,6 +641,30 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
+    public void testExtensionRegisterOnlySignalledInterfaces()
+        throws InterruptedException {
+
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("test-application");
+
+        registerApplication(new TestApplicationWithException());
+
+        ServiceRegistration<?> filterRegistration =
+            registerMultiExtension("Filter", ExceptionMapper.class.getName());
+
+        Response response = webTarget.request().get();
+
+        assertEquals(200, response.getStatus());
+
+        assertNull(response.getHeaders().getFirst("Filtered"));
+
+        filterRegistration.unregister();
+    }
+
+    @Test
     public void testGettableAndNotGettableApplication()
         throws InterruptedException {
 
@@ -670,6 +769,56 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
+    public void testInvalidExtension() throws InterruptedException {
+        Client client = createClient();
+
+        WebTarget webTarget = client.
+            target("http://localhost:65532").
+            path("test");
+
+        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
+
+        RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
+
+        assertEquals(
+            0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+        registerAddon(new TestAddon());
+
+        ServiceRegistration<?> filterRegistration =
+            registerInvalidExtension("Filter");
+
+        runtimeDTO = runtime.getRuntimeDTO();
+
+        assertEquals(0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+        assertEquals(1, runtimeDTO.failedExtensionDTOs.length);
+        assertEquals(
+            (long)filterRegistration.getReference().getProperty(
+                "service.id"),
+            runtimeDTO.failedExtensionDTOs[0].serviceId);
+        assertEquals(
+            DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE,
+            runtimeDTO.failedExtensionDTOs[0].failureReason);
+
+        Response response = webTarget.request().get();
+
+        assertEquals(
+            "This should say hello", "Hello test",
+            response.readEntity(String.class));
+
+        assertNull(response.getHeaders().getFirst("Filtered"));
+
+        filterRegistration.unregister();
+
+        runtimeDTO = runtime.getRuntimeDTO();
+
+        assertEquals(0, runtimeDTO.defaultApplication.extensionDTOs.length);
+
+        assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
+    }
+
+    @Test
     public void testNotGettableApplication() throws InterruptedException {
         JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
 
@@ -693,6 +842,66 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
+    public void testResourcesChangeCount() throws Exception {
+        ServiceTracker<JaxRSServiceRuntime, JaxRSServiceRuntime>
+            runtimeTracker = new ServiceTracker<>(
+                bundleContext, JaxRSServiceRuntime.class, null);
+
+        try {
+            runtimeTracker.open();
+
+            JaxRSServiceRuntime runtime = runtimeTracker.waitForService(15000L);
+
+            assertNotNull(runtime);
+
+            ServiceReference<JaxRSServiceRuntime> serviceReference =
+                runtimeTracker.getServiceReference();
+
+            Long changeCount = (Long)serviceReference.getProperty(
+                "service.changecount");
+
+            ServiceRegistration<?> serviceRegistration =
+                registerAddon(new TestAddon());
+
+            Long newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
+
+            assertTrue(changeCount < newCount);
+
+            changeCount = newCount;
+
+            ServiceRegistration<?> serviceRegistration2 =
+                registerAddon(new TestAddon());
+
+            newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
+
+            assertTrue(changeCount < newCount);
+
+            changeCount = newCount;
+
+            serviceRegistration.unregister();
+
+            newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
+
+            assertTrue(changeCount < newCount);
+
+            changeCount = newCount;
+
+            serviceRegistration2.unregister();
+
+            newCount = (Long)serviceReference.getProperty(
+                "service.changecount");
+
+            assertTrue(changeCount < newCount);
+        }
+        finally {
+            runtimeTracker.close();
+        }
+    }
+
+    @Test
     public void testStandaloneEndPoint() throws InterruptedException {
         Client client = createClient();
 
@@ -918,77 +1127,46 @@ public class JaxrsTest extends TestHelper {
     }
 
     @Test
-    public void testInvalidExtension() throws InterruptedException {
+    public void testStandaloneFilterReadd() {
         Client client = createClient();
 
         WebTarget webTarget = client.
             target("http://localhost:65532").
             path("test");
 
-        JaxRSServiceRuntime runtime = getJaxRSServiceRuntime();
-
-        RuntimeDTO runtimeDTO = runtime.getRuntimeDTO();
-
-        assertEquals(
-            0, runtimeDTO.defaultApplication.extensionDTOs.length);
-
         registerAddon(new TestAddon());
 
-        ServiceRegistration<?> filterRegistration =
-            registerInvalidExtension("Filter");
-
-        runtimeDTO = runtime.getRuntimeDTO();
-
-        assertEquals(0, runtimeDTO.defaultApplication.extensionDTOs.length);
-
-        assertEquals(1, runtimeDTO.failedExtensionDTOs.length);
-        assertEquals(
-            (long)filterRegistration.getReference().getProperty(
-                "service.id"),
-            runtimeDTO.failedExtensionDTOs[0].serviceId);
-        assertEquals(
-            DTOConstants.FAILURE_REASON_NOT_AN_EXTENSION_TYPE,
-            runtimeDTO.failedExtensionDTOs[0].failureReason);
-
-        Response response = webTarget.request().get();
-
-        assertEquals(
-            "This should say hello", "Hello test",
-            response.readEntity(String.class));
-
-        assertNull(response.getHeaders().getFirst("Filtered"));
-
-        filterRegistration.unregister();
-
-        runtimeDTO = runtime.getRuntimeDTO();
-
-        assertEquals(0, runtimeDTO.defaultApplication.extensionDTOs.length);
-
-        assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
-    }
+        assertEquals("Hello test",
+            webTarget.request().get().readEntity(String.class));
 
-    @Test
-    public void testExtensionRegisterOnlySignalledInterfaces()
-        throws InterruptedException {
+        Runnable testCase = () -> {
+            ServiceRegistration<?> filterRegistration = null;
 
-        Client client = createClient();
+            try {
+                Response response = webTarget.request().get();
 
-        WebTarget webTarget = client.
-            target("http://localhost:65532").
-            path("test-application");
+                assertNull(response.getHeaders().getFirst("Filtered"));
 
-        registerApplication(new TestApplicationWithException());
+                filterRegistration = registerExtension("Filter");
 
-        ServiceRegistration<?> filterRegistration =
-            registerMultiExtension("Filter", ExceptionMapper.class.getName());
+                response = webTarget.request().get();
 
-        Response response = webTarget.request().get();
+                assertEquals(
+                    "Hello test", response.readEntity(String.class));
 
-        assertEquals(200, response.getStatus());
+                assertEquals(
+                    "true", response.getHeaders().getFirst("Filtered"));
+            }
+            finally {
+                if (filterRegistration != null) {
+                    filterRegistration.unregister();
+                }
+            }
+        };
 
-        assertNull(response.getHeaders().getFirst("Filtered"));
+        testCase.run();
 
-        filterRegistration.unregister();
+        testCase.run();
     }
 
     @Test
@@ -1040,49 +1218,6 @@ public class JaxrsTest extends TestHelper {
         assertEquals(0, runtimeDTO.failedExtensionDTOs.length);
     }
 
-    @Test
-    public void testStandaloneFilterReadd() {
-        Client client = createClient();
-
-        WebTarget webTarget = client.
-            target("http://localhost:65532").
-            path("test");
-
-        registerAddon(new TestAddon());
-
-        assertEquals("Hello test",
-            webTarget.request().get().readEntity(String.class));
-
-        Runnable testCase = () -> {
-            ServiceRegistration<?> filterRegistration = null;
-
-            try {
-                Response response = webTarget.request().get();
-
-                assertNull(response.getHeaders().getFirst("Filtered"));
-
-                filterRegistration = registerExtension("Filter");
-
-                response = webTarget.request().get();
-
-                assertEquals(
-                    "Hello test", response.readEntity(String.class));
-
-                assertEquals(
-                    "true", response.getHeaders().getFirst("Filtered"));
-            }
-            finally {
-                if (filterRegistration != null) {
-                    filterRegistration.unregister();
-                }
-            }
-        };
-
-        testCase.run();
-
-        testCase.run();
-    }
-
     private JaxRSServiceRuntime getJaxRSServiceRuntime()
         throws InterruptedException {
 
@@ -1218,46 +1353,69 @@ public class JaxrsTest extends TestHelper {
         return serviceRegistration;
     }
 
-    private ServiceRegistration<?> registerMultiExtension(
-        String name, String... classes) {
+    private ServiceRegistration<?> registerInvalidExtension(
+        String name, Object... keyValues) {
+
+        TestFilter testFilter = new TestFilter();
 
         Dictionary<String, Object> properties = new Hashtable<>();
 
         properties.put(JAX_RS_EXTENSION, true);
         properties.put(JAX_RS_NAME, name);
 
-        ServiceRegistration<?> serviceRegistration =
+        for (int i = 0; i < keyValues.length; i = i + 2) {
+            properties.put(keyValues[i].toString(), keyValues[i + 1]);
+        }
+
+        ServiceRegistration<Object> serviceRegistration =
             bundleContext.registerService(
-                classes, new TestFilterAndExceptionMapper(), properties);
+                Object.class, testFilter, properties);
 
         _registrations.add(serviceRegistration);
 
         return serviceRegistration;
     }
 
-    private ServiceRegistration<?> registerInvalidExtension(
-        String name, Object... keyValues) {
-
-        TestFilter testFilter = new TestFilter();
+    private ServiceRegistration<?> registerMultiExtension(
+        String name, String... classes) {
 
         Dictionary<String, Object> properties = new Hashtable<>();
 
         properties.put(JAX_RS_EXTENSION, true);
         properties.put(JAX_RS_NAME, name);
 
-        for (int i = 0; i < keyValues.length; i = i + 2) {
-            properties.put(keyValues[i].toString(), keyValues[i + 1]);
-        }
-
-        ServiceRegistration<Object> serviceRegistration =
+        ServiceRegistration<?> serviceRegistration =
             bundleContext.registerService(
-                Object.class, testFilter, properties);
+                classes, new TestFilterAndExceptionMapper(), properties);
 
         _registrations.add(serviceRegistration);
 
         return serviceRegistration;
     }
 
+    private ServiceRegistration<Application> registerUngettableApplication(
+        Object... keyValues) {
+
+        return registerApplication(
+            new ServiceFactory<Application>() {
+                @Override
+                public Application getService(
+                    Bundle bundle,
+                    ServiceRegistration<Application> serviceRegistration) {
+
+                    return null;
+                }
+
+                @Override
+                public void ungetService(
+                    Bundle bundle,
+                    ServiceRegistration<Application> serviceRegistration,
+                    Application application) {
+
+                }
+            }, keyValues);
+    }
+
     private ServiceRegistration<?> registerUngettableExtension(
         String name, Object... keyValues) {
 
@@ -1298,27 +1456,4 @@ public class JaxrsTest extends TestHelper {
         return serviceRegistration;
     }
 
-    private ServiceRegistration<Application> registerUngettableApplication(
-        Object... keyValues) {
-
-        return registerApplication(
-            new ServiceFactory<Application>() {
-                @Override
-                public Application getService(
-                    Bundle bundle,
-                    ServiceRegistration<Application> serviceRegistration) {
-
-                    return null;
-                }
-
-                @Override
-                public void ungetService(
-                    Bundle bundle,
-                    ServiceRegistration<Application> serviceRegistration,
-                    Application application) {
-
-                }
-            }, keyValues);
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/449f090b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/AriesJaxRSServiceRuntime.java
----------------------------------------------------------------------
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 d9cc934..13b9628 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
@@ -69,6 +69,9 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
     private Collection<ServiceReference<Application>> _shadowedApplications =
         new CopyOnWriteArrayList<>();
 
+    private Set<ServiceReference<Application>> _dependentApplications =
+        ConcurrentHashMap.newKeySet();
+
     private Collection<ServiceReference<Application>> _erroredApplications =
         new CopyOnWriteArrayList<>();
 
@@ -100,6 +103,12 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
             applicationName, merger(extensionServiceReference));
     }
 
+    public void addDependentApplication(
+        ServiceReference<Application> applicationReference) {
+
+        _dependentApplications.add(applicationReference);
+    }
+
     public void addDependentService(ServiceReference<?> serviceReference) {
         _dependentServices.add(serviceReference);
     }
@@ -172,7 +181,9 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
             shadowedApplicationsDTOStream(),
             Stream.concat(
                 unreferenciableApplicationsDTOStream(),
-                erroredApplicationsDTOStream())
+                Stream.concat(
+                    dependentApplicationsDTOStream(),
+                    erroredApplicationsDTOStream()))
             ).toArray(
                 FailedApplicationDTO[]::new
             );
@@ -213,6 +224,12 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
             applicationName, remover(extensionServiceReference));
     }
 
+    public void removeDependentApplication(
+        ServiceReference<Application> applicationReference) {
+
+        _dependentApplications.remove(applicationReference);
+    }
+
     public void removeDependentService(ServiceReference<?> serviceReference) {
         _dependentServices.remove(serviceReference);
     }
@@ -323,6 +340,13 @@ public class AriesJaxRSServiceRuntime implements JaxRSServiceRuntime {
         return failedResourceDTO;
     }
 
+    private Stream<FailedApplicationDTO> dependentApplicationsDTOStream() {
+        return _dependentApplications.stream().map(
+            sr -> buildFailedApplicationDTO(
+                DTOConstants.FAILURE_REASON_REQUIRED_EXTENSIONS_UNAVAILABLE, sr)
+        );
+    }
+
     private Stream<FailedResourceDTO> dependentServiceStreamDTO() {
         return _dependentServices.stream().map(
             sr -> buildFailedResourceDTO(

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/449f090b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
----------------------------------------------------------------------
diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
index 15a26fd..72c6ef6 100644
--- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
+++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Utils.java
@@ -130,6 +130,10 @@ public class Utils {
                     map.compute(
                         key,
                         (__, set) -> {
+                            if (set.isEmpty()) {
+                                return set;
+                            }
+
                             Event<T> last = set.last();
 
                             if (content.equals(last.getContent())) {

http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/449f090b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/Whiteboard.java
----------------------------------------------------------------------
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 5787fa4..3c1d71e 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
@@ -155,8 +155,8 @@ public class Whiteboard {
                 all(
                     ignore(
                         whiteboardApplications(
-                            runtimeReference, runtime, configurationMap,
-                            counter)),
+                            bundleContext, runtimeReference, runtime,
+                            configurationMap, counter)),
                     ignore(
                         whiteBoardApplicationResources(
                             bundleContext, runtimeReference,
@@ -508,18 +508,97 @@ public class Whiteboard {
             anyMatch(SUPPORTED_EXTENSION_INTERFACES::contains);
     }
 
+    private static OSGi<ServiceReference<Application>>
+        waitForApplicationDependencies(
+            BundleContext bundleContext,
+            ServiceReference<Application> applicationReference,
+            AriesJaxRSServiceRuntime runtime,
+            OSGi<ServiceReference<Application>> program) {
+
+        String[] extensionDependencies = canonicalize(
+            applicationReference.getProperty(JAX_RS_EXTENSION_SELECT));
+
+        if (extensionDependencies.length > 0) {
+            program = onClose(
+                () -> runtime.removeDependentApplication(applicationReference)).
+                then(program);
+
+            runtime.addDependentApplication(applicationReference);
+        }
+        else {
+            return program;
+        }
+
+        for (String extensionDependency : extensionDependencies) {
+            extensionDependency = String.format(
+                "(&(!(objectClass=%s))%s)",
+                ApplicationExtensionRegistration.class.getName(),
+                extensionDependency);
+
+            program =
+                serviceReferences(extensionDependency).
+                    flatMap(
+                        sr -> {
+                            Object applicationSelectProperty =
+                                sr.getProperty(JAX_RS_APPLICATION_SELECT);
+
+                            if (applicationSelectProperty == null) {
+                                return just(applicationReference);
+                            }
+
+                            Filter filter;
+
+                            try {
+                                filter = bundleContext.createFilter(
+                                    applicationSelectProperty.toString());
+                            }
+                            catch (InvalidSyntaxException e) {
+                                return nothing();
+                            }
+
+                            if (filter.match(applicationReference)) {
+                                return just(applicationReference);
+                            }
+
+                            return nothing();
+                        }
+                    ).foreach(
+                    __ -> {},
+                    __ -> runtime.addDependentApplication(
+                        applicationReference)
+                ).
+                    then(program);
+        }
+
+        program = onClose(
+            ()-> runtime.removeDependentApplication(applicationReference)).
+            then(program);
+
+        program = program.foreach(
+            __ -> runtime.removeDependentApplication(applicationReference)
+        ).
+        then(
+            just(applicationReference)
+        );
+
+        return program;
+    }
+
     private static OSGi<?> waitForExtensionDependencies(
         BundleContext bundleContext,
         ServiceReference<?> serviceReference,
         ApplicationReference applicationReference,
         AriesJaxRSServiceRuntime runtime, OSGi<?> program) {
 
-        String[] extensionDependencies = Utils.canonicalize(
+        String[] extensionDependencies = canonicalize(
             serviceReference.getProperty(JAX_RS_EXTENSION_SELECT));
 
         if (extensionDependencies.length > 0) {
             runtime.addDependentService(serviceReference);
         }
+        else {
+            return program;
+        }
 
         for (String extensionDependency : extensionDependencies) {
             try {
@@ -548,6 +627,10 @@ public class Whiteboard {
             }
         }
 
+        program = onClose(
+            () -> runtime.removeDependentService(serviceReference)).
+            then(program);
+
         program = program.foreach(
             __ -> runtime.removeDependentService(serviceReference)
         );
@@ -614,15 +697,20 @@ public class Whiteboard {
     }
 
     private static OSGi<?> whiteboardApplications(
+        BundleContext bundleContext,
         ServiceReference<?> jaxRsRuntimeServiceReference,
         AriesJaxRSServiceRuntime runtime,
-        Map<String, ?> configuration, ServiceRegistrationChangeCounter counter) {
+        Map<String, ?> configuration,
+        ServiceRegistrationChangeCounter counter) {
 
         OSGi<ServiceTuple<Application>> gettableAplicationForWhiteboard =
             onlyGettables(
                 countChanges(
                     getApplicationsForWhiteboard(jaxRsRuntimeServiceReference),
-                    counter),
+                    counter).
+                flatMap(
+                    sr -> waitForApplicationDependencies(
+                        bundleContext, sr, runtime, just(sr))),
                 runtime::addNotGettableApplication,
                 runtime::removeNotGettableApplication);
 
@@ -633,20 +721,18 @@ public class Whiteboard {
         );
 
         return
-            bundleContext().flatMap(
-                bundleContext -> highestRankedPerPath.flatMap(
-                    tuple -> deployApplication(
-                        configuration, bundleContext, tuple, runtime)
-                ).map(
-                    ServiceTuple::getServiceReference
-                ).map(
-                    Utils::getProperties
-                ).foreach(
-                    p -> runtime.setApplicationForPath(
-                        getApplicationBase(p::get), p),
-                    p -> runtime.unsetApplicationForPath(
-                        getApplicationBase(p::get))
-                )
+            highestRankedPerPath.flatMap(
+                tuple -> deployApplication(
+                    configuration, bundleContext, tuple, runtime)
+            ).map(
+                ServiceTuple::getServiceReference
+            ).map(
+                Utils::getProperties
+            ).foreach(
+                p -> runtime.setApplicationForPath(
+                    getApplicationBase(p::get), p),
+                p -> runtime.unsetApplicationForPath(
+                    getApplicationBase(p::get))
             );
     }