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

Reply via email to