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 <[email protected]> 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 <[email protected] <mailto:[email protected]>>
>>> 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
>>>> [email protected] <mailto:[email protected]>
>>>>
>>>>
>>>> ----- Original message -----
>>>> From: Michael Lipp <mailto:[email protected]><[email protected]> <mailto:[email protected]>
>>>> Sent by:
>>>> <mailto:[email protected]>[email protected]
>>>> <mailto:[email protected]>
>>>> To: <mailto:[email protected]>[email protected]
>>>> <mailto:[email protected]>
>>>> 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
>>>> [email protected] <mailto:[email protected]>
>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>>>
>>>>
>>>> _______________________________________________
>>>> OSGi Developer Mail List
>>>> [email protected] <mailto:[email protected]>
>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> [email protected] <mailto:[email protected]>
>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>
>>
>> _______________________________________________
>> OSGi Developer Mail List
>> [email protected] <mailto:[email protected]>
>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
> _______________________________________________
> OSGi Developer Mail List
> [email protected] <mailto:[email protected]>
> https://mail.osgi.org/mailman/listinfo/osgi-dev
> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev