felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Pierre De Rop <pierre.de...@gmail.com>
Subject Re: Dependency Manager: publish adapter with properties of the adapted service
Date Thu, 25 Sep 2014 09:34:48 GMT
Ah ok; I understand.

>From your adapter (DeviceConsumerImpl), in the init() method, just call
component.setServiceProperties()  instead of component.setInterface method.

Something like this:

class DeviceConsumerImpl implements DeviceConsumer
    void init(Component c) {
        DependencyManager dm = c.getDependencyManager();

        // add a dynamic dependency on the DeviceParameter ...
        c.add(dm.createServiceDependency()
            .setService(DeviceParameter.class, "(device.id=" +
device.getDeviceId() + ")")
            .setRequired(true));

        // Now, set our adapter service properties, which will be appended
to the republished
        // adapted service properties !

        Hashtable props = new Hashtable();
        props.put(EventConstants.EVENT_TOPIC, "my/device/events");
        props.put(EventConstants.EVENT_FILTER,"(device.id=" +
device.getDeviceId() + ")");
        c.setServiceProperties(props);
    }

This works with DM 4.0.0, but should also work with DM 3.2.0 (but I did not
have time to test).

regards
/Pierre

On Thu, Sep 25, 2014 at 11:07 AM, Bulu <bulu@romandie.com> wrote:

> Hello Pierre
>
> My example was too simple, I would like to republish the adapter with
> values from the adapted service, but under new keys.
>
> Specifically, the new interface is EventHandler and I want to build the
> EVENT_FILTER from the adapted service (ie. Device) properties..
>
>
> Dictionary props =new  Hashtable();
> props.put(EventConstants.EVENT_TOPIC, "my/device/events");
>
> props.put(EventConstants.EVENT_FILTER,"(device.id=xxx)"); // xxx comes
> from the Device instance
>
> mgr.add(createAdapterService(Device.class,null)
>   .setImplementation(DeviceConsumerImpl.class)
>   .setInterface(EventHandler.class.getName(), props);
>
> Philipp
>
>
> On 25.09.2014 10:53, Pierre De Rop wrote:
>
>> Hi Philipp;
>>
>> On Thu, Sep 25, 2014 at 8:54 AM, Bulu <bulu@romandie.com> wrote:
>>
>>  Hello all
>>>
>>> (sorry for asking so many questions - they come-up as I write my code)
>>>
>>>  no problem at all :-)
>>
>>
>>  In DM, how can you adapt a certain service and re-publish under a new
>>> interface using some properties of the adapted service?
>>>
>>>  When you define an adapter (DeviceConsumer), the service properties of
>> the
>> adapted service (Device) are automatically propagated to the new adapter
>> interface (DeviceConsumer).
>>
>>
>>
>>
>>
>>  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.
>>>
>>>  since the adapted service properties are propagated, I think you don't
>> need
>> to pass a props to the setInterface method; just pass "null":
>>
>> mgr.add(createAdapterService(Device.class,null)
>>    .setImplementation(DeviceConsumerImpl.class)
>>    .setInterface(DeviceConsumer.class.getName(), null);
>>
>> If you pass some properties to the setInterface method, those properties
>> will be appended to the service properties of the original adapted
>> service,
>> so in the end the re-publised service will contain the adapted service
>> properties + the properties you pass to the setInterface methods.
>>
>>
>>
>> does this help ?
>>
>>
>> regards
>> /Pierre
>>
>>
>>  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
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message