Yes OK. This is what I'm currently doing.First publish the adapter as EventHandler and later (in init() ) set the properties correctly.
I just thought it wasn't clean. Thanks again Philipp
On 25.09.2014 11:34, Pierre De Rop wrote:
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 <[email protected]> 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 <[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 newinterface using some properties of the adapted service? When you define an adapter (DeviceConsumer), the service properties ofthe 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'tneed 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 allIf 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 aServiceRegistration 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, asdescribed 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]
--------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]

