felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bulu <b...@romandie.com>
Subject Dependency Manager: publish adapter with properties of the adapted service
Date Thu, 25 Sep 2014 06:54:27 GMT
Hello all

(sorry for asking so many questions - they come-up as I write my code)

In DM, how can you adapt a certain service and re-publish under a new 
interface using some properties of the adapted service?

Example:
interface Device{
   int getId();
}
each published with property
device.id=xxx
where xxx is the int from getId()

elsewhere, we want to adapt the Device services
mgr.add(createAdapterService(Device.class,null)
   .setImplementation(DeviceConsumerImpl.class)
   .setInterface(DeviceConsumer.class.getName(), props);

here, "props" should again contain the device.id=xxx value, but its not 
yet available, so the above cannot work.

We could inject it in the service's init method:
class DeviceConsumerImpl {
   Device d;
   public void init(Component c){
     Dictionary<String, Object> props = new Hashtable<>();
     props.put("device.id", d.getId())
     c.setInterface(DeviceConsumer.class.getName(), props);
}

but this fails with IllegalStateException (it seems you cannot publish 
(ie. setInterface) a new service while the object is being initialized).

So how should it be done?

I came up with a workaround, which is to publish the service at first 
with incomplete properties, and just update them in the init method when 
the values are present. But that seems like a hack... Is there a better way?

Thanks Philipp





On 24.09.2014 18:09, Pierre De Rop wrote:
> Hi Philipp;
>
> see my response, inlined below:
>
>
> On Wed, Sep 24, 2014 at 4:46 PM, Bulu <bulu@romandie.com> wrote:
>
>> Hello all
>>
>> If the published property of a service is based on a value in the actual
>> service object, and that value later changes, how can I update the
>> properties using DM?
>>
>> Example: You have Device objects (and the corresponding impl)
>> public interface Device{
>>    public int getRoom();
>>    public void setRoom(int i);
>> }
>>
>> Maybe you originally register the device like this
>>
>> Device d = new DeviceImpl();
>> s.setRoom(12);
>> Dictionary<String, Object> props = new Hashtable<>();
>> props.put("room", d.getRoom());
>> mgr.add(createComponent()
>>     .setImplementation(d)
>>     .setInterface(Device.class.getName(), props));
>>
>> ... later somebody else (maybe a consumer of the service...) calls
>> d.setRoom(13)
>>
>> How can I update the "room" property of the service?
>>
>> I believe I could keep the Component from start(Component c) and later use
>> its setServiceProperties() but is that clean/correct?
>>
> This is indeed possible, but alternatively, you could also declare a
> ServiceRegistration field in your implementation class, which will be
> injected once the device service has been registered.
> And later, from the setRoot(int id)  you can then use the service
> registration in order to modify or add some service properties.
>
>
>
>> like so:
>> class DeviceImpl implements Device {
>>    private Component c;
>>    private int room;
>>    public void start(Component c){
>>      this.c = c;
>>    }
>>
>>    public void setRoom(int i){
>>      room = i;
>>      c.setServiceProperties(c.getServiceProperties().put("room", i));
>>    }
>> }
>>
>> Is this correct? Is there a better method or pattern to use? Any problems
>> to expect from keeping the Component around?
>>
> if you use this pattern instead of using the ServiceRegistration, as
> described before, then yes, it would also work, except that there is a
> little mistake in the above example: the setServiceProperties takes a
> Dictionary as parameter, while the c.getServiceProperties().put("room", i)
> returns an object.
>
> Since the Component.getServiceProperties() method returns a copy of the
> actual service properties, you could then do like this:
>
> Dictionary props = component.getServiceProperties();
> props.put("room", i);
> component.setServiceProperties(props);
>
>
>> Also, what happens when the service consumer which is calling setRoom(),
>> is actually filtering on that property, so that his object gets removed
>> still while he is calling the method?
>>
> there are two cases:
>
> 1) using DM 3.2.0, if your consumer calls the device.setRoom(int id)
> method, then at the time this methods calls
> "component.setServiceProperties()", then the consumer will be synchronously
> called in it's "changed" callback if one has been defined and if the
> dependency filter on the device service is still satisfied.
>
> And if the consumer dependency filter is not satisfied anymore, then the
> consumer will be synchronously called in its stop callback (because the
> consumer is losing the device service, and the consumer component will then
> being stopped), and then the consumer "unbind(Device)" callback will be
> called (if defined).
>
> And at this point, you will then return from the intial invocation of the
> device.setRoot(int id) method.
>
> 2) using DM 4.0.0 (not yet in the trunk, only in sandbox), the same as
> above applies except if the
>   parallel Dependency Manager is enabled.
>
> Indeed, In DM 4.0.0, you can now optionally register a threadpool in the
> service registry, in order to handle all component events concurrently
> (service depenency management, and lifecycle callbacks).
> So, in this case, when you would call component.setServiceProperties(), or
> serviceRegistration.setProperties() method, you would then be
> asynchronously called in your consumer.stop / consumer.unbind(Device)
> method.
>
> regards;
> /Pierre
>
>
>
>
>> Regards Philipp
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Mime
View raw message