Hi Ray, So a component property type is unable to override any super type methods (i.e. the Java compiler blocks this).
You therefore can’t define any of the following methods: annotationType getClass hashCode clone toString notify notifyAll wait Unfortunately the DS spec is silent about what these methods should do. I think there needs to be a spec clarification saying that these methods must behave as defined by Object/Annotation. Note that this would be a breaking behaviour change for Felix SCR as currently the result of calling toString is access to the “toString” configuration property. Technically the change is also breaking for the spec, but I think we can get away with it because the component property type can’t directly define toString(). Another option is just to set a toString property in your component properties. That will make sure that your configuration always returns a String for toString, although you shouldn’t rely on the value as the toString behaviour might change! Tim > On 21 Nov 2016, at 02:40, Raymond Auge <raymond.a...@liferay.com> wrote: > > You're right Tim, it's not a bug per say and that's why I never called it > that. But it sure is damned annoying. And frankly I don't have a really good > solution either. > > However it seems the only truly logical thing the proxy could do is blacklist > any of the Object non-arg methods. To be honest, I think that wouldn't be a > bad thing... if someone really uses any of these "properties" I'd question > their motives: > > getClass > hashCode > clone > toString > notify > notifyAll > wait > > They could get a better result with any kind of prefix. > > - Ray > > On Sun, Nov 20, 2016 at 6:56 PM, Tim Ward <tim.w...@paremus.com > <mailto:tim.w...@paremus.com>> wrote: > I'm not sure how you would fix this. Isn't toString a valid (and unset) > property of a configuration? > > Sounds like a working, albeit non-obviously so, implementation to me. > > Regards, > > Tim > > Sent from my iPhone > > On 20 Nov 2016, at 23:43, Raymond Auge <raymond.a...@liferay.com > <mailto:raymond.a...@liferay.com>> wrote: > >> 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 >> <mailto: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$ServiceObjectsImpl@b55 >> a5b0, deactivated=false, hashCode=2085697315 <tel: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 <mailto:osgi-dev@mail.osgi.org> >> https://mail.osgi.org/mailman/listinfo/osgi-dev >> <https://mail.osgi.org/mailman/listinfo/osgi-dev> >> _______________________________________________ >> OSGi Developer Mail List >> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >> https://mail.osgi.org/mailman/listinfo/osgi-dev >> <https://mail.osgi.org/mailman/listinfo/osgi-dev> > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> > https://mail.osgi.org/mailman/listinfo/osgi-dev > <https://mail.osgi.org/mailman/listinfo/osgi-dev> > > > > -- > Raymond Augé <http://www.liferay.com/web/raymond.auge/profile> (@rotty3000) > Senior Software Architect Liferay, Inc. <http://www.liferay.com/> (@Liferay) > Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org/> (@OSGiAlliance) > _______________________________________________ > 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