You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by tj...@apache.org on 2014/07/11 17:22:52 UTC

svn commit: r1609727 - in /aries/trunk/blueprint: blueprint-core/src/main/java/org/apache/aries/blueprint/container/ blueprint-itests/ blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/ blueprint-itests/src/test/java/org/apache/aries/blu...

Author: tjwatson
Date: Fri Jul 11 15:22:51 2014
New Revision: 1609727

URL: http://svn.apache.org/r1609727
Log:
ARIES-1215 - Use system bundle for tracking namespace handlers and bundles

If the property org.apache.aries.blueprint.use.system.context=true is set 
then the blueprint extender will use the system bundle context to track blueprint bundles
and track NamespaceHandler services.

Two new testcases were added.

1) verifies that if a blueprint bundle is hidden
from the blueprint extender, using bundle hooks, then the blueprint extender can still
track the bundle properly using the system bundle context

2) verifies that if the blueprint cm bundle is hidden from the 
blueprint extender, using service hooks, then the blueprint extender can still
process blueprint bundles that use the cm namespace handler properly

When org.apache.aries.blueprint.use.system.context=true the blueprint extender
will no longer use the RecursiveBundleTracker.  This means that the old 
equinox composite bundles will not be supported when this option is enabled.
This option is intended to be used with subsystems.


Added:
    aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerUseSystemContextTest.java
    aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/cm/ManagedServiceFactoryUseSystemBundleTest.java
Modified:
    aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
    aries/trunk/blueprint/blueprint-itests/pom.xml

Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java?rev=1609727&r1=1609726&r2=1609727&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintExtender.java Fri Jul 11 15:22:51 2014
@@ -53,6 +53,7 @@ import org.osgi.framework.ServiceRegistr
 import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.container.BlueprintEvent;
+import org.osgi.util.tracker.BundleTracker;
 import org.osgi.util.tracker.BundleTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -74,7 +75,7 @@ public class BlueprintExtender implement
     private final ConcurrentMap<Bundle, FutureTask> destroying = new ConcurrentHashMap<Bundle, FutureTask>();
     private BlueprintEventDispatcher eventDispatcher;
     private NamespaceHandlerRegistry handlers;
-    private RecursiveBundleTracker bt;
+    private Object bt;
     private ServiceRegistration parserServiceReg;
     private ServiceRegistration blueprintServiceReg;
     private ServiceRegistration quiesceParticipantReg;
@@ -86,7 +87,10 @@ public class BlueprintExtender implement
         LOGGER.debug("Starting blueprint extender...");
 
         this.context = ctx;
-        handlers = new NamespaceHandlerRegistryImpl(ctx);
+        boolean useSystemContext = Boolean.parseBoolean(ctx.getProperty("org.apache.aries.blueprint.use.system.context"));
+        BundleContext trackingContext = useSystemContext ? ctx.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext() : ctx;
+
+        handlers = new NamespaceHandlerRegistryImpl(trackingContext);
         executors = new ScheduledExecutorServiceWrapper(ctx, "Blueprint Extender", new ScheduledExecutorServiceFactory() {
           public ScheduledExecutorService create(String name)
           {
@@ -102,12 +106,16 @@ public class BlueprintExtender implement
         // handled.
         context.addBundleListener(this);
         int mask = Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.STOPPING | Bundle.ACTIVE;
-        bt = new RecursiveBundleTracker(ctx, mask, this);
+        bt = useSystemContext ? new BundleTracker(trackingContext, mask, this) : new  RecursiveBundleTracker(ctx, mask, this);
         
         proxyManager = new SingleServiceTracker<ProxyManager>(ctx, ProxyManager.class, new SingleServiceListener() {
           public void serviceFound() {
             LOGGER.debug("Found ProxyManager service, starting to process blueprint bundles");
-            bt.open();
+            if (bt instanceof BundleTracker) {
+            	((BundleTracker) bt).open();
+            } else if (bt instanceof RecursiveBundleTracker) {
+            	((RecursiveBundleTracker) bt).open();
+            }
           }
           public void serviceLost() {
             while (!containers.isEmpty()) {
@@ -115,7 +123,11 @@ public class BlueprintExtender implement
                 destroyContainer(bundle);
               }
             }
-            bt.close();
+            if (bt instanceof BundleTracker) {
+            	((BundleTracker) bt).close();
+            } else if (bt instanceof RecursiveBundleTracker) {
+            	((RecursiveBundleTracker) bt).close();
+            }
           }
           public void serviceReplaced() {
           }
@@ -165,7 +177,11 @@ public class BlueprintExtender implement
             }
         }
 
-        bt.close();
+        if (bt instanceof BundleTracker) {
+        	((BundleTracker) bt).close();
+        } else if (bt instanceof RecursiveBundleTracker) {
+        	((RecursiveBundleTracker) bt).close();
+        }
         proxyManager.close();
 
         this.eventDispatcher.destroy();

Modified: aries/trunk/blueprint/blueprint-itests/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-itests/pom.xml?rev=1609727&r1=1609726&r2=1609727&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-itests/pom.xml (original)
+++ aries/trunk/blueprint/blueprint-itests/pom.xml Fri Jul 11 15:22:51 2014
@@ -62,17 +62,17 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.core</artifactId>
-            <version>1.4.1-SNAPSHOT</version>
+            <version>1.4.2-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>blueprint-parser</artifactId>
-            <version>1.2.1-SNAPSHOT</version>
+            <version>1.2.2-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.proxy</groupId>
             <artifactId>org.apache.aries.proxy.impl</artifactId>
-            <version>1.0.3-SNAPSHOT</version>
+            <version>1.0.4-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.quiesce</groupId>
@@ -84,7 +84,7 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.cm</artifactId>
-            <version>1.0.4-SNAPSHOT</version>
+            <version>1.0.5-SNAPSHOT</version>
             <type>bundle</type>
             <scope>compile</scope>
             <exclusions>
@@ -244,14 +244,16 @@
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.annotation.api</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
+            <version>1.0.2-SNAPSHOT</version>
             <type>bundle</type>
             <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.aries.blueprint</groupId>
             <artifactId>org.apache.aries.blueprint.annotation.impl</artifactId>
-            <version>1.0.1-SNAPSHOT</version>
+            <!-- TODO using 1.0.1 released or 1.0.2.SNAPSHOT causes failures in
+            org.apache.aries.blueprint.itests.BlueprintAnnotationTest -->
+            <version>1.0.0</version>
             <type>bundle</type>
             <scope>compile</scope>
         </dependency>

Added: aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerUseSystemContextTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerUseSystemContextTest.java?rev=1609727&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerUseSystemContextTest.java (added)
+++ aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerUseSystemContextTest.java Fri Jul 11 15:22:51 2014
@@ -0,0 +1,105 @@
+/*
+ * 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.blueprint.itests;
+
+import static org.apache.aries.blueprint.itests.Helper.mvnBundle;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.bundle.EventHook;
+import org.osgi.framework.hooks.bundle.FindHook;
+
+public class BlueprintContainerUseSystemContextTest extends AbstractBlueprintIntegrationTest {
+
+	ServiceRegistration eventHook;
+	ServiceRegistration findHook;
+	@Before
+	public void regiserHook() {
+		final BundleContext systemContext = context().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
+		eventHook = context().registerService(EventHook.class, new EventHook() {
+			@Override
+			public void event(BundleEvent event,
+					Collection contexts) {
+				if ("org.apache.aries.blueprint.sample".equals(event.getBundle().getSymbolicName())) {
+					// hide sample from everything but the system bundle
+					// TODO on R6 we should be able to even try hiding from the system bundle
+					// R5 it was not clear if hooks could hide from the system bundle
+					// equinox R5 does allow hiding from system bundle
+					contexts.retainAll(Collections.singleton(systemContext));
+				}
+			}
+		}, null);
+		findHook = context().registerService(FindHook.class, new FindHook(){
+			@Override
+			public void find(BundleContext context, Collection bundles) {
+				if (context.equals(systemContext)) {
+					// TODO on R6 we should be able to even try hiding from the system bundle
+					// R5 it was not clear if hooks could hide from the system bundle
+					// equinox R5 does allow hiding from system bundle
+					return;
+				}
+				for (Iterator iBundles = bundles.iterator(); iBundles.hasNext();) {
+					if ("org.apache.aries.blueprint.sample".equals(((Bundle) iBundles.next()).getSymbolicName())) {
+						// hide sample from everything
+						iBundles.remove();
+					}
+				}
+			}}, null);
+	}
+
+	@After 
+	public void unregisterHook() {
+		eventHook.unregister();
+		findHook.unregister();
+	}
+
+    @Test
+    public void test() throws Exception {
+    	applyCommonConfiguration(context());
+        Bundle bundle = context().installBundle(sampleBundleOption().getURL());
+        assertNotNull(bundle);
+        bundle.start();
+        
+        // do the test
+        Helper.testBlueprintContainer(context(), bundle);
+    }
+
+    @org.ops4j.pax.exam.Configuration
+    public Option[] configuration() {
+        return new Option[] {
+            baseOptions(),
+            CoreOptions.systemProperty("org.apache.aries.blueprint.use.system.context").value("true"),
+            Helper.blueprintBundles()
+        };
+    }
+
+}

Added: aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/cm/ManagedServiceFactoryUseSystemBundleTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/cm/ManagedServiceFactoryUseSystemBundleTest.java?rev=1609727&view=auto
==============================================================================
--- aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/cm/ManagedServiceFactoryUseSystemBundleTest.java (added)
+++ aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/cm/ManagedServiceFactoryUseSystemBundleTest.java Fri Jul 11 15:22:51 2014
@@ -0,0 +1,404 @@
+/**
+ * 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.blueprint.itests.cm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.apache.aries.blueprint.itests.AbstractBlueprintIntegrationTest;
+import org.apache.aries.blueprint.itests.Helper;
+import org.apache.aries.blueprint.itests.cm.service.Foo;
+import org.apache.aries.blueprint.itests.cm.service.FooFactory;
+import org.apache.aries.blueprint.itests.cm.service.FooInterface;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.ProbeBuilder;
+import org.ops4j.pax.exam.TestProbeBuilder;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.hooks.service.EventListenerHook;
+import org.osgi.framework.hooks.service.FindHook;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class ManagedServiceFactoryUseSystemBundleTest extends AbstractBlueprintIntegrationTest {
+	private static final String CM_BUNDLE = "org.apache.aries.blueprint.cm";
+	private static final String TEST_BUNDLE = "org.apache.aries.blueprint.cm.test.b1";
+	@Inject
+	ConfigurationAdmin ca;
+	
+	@ProbeBuilder
+	public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
+		probe.setHeader(Constants.EXPORT_PACKAGE, Foo.class.getPackage().getName());
+    	probe.setHeader(Constants.IMPORT_PACKAGE, Foo.class.getPackage().getName());
+		return probe;
+	}
+
+    @org.ops4j.pax.exam.Configuration
+    public Option[] config() {
+    	InputStream testBundle = TinyBundles.bundle()
+    		.add(FooInterface.class)
+    		.add(Foo.class)
+    		.add(FooFactory.class)
+    		.add("OSGI-INF/blueprint/context.xml", 
+    				getResource("ManagedServiceFactoryTest.xml"))
+    		.set(Constants.BUNDLE_SYMBOLICNAME, TEST_BUNDLE)
+    		.set(Constants.EXPORT_PACKAGE, Foo.class.getPackage().getName())
+    		.set(Constants.IMPORT_PACKAGE, Foo.class.getPackage().getName())
+    		.build(TinyBundles.withBnd());
+    	return new Option[] {
+    			baseOptions(),
+                CoreOptions.systemProperty("org.apache.aries.blueprint.use.system.context").value("true"),
+    			Helper.blueprintBundles(),
+    			CoreOptions.keepCaches(),
+    			CoreOptions.streamBundle(testBundle)
+    	};
+    }
+
+	ServiceRegistration eventHook;
+	ServiceRegistration findHook;
+	@Before
+	public void regiserHook() throws BundleException {
+		context().getBundleByName(CM_BUNDLE).stop();
+		final BundleContext systemContext = context().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
+		eventHook = context().registerService(EventListenerHook.class, new EventListenerHook() {
+
+			@Override
+			public void event(ServiceEvent event,
+					Map contexts) {
+				if (CM_BUNDLE.equals(event.getServiceReference().getBundle().getSymbolicName())) {
+					// hide from everything but the system bundle
+					// TODO on R6 we should be able to even try hiding from the system bundle
+					// R5 it was not clear if hooks could hide from the system bundle
+					// equinox R5 does allow hiding from system bundle
+					contexts.keySet().retainAll(Collections.singleton(systemContext));
+				}
+			}
+
+		}, null);
+		findHook = context().registerService(FindHook.class, new FindHook(){
+			@Override
+			public void find(BundleContext context, String arg1, String arg2,
+					boolean arg3, Collection references) {
+				// hide from everything but the system bundle
+				// TODO on R6 we should be able to even try hiding from the system bundle
+				// R5 it was not clear if hooks could hide from the system bundle
+				// equinox R5 does allow hiding from system bundle
+				if (!context.equals(systemContext)) {
+					for (Iterator<ServiceReference> iReferences = references.iterator(); iReferences.hasNext();) {
+						if (CM_BUNDLE.equals(iReferences.next().getBundle().getSymbolicName())) {
+							iReferences.remove();
+						}
+					}
+				}
+			}
+			
+		}, null);
+		context().getBundleByName(CM_BUNDLE).start();
+	}
+
+	@After
+	public void unregisterHook() {
+		eventHook.unregister();
+		findHook.unregister();
+	}
+
+    @Test
+    public void test1() throws Exception {
+        Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory", null);
+        Hashtable<String,String> props = new Hashtable<String,String>();
+        props.put("a", "5");
+        cf.update(props);
+        
+		@SuppressWarnings("rawtypes")
+		ServiceReference sr = getServiceRef(Foo.class, "(key=foo1)");
+        Foo foo = (Foo)context().getService(sr);
+        assertNotNull(foo);
+        assertEquals(5, foo.getA());
+        assertEquals("default", foo.getB());
+        assertEquals("5", sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+
+        props = new Hashtable<String,String>();
+        props.put("a", "5");
+        props.put("b", "foo");
+        cf.update(props);
+        Thread.sleep(500);
+
+        // No update of bean after creation
+        assertEquals(5, foo.getA());
+        assertEquals("default", foo.getB());
+
+        // Only initial update of service properties
+        assertEquals("5", sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+    }
+
+    @Test
+    public void test2() throws Exception {
+        Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory2", null);
+        Hashtable<String,String> props = new Hashtable<String,String>();
+        props.put("a", "5");
+        cf.update(props);
+
+        @SuppressWarnings("rawtypes")
+		ServiceReference sr = getServiceRef(Foo.class, "(key=foo2)");
+		Foo foo = (Foo)context().getService(sr);
+        assertNotNull(foo);
+        assertEquals(5, foo.getA());
+        assertEquals("default", foo.getB());
+        assertNull(sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+
+        props = new Hashtable<String,String>();
+        props.put("a", "5");
+        props.put("b", "foo");
+        cf.update(props);
+
+        // Update after creation
+        Thread.sleep(500);
+        assertEquals(5, foo.getA());
+        assertEquals("foo", foo.getB());
+
+        // No update of service properties
+        assertNull(sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+    }
+
+
+
+    @Test
+    public void test3() throws Exception {
+        Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory3", null);
+        Hashtable<String,String> props = new Hashtable<String,String>();
+        props.put("a", "5");
+        cf.update(props);
+
+        @SuppressWarnings("rawtypes")
+		ServiceReference sr = getServiceRef(Foo.class, "(&(key=foo3)(a=5))");
+        assertNotNull(sr);
+        Foo foo = (Foo) context().getService(sr);
+        assertNotNull(foo);
+        assertEquals(5, foo.getA());
+        assertEquals("default", foo.getB());
+        assertEquals("5", sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+
+        props = new Hashtable<String,String>();
+        props.put("a", "5");
+        props.put("b", "foo");
+        cf.update(props);
+
+        // Update after creation
+        Thread.sleep(500);
+        assertEquals(5, foo.getA());
+        assertEquals("foo", foo.getB());
+
+        // Update of service properties
+        assertEquals("5", sr.getProperty("a"));
+        assertEquals("foo", sr.getProperty("b"));
+        cf.delete();
+    }
+
+    @SuppressWarnings("rawtypes")
+	@Test
+    public void testCreateAndUpdate() throws Exception {
+        Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory3", null);
+        Hashtable<String,String> props = new Hashtable<String,String>();
+        props.put("a", "5");
+        cf.update(props);
+
+        Configuration cf2 = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory3", null);
+        Hashtable<String,String> props2 = new Hashtable<String,String>();
+        props2.put("a", "7");
+        cf2.update(props2);
+
+        ServiceReference sr = getServiceRef(Foo.class, "(&(key=foo3)(a=5))");
+        ServiceReference sr2 = getServiceRef(Foo.class, "(&(key=foo3)(a=7))");
+
+        Foo foo = (Foo) context().getService(sr);
+        assertNotNull(foo);
+        assertEquals(5, foo.getA());
+        assertEquals("default", foo.getB());
+        assertEquals("5", sr.getProperty("a"));
+        assertNull(sr.getProperty("b"));
+
+        Foo foo2 = (Foo) context().getService(sr2);
+        assertNotNull(foo2);
+        assertEquals(7, foo2.getA());
+        assertEquals("default", foo2.getB());
+        assertEquals("7", sr2.getProperty("a"));
+        assertNull(sr2.getProperty("b"));
+
+        props = new Hashtable<String,String>();
+        props.put("a", "5");
+        props.put("b", "foo");
+        cf.update(props);
+
+        props2 = new Hashtable<String,String>();
+        props2.put("a", "7");
+        props2.put("b", "foo2");
+        cf2.update(props2);
+
+        // Update after creation
+        Thread.sleep(500);
+        assertEquals(5, foo.getA());
+        assertEquals("foo", foo.getB());
+
+        // Update of service properties
+        assertEquals("5", sr.getProperty("a"));
+        assertEquals("foo", sr.getProperty("b"));
+
+        // 2a Update after creation
+        assertEquals(7, foo2.getA());
+        assertEquals("foo2", foo2.getB());
+
+        // 2b Update of service properties
+        assertEquals("7", sr2.getProperty("a"));
+        assertEquals("foo2", sr2.getProperty("b"));
+        cf.delete();
+        cf2.delete();
+    }
+
+  @SuppressWarnings("rawtypes")
+@Test
+  public void testCreateAndUpdateUsingUpdateMethod() throws Exception {
+    Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory4", null);
+    Hashtable<String, String> props = new Hashtable<String, String>();
+    props.put("a", "5");
+    cf.update(props);
+
+    Configuration cf2 = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory4", null);
+    Hashtable<String, String> props2 = new Hashtable<String, String>();
+    props2.put("a", "7");
+    cf2.update(props2);
+
+    ServiceReference sr = getServiceRef(Foo.class, "(&(key=foo4)(a=5))");
+    ServiceReference sr2 = getServiceRef(Foo.class, "(&(key=foo4)(a=7))");
+
+    Foo foo = (Foo) context().getService(sr);
+    assertNotNull(foo);
+    assertEquals(5, foo.getA());
+    assertEquals("default", foo.getB());
+    assertEquals("5", sr.getProperty("a"));
+    assertNull(sr.getProperty("b"));
+
+    Foo foo2 = (Foo) context().getService(sr2);
+    assertNotNull(foo2);
+    assertEquals(7, foo2.getA());
+    assertEquals("default", foo2.getB());
+    assertEquals("7", sr2.getProperty("a"));
+    assertNull(sr2.getProperty("b"));
+
+    props = new Hashtable<String, String>();
+    props.put("a", "5");
+    props.put("b", "foo");
+    cf.update(props);
+
+    props2 = new Hashtable<String, String>();
+    props2.put("a", "7");
+    props2.put("b", "foo2");
+    cf2.update(props2);
+
+    // Update after creation
+    Thread.sleep(500);
+    assertEquals(5, foo.getA());
+    assertEquals("foo", foo.getB());
+
+    // Update of service properties
+    assertEquals("5", sr.getProperty("a"));
+    assertEquals("foo", sr.getProperty("b"));
+
+    // 2a Update after creation
+    assertEquals(7, foo2.getA());
+    assertEquals("foo2", foo2.getB());
+
+    // 2b Update of service properties
+    assertEquals("7", sr2.getProperty("a"));
+    assertEquals("foo2", sr2.getProperty("b"));
+  }
+  
+  @Test
+  public void testFactoryCreation() throws Exception {
+    Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory5", null);
+    Hashtable<String, String> props = new Hashtable<String, String>();
+    props.put("a", "5");
+    cf.update(props);
+
+    @SuppressWarnings("rawtypes")
+	ServiceReference sr = getServiceRef(Foo.class, "(key=foo5)");
+    Foo foo = (Foo) context().getService(sr);
+    assertNotNull(foo);
+    assertEquals(5, foo.getA());
+    assertEquals("default", foo.getB());
+    assertEquals("5", sr.getProperty("a"));
+    assertNull(sr.getProperty("b"));
+
+    props = new Hashtable<String, String>();
+    props.put("a", "5");
+    props.put("b", "foo");
+    cf.update(props);
+    Thread.sleep(500);
+
+    // No update of bean after creation
+    assertEquals(5, foo.getA());
+    assertEquals("default", foo.getB());
+
+    // Only initial update of service properties
+    assertEquals("5", sr.getProperty("a"));
+    assertNull(sr.getProperty("b"));
+  }
+  
+	@SuppressWarnings("rawtypes")
+	private ServiceReference getServiceRef(Class serviceInterface, String filter) throws InvalidSyntaxException {
+		int tries = 0;
+		do {
+			 ServiceReference[] srAr = bundleContext.getServiceReferences(serviceInterface.getName(), filter);
+			 if (srAr != null && srAr.length > 0) {
+				 return (ServiceReference) srAr[0];
+			 }
+			 tries ++;
+			 try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+				// Ignore
+			}
+		}  while (tries < 100);
+      throw new RuntimeException("Could not find service " + serviceInterface.getName() + ", " + filter);
+	}
+}