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 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]
>>>
>>>
>>>
>