Scott, the null is a tricky side effect of the config proxy's toString
method. It's not your code. The object is indeed not null, but putting it
in a string triggers this naughty output which I admit has caused me
headaches a few times. Someone should really fix it.

- Ray

On Nov 20, 2016 2:27 PM, "Scott Lewis" <sle...@composent.com> wrote:

> I've created these two components:
>
> #1 FooImpl of IFoo service
>
> @ObjectClassDefinition(name = "Foo Configuration")
> @interface FooConfig {
>   String message() default "Hi There";
> }
> @Designate(ocd = FooConfig.class, factory=true)
> @Component(scope=ServiceScope.PROTOTYPE,configurationPolicy=
> ConfigurationPolicy.REQUIRE)
> public class FooImpl implements IFoo {
>
>     private FooConfig config;
>
>     @Override
>     public String getMessage() {
>         return config.message();
>     }
>
>     @Activate
>     void activate(FooConfig config) throws Exception {
>         System.out.println("activate instance="+this+" with
> config="+config);
>         this.config = config;
>     }
>
>     @Deactivate
>     void deactivate() {
>         System.out.println("deactivate instance="+this);
>     }
>
>     @Modified
>     void modified(FooConfig config) {
>         System.out.println("modified instance="+this+" with new
> config="+config);
>     }
> }
>
>
> // #2 The FooConsumer that creates the prototype instances
>
> @Component(immediate=true)
> public class FooConsumer {
>
>     private ComponentServiceObjects<IFoo> f;
>
>     @Reference(scope=ReferenceScope.PROTOTYPE_REQUIRED)
>     void setFooFactory(ComponentServiceObjects<IFoo> fact) {
>         this.f = fact;
>     }
>
>     void unsetFooFactory(ComponentServiceObjects<IFoo> fact) {
>         this.f = null;
>     }
>
>     private IFoo[] foos;
>
>     @Activate
>     void activate() {
>         System.out.println("activate FooConsumer="+f);
>         foos = new IFoo[5];
>         for(int i=0; i < 5; i++) {
>             foos[i] = f.getService();
>             System.out.println("foos["+i+"].getMessage() returns:
> "+foos[i].getMessage());
>         }
>     }
>
>     @Deactivate
>     void deactivate() {
>         for(int i=0; i < 5; i++) {
>             f.ungetService(foos[i]);
>         }
>     }
> }
>
> When the two bundles (IFoo API bundle and bundle containing above 2
> components) are installed and started on Karaf 4.0.5 no output is produced,
> since there is no configuration created and the consumer ref to the
> ComponentServiceFactory is set to REQUIRE. When I go to the webconsole and
> create a Foo Configuration the following output is produced:
>
> karaf@root()> activate FooConsumer=ComponentServiceObjectsImpl
> [instances=[], se
> rviceObjects=org.apache.felix.framework.BundleContextImpl$Se
> rviceObjectsImpl@b55
> a5b0, deactivated=false, hashCode=2085697315]
> activate instance=org.eclipse.ecf.test.foo.impl.FooImpl@6d86a6c2 with
> config=null
> foos[0].getMessage() returns: Hi There Scott
> activate instance=org.eclipse.ecf.test.foo.impl.FooImpl@68a1dfe8 with
> config=null
> foos[1].getMessage() returns: Hi There Scott
> activate instance=org.eclipse.ecf.test.foo.impl.FooImpl@215c5b23 with
> config=null
> foos[2].getMessage() returns: Hi There Scott
> activate instance=org.eclipse.ecf.test.foo.impl.FooImpl@7bba307e with
> config=null
> foos[3].getMessage() returns: Hi There Scott
> activate instance=org.eclipse.ecf.test.foo.impl.FooImpl@21f74969 with
> config=null
> foos[4].getMessage() returns: Hi There Scott
>
>
> I don't know why the config=null is reported...the config passed in is not
> null (via debugger), and you can see that the config.message() call returns
> Hi There Scott.  It appears to me to be a small bug (e.g. in the toString()
> impl of the proxy that's passed in)?
>
> This is fine for my use case WRT creating service instances on demand via
> the FooConsumer.   However, I would like to be able to have a distinct/new
> configuration associated with each new FooImpl, rather than a single
> FooConfig instance assigned to all of them.   Is this possible using the
> PROTOTYPE pattern, or is it necessary to use the ComponentFactory in the
> manner Tim describes to accomplish this:
>
> The way that this is done is to pass the configuration using the
> newInstance method. Effectively your pattern would be to register a
> ConfigurationListener or ManagedServiceFactory, passing the configuration
> Dictionary to the Component Factory for each Factory Configuration.
>
> Thanksinadvance,
>
> Scott
>
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to