Re: [osgi-dev] Fabric Service Model - Request for feedback
Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference https://github.com/tdiesler/jbosgi/blob/master/testsuite/functional/src/main/java/org/jboss/test/osgi/ds/support/ValidatingReference.java to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org mailto:he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this ... The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org
Re: [osgi-dev] Fabric Service Model - Request for feedback
Christian, I consider that to be one of the worst features of Blueprint, so I would be very opposed to adding it to DS! Regards Neil On Fri, Sep 13, 2013 at 11:17 AM, Christian Schneider ch...@die-schneider.net wrote: I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org
Re: [osgi-dev] Fabric Service Model - Request for feedback
Honestly the proxy creation alone created a lot of issues in the past :-) So what would be your preferred solution for blueprint? Stopping the blueprint context when a required service goes away? I originally thought it would do that before I learned how it actually works. I am not sure why blueprint works this way but I would be interested to learn why and what would be better behaviours. Perhaps the blueprint standard can be enhanced. Christian On 13.09.2013 12:19, Neil Bartlett wrote: Christian, I consider that to be one of the worst features of Blueprint, so I would be very opposed to adding it to DS! Regards Neil On Fri, Sep 13, 2013 at 11:17 AM, Christian Schneider ch...@die-schneider.net wrote: I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and
Re: [osgi-dev] Fabric Service Model - Request for feedback
Amen! Christian, I consider that to be one of the worst features of Blueprint, so I would be very opposed to adding it to DS! Regards Neil On Fri, Sep 13, 2013 at 11:17 AM, Christian Schneider ch...@die-schneider.net wrote: I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this ⦠The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi
Re: [osgi-dev] Fabric Service Model - Request for feedback
Christian, I don't think this behaviour can be removed from Blueprint, it's too intrinsic to the design. Anyway, I'm not suggesting making any changes to Blueprint. Neil On Fri, Sep 13, 2013 at 11:28 AM, Christian Schneider ch...@die-schneider.net wrote: Honestly the proxy creation alone created a lot of issues in the past :-) So what would be your preferred solution for blueprint? Stopping the blueprint context when a required service goes away? I originally thought it would do that before I learned how it actually works. I am not sure why blueprint works this way but I would be interested to learn why and what would be better behaviours. Perhaps the blueprint standard can be enhanced. Christian On 13.09.2013 12:19, Neil Bartlett wrote: Christian, I consider that to be one of the worst features of Blueprint, so I would be very opposed to adding it to DS! Regards Neil On Fri, Sep 13, 2013 at 11:17 AM, Christian Schneider ch...@die-schneider.net wrote: I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are
Re: [osgi-dev] Fabric Service Model - Request for feedback
Blueprint service damping is one of those things that will always polarise opinions. I think it has it's uses - we use it in WebSphere to limit application churn during update. Damping enables updates to downstream bundles to be isolated to those bundles, with a brief pause in throughput instead of Service Unavailable. That said, there's always the potential for a window, so you do still have to handle these conditions. Damping isn't for everyone, though, and this is why Blueprint 1.1 is being worked [1], to cover non-damping behaviour. [1] https://github.com/osgi/design/tree/master/rfcs/rfc0184 Regards, Graham. Graham Charters PhD CEng MBCS CITP STSM, WebSphere OSGi Applications Lead Architect, Master Inventor IBM United Kingdom Limited, MP 146, Hursley Park, Winchester, SO21 2JN, UK Tel: (Ext) +44-1962-816527 (Int) 7-246527 (Fax) +44-1962-816527 Internet: chart...@uk.ibm.com From: Balázs Zsoldos balazs.zsol...@everit.biz To: OSGi Developer Mail List osgi-dev@mail.osgi.org, Date: 13/09/2013 11:45 Subject:Re: [osgi-dev] Fabric Service Model - Request for feedback Sent by:osgi-dev-boun...@mail.osgi.org Hi Neil, I have been thinking a lot about this behavior. It causes new issues but it also gives more possibility in design. Therefore I would not say that is a bad feature in Blueprint. As many developers come from Spring they will choose blueprint instead of DS at the first time. In case you are against blueprint features I think it would be nice to somehow express your thoughts about them in a way that OSGi juniors will understand as well. What I found out till now: Pros: Service wirings are much more lazy so in case of a service change not the whole application has to restart but only that crumb. This makes deployment time much faster so development will be better In case of a live server bundle updates can be done in lower levels in the way that users will not notice it at all. Imagine that there is 3 secs timeout and version upgrades are done in one sec. The front-end users will notice only that there is one sec lag but they will not see any downtime. Cons: There can be issues. For example if someone wants to use a lazy wired service in the destroy method or the service uses a lazy wired service the bundle will not be able to stop but will wait for timeout. We experienced this with activiti-blueprint usage. The DataSource service went away before activiti started to stop. Activiti wanted to write records into the database but no DataSource was available but only a proxy reference. The logic is a bit strange and brings issues but also brings many new possibilities. What a developer has to concider is that if he/she uses this technique very strict rules has to be kept: No service usage in the stopping functions Developers should not think in OSGi services when special libraries are implemented as use like Loggers. Logger should be instantiated as it was before, just by calling a constructor or a factory class. Till now I think that the possibility I call lazy service wiring gives so much improvement that I can live with the rules and issues it raises. Those were my thoughts but I would be very interested in others opinion. Maybe there is a better solution to speed up version upgrades and the possibility to replace only one service in a big application without affecting the other parts. Regards, Balazs On Fri, Sep 13, 2013 at 12:19 PM, Neil Bartlett njbartl...@gmail.com wrote: Christian, I consider that to be one of the worst features of Blueprint, so I would be very opposed to adding it to DS! Regards Neil On Fri, Sep 13, 2013 at 11:17 AM, Christian Schneider ch...@die-schneider.net wrote: I think you can take a look at what aries blueprint does for these cases. They create a proxy for each injected service and switch the service if the original one goes away. If no service is available then I think it waits for some time for a new one to come and throws an exception if a time out happens. Perhaps a similar behaviour can also be added for DS. Not sure if it matches the DS ideas though. Christian On 13.09.2013 12:10, Thomas Diesler wrote: Thank you all for your replies. We ended up with three measures #1 assert that the component is still valid on entry of every public method (AtomicBoolean set by activate/deactivate) #2 Use a ValidatingReference to hold unary references to dependent services (prevents NPE when a dependent service goes away) #3 Throw an InvalidComponentException runtime exception on #1 and #2 The idea is that access to a deactivated reference never throws NPE Access to the public API is prevented from deactivated service instances cheers --thomas On Sep 11, 2013, at 11:11 AM, Richard S. Hall he...@ungoverned.org wrote: Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts
Re: [osgi-dev] Fabric Service Model - Request for feedback
Very impressive list of enhancements. This covers almost everything I ever complained about :-) Christian On 13.09.2013 13:43, Graham Charters wrote: Blueprint service damping is one of those things that will always polarise opinions. I think it has it's uses - we use it in WebSphere to limit application churn during update. Damping enables updates to downstream bundles to be isolated to those bundles, with a brief pause in throughput instead of Service Unavailable. That said, there's always the potential for a window, so you do still have to handle these conditions. Damping isn't for everyone, though, and this is why Blueprint 1.1 is being worked [1], to cover non-damping behaviour. [1] _https://github.com/osgi/design/tree/master/rfcs/rfc0184_ Regards, Graham. -- Christian Schneider http://www.liquid-reality.de Open Source Architect http://www.talend.com ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
I know that Apache Felix iPOJO would not release references of ServiceT to A or B (if A or B are removed) when ServiceT.doStuff() is being called. Service release happen as soon as the executing Thread exits the SeviceT.doStuff() method. As when service unregistration happens, the framework calls service listeners synchronously, this behavior, some kind of freeze the dependency for a (short) time (upon the methods execution is finished). --G 2013/9/10 Thomas Diesler thomas.dies...@jboss.com The proposal is targeted for a specific project (fuse-fabric) - remote services are not involved in the consideration at the moment. The problem however seems to be general enough that I wanted to present it to this audience. I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. cheers --thomas On Sep 10, 2013, at 1:35 PM, BJ Hargrave hargr...@us.ibm.com wrote: You still have the issue that services are transient. You cannot pin a set of them for some time duration. A service can represent a remote service, access to which is subject to failure of the network or remote withdrawal of the service. But I am not totally sure I understood your proposal. -- *BJ Hargrave* Senior Technical Staff Member, IBM OSGi Fellow and CTO of the *OSGi Alliance* http://www.osgi.org/* **hargr...@us.ibm.com* hargr...@us.ibm.com office: +1 386 848 1781 mobile: +1 386 848 3788 From:Thomas Diesler thomas.dies...@jboss.com To:OSGi Developer Mail List osgi-dev@mail.osgi.org Date:2013/09/10 07:01 Subject:[osgi-dev] Fabric Service Model - Request for feedback Sent by:osgi-dev-boun...@mail.osgi.org -- Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org
Re: [osgi-dev] Fabric Service Model - Request for feedback
On Sep 10, 2013, at 6:28 PM, Neil Bartlett njbartl...@gmail.com wrote: Thomas, if you use DS idiomatically then the service reference cannot change to null during your method call. First, as Chris pointed out, static references will not change while your component is active, because as soon as the referenced services goes away your component will be deactivated. So we don't need to worry about these. How would that be when unsynchronised? A client obtains a reference to a service and makes a call on it. If these are two consecutive/unsynchronized actions, the service may have become invalid by the time the client thread enters the service method. This can be prevented when all access to DS references and public methods that use them are synchronised. For dynamic references, you do need to find a way to deal with the dynamics in a thread safe way. My preferred solution is to store the service value in an AtomicReference field. At the start of any method that uses the service, I copy the content of the AtomicReference to a local variable, using the get() method. Once in a local variable, I can check for null and then use the service. The value of the local variable cannot change while I am using it in my method. ok. You seem to be concerned about the deeper call stack, but as the caller of a service it is simply not your concern to try to enforce something about the implementation of the service you are calling. You should however be prepared for the service invocation to go wrong in unpredictable ways. Usually the best way to deal with this is simply to bubble up the exception to your own caller. ok - and possibly retry at the entry level. Note that although the Java memory model permits you to pin the service instance in memory temporarily -- i.e. by pointing a local variable at it -- that does not mean that the underlying service is still valid. As BJ points out, the service *may* be a proxy for a remote service, or it may represent some device attached to the computer that has just been ripped out. So the technique of referring to services with local vars helps to avoid the worst case of having to lock and null-check *every* time you use the service within your method, but it does NOT enforce that the underlying service is still working sensibly under the covers, and nothing you do CAN ever enforce this, so get used to it and adapt your coding style appropriately. ok - thanks Neil On Tue, Sep 10, 2013 at 3:54 PM, Thomas Diesler thomas.dies...@jboss.com wrote: Thanks Chris, could you say something about the effect on call stacks that are already in progress. In a complex graph of interdependent services you may have multiple DS injection points and that a ref is null is only the most obvious case. What about the ref not being null but being a different instance than has been used earlier in the call stack. Also the possibility of different configuration data getting associated with the same service instance. cheers --thomas On Sep 10, 2013, at 4:39 PM, chris.g...@kiffer.be wrote: I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. Services injected by DS are, as you say, non-final fields so they can change their value. This situation is not unique to DS - in principle *any* non-final field of your class could be modified at any time by any other thread which can access it, so you have to either handle this or prove that it can't happen. For example you make a copy in a (final) local variable: then you are safe from NPEs but you may be using an instance which is somehow obsolete - so you have to be aware of that. Etc.. Turning to DS, the solution can depend upon whether the absence of a dependency is a normal or an abnormal state of affairs. If it is normal then you declare the dependency as optional unary and indeed you have be aware that it can go away or be replaced at the most inconvenient moment. As you say there are a lot of callbacks: in this case you almost certainly want to write your own set/unset methods so that you can deal with synchronisation issues etc.. If OTOH you really don't want to deal with the dynamics then you declare the dependency as mandatory unary and then if it goes away, so do you. If it comes back a new instance of your component is created so there is no problem of stale references etc.. It is important that components properly handle being stopped: any subsequent service calls should be handled in a way which helps the caller realise that the service object is no longer usable. I don't think this is a problem which can be solved by adding one more layer of abstraction; rather it is a case of applying best practices and using DS idiomatically. Does this make sense? Regards Chris Gray
Re: [osgi-dev] Fabric Service Model - Request for feedback
Wise words (as usual) from Neil. I'd like to single out these sentences for printing out and hanging on the wall: as the caller of a service it is simply not your concern to try to enforce something about the implementation of the service you are calling. You should however be prepared for the service invocation to go wrong in unpredictable ways. In OSGi invoking a service looks just like any other method call (which is great), but at the same time it represents crossing a boundary. Maybe you think you know now how the service will behave, but next week someone may have the bright idea of moving the implementation to a USB dongle or The Cloud, or they switch to using a new open-source library - and your assumptions are rendered invalid. So every time you invoke another service you should be asking yourself questions like do I need a try - catch -finally here? Am I holding any locks that could cause problems?. It's interesting to know that iPOJO won't do this, but then iPOJO too is just one implementation. Just as you shouldn't rely on the known behaviour of your services, you certainly shouldn't rely on the known behaviour of a particular framework. Chris ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
Resending my reply from yesterday since my original message didn't seem to go through... Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this ... The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
[osgi-dev] Fabric Service Model - Request for feedback
Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
You still have the issue that services are transient. You cannot pin a set of them for some time duration. A service can represent a remote service, access to which is subject to failure of the network or remote withdrawal of the service. But I am not totally sure I understood your proposal. -- BJ Hargrave Senior Technical Staff Member, IBM OSGi Fellow and CTO of the OSGi Alliance hargr...@us.ibm.com office: +1 386 848 1781 mobile: +1 386 848 3788 From: Thomas Diesler thomas.dies...@jboss.com To: OSGi Developer Mail List osgi-dev@mail.osgi.org Date: 2013/09/10 07:01 Subject:[osgi-dev] Fabric Service Model - Request for feedback Sent by:osgi-dev-boun...@mail.osgi.org Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
The proposal is targeted for a specific project (fuse-fabric) - remote services are not involved in the consideration at the moment. The problem however seems to be general enough that I wanted to present it to this audience. I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. cheers --thomas On Sep 10, 2013, at 1:35 PM, BJ Hargrave hargr...@us.ibm.com wrote: You still have the issue that services are transient. You cannot pin a set of them for some time duration. A service can represent a remote service, access to which is subject to failure of the network or remote withdrawal of the service. But I am not totally sure I understood your proposal. -- BJ Hargrave Senior Technical Staff Member, IBM OSGi Fellow and CTO of the OSGi Alliance hargr...@us.ibm.com office: +1 386 848 1781 mobile: +1 386 848 3788 From:Thomas Diesler thomas.dies...@jboss.com To:OSGi Developer Mail List osgi-dev@mail.osgi.org Date:2013/09/10 07:01 Subject:[osgi-dev] Fabric Service Model - Request for feedback Sent by:osgi-dev-boun...@mail.osgi.org Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev Thomas Diesler JBoss OSGi Lead JBoss, a division of Red Hat ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
Hi Thomas, what's the core differences with DOSGi ? I know Fabric, and I work on Karaf Cellar (which also provide DOSGi). It sounds like a good addition, and it sounds more or less related to DOSGi. Regards JB On 09/10/2013 01:50 PM, Thomas Diesler wrote: The proposal is targeted for a specific project (fuse-fabric) - remote services are not involved in the consideration at the moment. The problem however seems to be general enough that I wanted to present it to this audience. I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. cheers --thomas On Sep 10, 2013, at 1:35 PM, BJ Hargrave hargr...@us.ibm.com mailto:hargr...@us.ibm.com wrote: You still have the issue that services are transient. You cannot pin a set of them for some time duration. A service can represent a remote service, access to which is subject to failure of the network or remote withdrawal of the service. But I am not totally sure I understood your proposal. -- *BJ Hargrave* Senior Technical Staff Member, IBM OSGi Fellow and CTO of the _OSGi Alliance_ http://www.osgi.org/_ __hargr...@us.ibm.com_ mailto:hargr...@us.ibm.com office: +1 386 848 1781 mobile: +1 386 848 3788 From: Thomas Diesler thomas.dies...@jboss.com mailto:thomas.dies...@jboss.com To: OSGi Developer Mail List osgi-dev@mail.osgi.org mailto:osgi-dev@mail.osgi.org Date: 2013/09/10 07:01 Subject: [osgi-dev] Fabric Service Model - Request for feedback Sent by: osgi-dev-boun...@mail.osgi.org mailto:osgi-dev-boun...@mail.osgi.org Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org mailto:osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org mailto:osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev Thomas Diesler JBoss OSGi Lead JBoss, a division of Red Hat
Re: [osgi-dev] Fabric Service Model - Request for feedback
Hi JB, please tell me more - I'm targeting local dynamic services in a single framework. What overhead would DOSGi bring to the game? cheers --thomas On Sep 10, 2013, at 1:57 PM, Jean-Baptiste Onofré j...@nanthrax.net wrote: Hi Thomas, what's the core differences with DOSGi ? I know Fabric, and I work on Karaf Cellar (which also provide DOSGi). It sounds like a good addition, and it sounds more or less related to DOSGi. Regards JB On 09/10/2013 01:50 PM, Thomas Diesler wrote: The proposal is targeted for a specific project (fuse-fabric) - remote services are not involved in the consideration at the moment. The problem however seems to be general enough that I wanted to present it to this audience. I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. cheers --thomas On Sep 10, 2013, at 1:35 PM, BJ Hargrave hargr...@us.ibm.com mailto:hargr...@us.ibm.com wrote: You still have the issue that services are transient. You cannot pin a set of them for some time duration. A service can represent a remote service, access to which is subject to failure of the network or remote withdrawal of the service. But I am not totally sure I understood your proposal. -- *BJ Hargrave* Senior Technical Staff Member, IBM OSGi Fellow and CTO of the _OSGi Alliance_ http://www.osgi.org/_ __hargr...@us.ibm.com_ mailto:hargr...@us.ibm.com office: +1 386 848 1781 mobile: +1 386 848 3788 From: Thomas Diesler thomas.dies...@jboss.com mailto:thomas.dies...@jboss.com To: OSGi Developer Mail List osgi-dev@mail.osgi.org mailto:osgi-dev@mail.osgi.org Date: 2013/09/10 07:01 Subject: [osgi-dev] Fabric Service Model - Request for feedback Sent by: osgi-dev-boun...@mail.osgi.org mailto:osgi-dev-boun...@mail.osgi.org Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this … The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org mailto:osgi
Re: [osgi-dev] Fabric Service Model - Request for feedback
I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. Services injected by DS are, as you say, non-final fields so they can change their value. This situation is not unique to DS - in principle *any* non-final field of your class could be modified at any time by any other thread which can access it, so you have to either handle this or prove that it can't happen. For example you make a copy in a (final) local variable: then you are safe from NPEs but you may be using an instance which is somehow obsolete - so you have to be aware of that. Etc.. Turning to DS, the solution can depend upon whether the absence of a dependency is a normal or an abnormal state of affairs. If it is normal then you declare the dependency as optional unary and indeed you have be aware that it can go away or be replaced at the most inconvenient moment. As you say there are a lot of callbacks: in this case you almost certainly want to write your own set/unset methods so that you can deal with synchronisation issues etc.. If OTOH you really don't want to deal with the dynamics then you declare the dependency as mandatory unary and then if it goes away, so do you. If it comes back a new instance of your component is created so there is no problem of stale references etc.. It is important that components properly handle being stopped: any subsequent service calls should be handled in a way which helps the caller realise that the service object is no longer usable. I don't think this is a problem which can be solved by adding one more layer of abstraction; rather it is a case of applying best practices and using DS idiomatically. Does this make sense? Regards Chris Gray ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
Thanks Chris, could you say something about the effect on call stacks that are already in progress. In a complex graph of interdependent services you may have multiple DS injection points and that a ref is null is only the most obvious case. What about the ref not being null but being a different instance than has been used earlier in the call stack. Also the possibility of different configuration data getting associated with the same service instance. cheers --thomas On Sep 10, 2013, at 4:39 PM, chris.g...@kiffer.be wrote: I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. Services injected by DS are, as you say, non-final fields so they can change their value. This situation is not unique to DS - in principle *any* non-final field of your class could be modified at any time by any other thread which can access it, so you have to either handle this or prove that it can't happen. For example you make a copy in a (final) local variable: then you are safe from NPEs but you may be using an instance which is somehow obsolete - so you have to be aware of that. Etc.. Turning to DS, the solution can depend upon whether the absence of a dependency is a normal or an abnormal state of affairs. If it is normal then you declare the dependency as optional unary and indeed you have be aware that it can go away or be replaced at the most inconvenient moment. As you say there are a lot of callbacks: in this case you almost certainly want to write your own set/unset methods so that you can deal with synchronisation issues etc.. If OTOH you really don't want to deal with the dynamics then you declare the dependency as mandatory unary and then if it goes away, so do you. If it comes back a new instance of your component is created so there is no problem of stale references etc.. It is important that components properly handle being stopped: any subsequent service calls should be handled in a way which helps the caller realise that the service object is no longer usable. I don't think this is a problem which can be solved by adding one more layer of abstraction; rather it is a case of applying best practices and using DS idiomatically. Does this make sense? Regards Chris Gray ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
Thomas, if you use DS idiomatically then the service reference cannot change to null during your method call. First, as Chris pointed out, static references will not change while your component is active, because as soon as the referenced services goes away your component will be deactivated. So we don't need to worry about these. For dynamic references, you do need to find a way to deal with the dynamics in a thread safe way. My preferred solution is to store the service value in an AtomicReference field. At the start of any method that uses the service, I copy the content of the AtomicReference to a local variable, using the get() method. Once in a local variable, I can check for null and then use the service. The value of the local variable cannot change while I am using it in my method. You seem to be concerned about the deeper call stack, but as the caller of a service it is simply not your concern to try to enforce something about the implementation of the service you are calling. You should however be prepared for the service invocation to go wrong in unpredictable ways. Usually the best way to deal with this is simply to bubble up the exception to your own caller. Note that although the Java memory model permits you to pin the service instance in memory temporarily -- i.e. by pointing a local variable at it -- that does not mean that the underlying service is still valid. As BJ points out, the service *may* be a proxy for a remote service, or it may represent some device attached to the computer that has just been ripped out. So the technique of referring to services with local vars helps to avoid the worst case of having to lock and null-check *every* time you use the service within your method, but it does NOT enforce that the underlying service is still working sensibly under the covers, and nothing you do CAN ever enforce this, so get used to it and adapt your coding style appropriately. Neil On Tue, Sep 10, 2013 at 3:54 PM, Thomas Diesler thomas.dies...@jboss.com wrote: Thanks Chris, could you say something about the effect on call stacks that are already in progress. In a complex graph of interdependent services you may have multiple DS injection points and that a ref is null is only the most obvious case. What about the ref not being null but being a different instance than has been used earlier in the call stack. Also the possibility of different configuration data getting associated with the same service instance. cheers --thomas On Sep 10, 2013, at 4:39 PM, chris.g...@kiffer.be wrote: I'm wondering how other folks deal with the issues of service dynamicity and configuration change in the duration of a single call to a complex graph of interconnected services. Services injected by DS are, as you say, non-final fields so they can change their value. This situation is not unique to DS - in principle *any* non-final field of your class could be modified at any time by any other thread which can access it, so you have to either handle this or prove that it can't happen. For example you make a copy in a (final) local variable: then you are safe from NPEs but you may be using an instance which is somehow obsolete - so you have to be aware of that. Etc.. Turning to DS, the solution can depend upon whether the absence of a dependency is a normal or an abnormal state of affairs. If it is normal then you declare the dependency as optional unary and indeed you have be aware that it can go away or be replaced at the most inconvenient moment. As you say there are a lot of callbacks: in this case you almost certainly want to write your own set/unset methods so that you can deal with synchronisation issues etc.. If OTOH you really don't want to deal with the dynamics then you declare the dependency as mandatory unary and then if it goes away, so do you. If it comes back a new instance of your component is created so there is no problem of stale references etc.. It is important that components properly handle being stopped: any subsequent service calls should be handled in a way which helps the caller realise that the service object is no longer usable. I don't think this is a problem which can be solved by adding one more layer of abstraction; rather it is a case of applying best practices and using DS idiomatically. Does this make sense? Regards Chris Gray ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Fabric Service Model - Request for feedback
Yes, you can do some of these sorts of things with iPOJO. First, iPOJO has the notion of a service-level service dependency as well as an implementation-level service dependency (which is the level of DS dependencies). Second, iPOJO caches services references within a service method invocation so that a thread calling a method on a service will see the same injected services until the thread exits the invoked service method. It doesn't deal with configuration locking (at least not of which I am aware). - richard On 9/10/13 06:41 , Thomas Diesler wrote: Hi Folks, in Fabric we have a service model whereby services have interdependencies, are configurable and dynamic by nature - all of which is managed in OSGi with the help of Declarative Services. To illustrate I use a simple example ServiceT { @Reference ServiceA serviceA; @Reference ServiceB serviceB; public doStuff() { // that uses serviceA serviceB } } The injection is handled by the DS framework - there are various callbacks involved. Lets assume the system is fully configured and a client makes a call on ServiceT ServiceT serviceT = getServiceT(); serviceT.doStuff(); Due to the dynamic nature of OSGi services and their respective configuration ServiceT must deal with the following possible/likely situations #1 An instance of a referenced service is not available at the point of access (i.e. serviceA is null) #2 In the context of a single call the service instance may change (i.e. call may span multiple instances of serviceA) #3 In the context of a single call the configuration of a service instance may change (i.e. serviceA is not immutable, sequential operations on A may access different configurations) In OSGi there is no notion of global lock for service/configurations nor a notion of lock of a given set of services/configurations - I cannot do lock(T, A, B); try { ServiceT serviceT = getServiceT(); serviceT.doStuff(); } finally { unlock(T, A, B); } This code is also flawed because it assumes that the caller of doStuff() is aware of the transitive set of services involved in the call and that this set will not change. As a conclusion we can say that the behaviour of doStuff() is only defined when we assume stability in service availability and their respective configuration, which happens to be true most of the time - nevertheless, there are no guarantees for defined behaviour. How about this ... The functionality of A and B and its respective configuration is decoupled from OSGi and its dynamicity A { final Map config; public doStuffInA() { } } B { final Map config; public doStuffInB() { } } ServiceA and ServiceB are providers of immutable instances of A and B respectively. There is a notion of CallContext that provides an idempotent set of instances involved in the call. CallContext { public T get(ClassT type); } This guarantees that throughout the duration of a call we always access the same instance, which itself is immutable. CallContext also takes care of instance availability and may have appropriate timeouts if a given instance type cannot be provided. It would still be the responsibility of A/B to decide wether an operation is permissible on stale configuration. Changes to the system would be non-trival and before I do any prototyping I'd like to hear what you think. cheers --thomas ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev