> I think you confuse the validity of a service with its life cycle. > There is -never- a guarantee that a service is valid. Just think of a > service that is backed by a remote connection, if the cable is cut > there is no way you can call that service anymore even though it is > still registered. There are an infinite amount of cases where a > service can fail before it is unregistered. I don't know if these terms have special OSGi semantics, but "valid" means to me that the service is there, i.e. the service object exists and -- more important -- can be used, i.e. it's legal (with respect to the service object's life cycle) to invoke its methods. (Of course, method invocations can fail as e.g. Input/OutputStreams indicate by the IOExceptions they throw -- special case RemoteException -- or PreparedStatement.executeUpdate indicates by an SQLException; these cases have obviously to be handled somehow in my code when I invoke a service's method).
What irritates me with a lot of OSGi code examples is the check for "null" when getting the service. Of course, if I cannot be sure that it "is there" and "can be used" (i.e. if I cannot be sure that it is "valid") then I have to check (that's the case in the usual OSGi examples, because they start the "example's service" without considering the availability of the service(s) they rely on -- just as in your snippet http://www.aqute.biz/Snippets/Tracker, that I referred to, where you simply fall back to System.err if the log service is not available). In general, if my service relies on another service and I want to invoke one of that service's methods, I don't want to write code that first checks for and then handles the special case that the service isn't valid (isn't there or isn't usable with respect to its life cycle). I simply want my code to run only if the service I rely on is available in the first place. (Which implies that I *don't* have to check for null when getting the service.) So, if my own code (the threads providing the service) runs only between invocations of "addingService" and "removedService" (tracking the service I rely on, as in my initial sample code), then (from my understanding) it should be unnecessary to check whether ServiceTracker.getService() returns null. Between those calls it *must* return a service object, right? (This is what I wanted to clarify.) - Michael > > The life cycle of services is designed so you can properly clean up > your own data structures when a service disappears. However, there is > NEVER a guarantee that you can still call the service. > > Kind regards, > > Peter Kriens > > > >> On 15 apr. 2016, at 10:45, Michael Lipp <m...@mnl.de >> <mailto:m...@mnl.de>> wrote: >> >> BJ Hargrave: >>> The tense of the customizer method name tells you when it is called >>> relative to when the tracking event occurred. addingService is "ing" >>> so it is in the process of being tracked and is thus before the >>> service becomes tracked. removedService is "ed" so it is past tense >>> and thus after the service is no longer tracked but it is called >>> during the service's unregistration so the service being untracked >>> is still valid at the time of the removedService call. >> The point is that the validity of the service "while being added" or >> "after having been removed" cannot be derived from the tense. Being >> notified "after the service has been removed" actually suggests to me >> that it is no longer there and therefore invalid. So I think it would >> be nice to have a clear statement about the validity (just like yours >> above) in the documentation of "addingService" and "removedService". >> Maybe it's already stated somewhere else, but I failed to find it. >> Maybe I should be able to derive it as obvious from the context, but >> I failed with that as well. (The documentation of UNREGISTERING is >> much clearer in that respect.) >> >> Thanks for the quick response and clarification. >> >> - Michael >> >>> >>> -- >>> >>> BJ Hargrave >>> Senior Technical Staff Member, IBM // office: +1 386 848 1781 >>> OSGi Fellow and CTO of the OSGi Alliance // mobile: +1 386 848 3788 >>> hargr...@us.ibm.com >>> >>> >>> >>> ----- Original message ----- >>> From: Michael Lipp <m...@mnl.de> >>> Sent by: osgi-dev-boun...@mail.osgi.org >>> To: osgi-dev@mail.osgi.org >>> Cc: >>> Subject: [osgi-dev] Clarify usage of ServiceTracker >>> Date: Wed, Apr 13, 2016 4:47 PM >>> >>> Hi, >>> >>> I'm trying to get a clear picture of the ServiceTracker. I've >>> looked at some examples >>> (e.g. http://www.aqute.biz/Snippets/Tracker), but they all seem >>> rather complicated. I'm especially interested in knowing when I >>> can assume a service object to exist. >>> >>> It is clear to me from the specification that a service object >>> is available (different from null) when the default >>> implementation of addingService returns. So to avoid constantly >>> calling myTracker.getService() (and check for null) whenever I >>> want to invoke a method of the service object, I can derive my >>> own ServiceTracker by overriding addingService (using the >>> LogService as an example): >>> >>> @Override >>> public LogService addingService(ServiceReference<LogService> >>> reference) { >>> myLogService = super.addingService(reference); >>> // Start the thread(s) that refer to (use) myLogService >>> return myLogService; >>> } >>> >>> ... and use myLogService until the service becomes unavailable >>> (invalid). >>> >>> It is less clear to me how to know when the service becomes >>> unavailable. The specification says: >>> >>> removedService(ServiceReference,T) - Called whenever a >>> tracked service is removed from the >>> ServiceTracker object. >>> >>> IMHO "is removed" is a bit unspecific (before/after?). However, >>> I found in the Apache Felix implementation (which isn't a >>> specification, of course) that removedService is invoked while >>> handling the UNREGISTERING event: >>> >>> UNREGISTERING - A service object is in the process of being >>> unregistered. This event is synchro- >>> nously delivered before the service object has completed >>> unregistering. That is, during the deliv- >>> ery of this event, the service object is still valid. >>> >>> So I should be on the safe side if I also override removedService: >>> >>> @Override >>> public void removedService(ServiceReference<LogService> >>> reference, >>> LogService service) { >>> // Interrupt and join the thread(s) that refer to (use) >>> myLogService >>> myLogService = null; >>> super.removedService(reference, service); >>> } >>> >>> Doing it this way, using myLogService in the thread(s) started >>> in addingService and stopped in in removeService should be safe, >>> right? >>> >>> - Michael >>> >>> _______________________________________________ >>> 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 <mailto: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