I am not sure what we’re discussing here? For each of your concerns/objections Declarative Services provides a very elegant answer, Service Trackers are only used in the rarest of cases.
Your concerns remind me of a programmer that refused to use a compiler and insisted on writing his Java byte codes with Vi … :-) There just happens to be a much better solution. Did you try out the OSGi enRoute Quick Start[1] to get a “feel” for DS? Kind regards, Peter Kriens [1]: http://enroute.osgi.org/qs/050-start.html <http://enroute.osgi.org/qs/050-start.html> > On 15 apr. 2016, at 11:56, Michael Lipp <m...@mnl.de> wrote: > >> >> 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 > <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 <mailto:hargr...@us.ibm.com> >>>> >>>> >>>> ----- Original message ----- >>>> From: Michael Lipp <mailto:m...@mnl.de><m...@mnl.de> <mailto:m...@mnl.de> >>>> Sent by: >>>> <mailto:osgi-dev-boun...@mail.osgi.org>osgi-dev-boun...@mail.osgi.org >>>> <mailto:osgi-dev-boun...@mail.osgi.org> >>>> To: <mailto:osgi-dev@mail.osgi.org>osgi-dev@mail.osgi.org >>>> <mailto: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>http://www.aqute.biz/Snippets/Tracker >>>> <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 <mailto:osgi-dev@mail.osgi.org> >>>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>>> <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 >>>> <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 >>> <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 >> <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 > <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