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