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 <[email protected]> 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 <[email protected]> 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: [email protected]
For additional commands, e-mail: [email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Reply via email to