I now tried to call only one of those methods with the following result: ONLY SELECTED
bin\karaf.bat clean ------------------- accept: intercepted onServiceArrival: 1 matching references getServiceReferences accept: intercepted bin\karaf.bat ------------- accept: intercepted configurationChanged invalidating... Invalidating selected... Done invalidating Validated getServiceReferences Invalidated ONLY MATCHING bin\karaf.bat clean ------------------- accept: intercepted onServiceArrival: 1 matching references getServiceReferences bin\karaf.bat ------------- karaf@root> accept: intercepted configurationChanged invalidating... Invalidating matching... accept: intercepted Done invalidating Validated getServiceReferences Invalidated It seems to give the same result as calling both of them. /Bengt 2014-03-03 16:36 GMT+01:00 Bengt Rodehav <[email protected]>: > I call both of them: > > public void invalidateSelectedServices() { > List<DependencyModel> list = new ArrayList<DependencyModel>(); > synchronized (this) { > list.addAll(dependencies); > } > > for (DependencyModel dep : list) { > if (isMine(dep)) { > System.out.println("Invalidating matching..."); > dep.invalidateMatchingServices(); > System.out.println("Invalidating selected..."); > dep.invalidateSelectedServices(); > System.out.println("Done invalidating"); > } > } > } > > @Override > synchronized public void configurationChanged(ComponentInstance theArg0, > Map<String, Object> theArg1) { > System.out.println("configurationChanged invalidating..."); > invalidateSelectedServices(); > } > > I think I used to only call invalidateSelectedServices() but then I had > the opposite problem. Since the accept() method wasn't called, the > intercepted property was not set to true. Also, if I only call > invalidateMatchingServices(), the service references are not recalculated. > It is important that both my accept() method and my getServiceReferences() > method are called. > > Sounds like this might be an issue now that you mention it. How are the > invalidateXYZ() methods supposed to work? > > /Bengt > > > 2014-03-03 16:19 GMT+01:00 Clement Escoffier <[email protected]> > : > > >> On 3 mars 2014, at 16:09, Bengt Rodehav <[email protected]> wrote: >> >> > I now added logging to the following methods: >> > >> > - onServiceArrival >> > - onServiceDeparture >> > - onServiceModified >> > >> > I tried starting both with a clean start and then without clean. I got >> the >> > following results: >> > >> > *bin\karaf.bat clean* >> > accept: intercepted >> > onServiceArrival: 1 matching references >> > getServiceReferences >> > accept: intercepted >> > >> > *bin\karaf.bat* >> > accept: intercepted >> > configurationChanged invalidating... >> > Invalidating matching... >> > accept: intercepted >> > Invalidating selected... >> > Done invalidating >> > Validated >> > getServiceReferences >> > Invalidated >> > >> > As you can see the instance never becomes valid on a clean start. Then >> > again, no configuration changes are detected on a clean start. It seems >> to >> > be when I detect a configuration change and manually invalidate the >> > dependencies that the problem appears. >> > >> > Does this give you any clue? >> >> Which method are you calling ? invalidateMatchingServices, or >> invalidateSelectedServices(), anyway it narrows the location of the bug to >> a small amount of code: >> >> public void invalidateMatchingServices() { >> ChangeSet changeset; >> try { >> m_dependency.acquireWriteLockIfNotHeld(); >> m_matchingReferences.clear(); >> changeset = computeChangesInMatchingServices(); >> } finally { >> m_dependency.releaseWriteLockIfHeld(); >> } >> m_dependency.onChange(changeset); >> } >> >> public void invalidateSelectedServices() { >> ChangeSet changeset; >> try { >> m_dependency.acquireWriteLockIfNotHeld(); >> ServiceReference oldBest = getFirstService(); >> List<ServiceReference> beforeRanking = getSelectedServices(); >> m_selectedReferences.clear(); >> final List<ServiceReference> allServices = >> getMatchingServices(); >> List<ServiceReference> references = Collections.emptyList(); >> if (!allServices.isEmpty()) { >> references = >> m_rankingInterceptor.getServiceReferences(m_dependency, allServices); >> } >> RankingResult result = computeDifferences(beforeRanking, >> references); >> m_selectedReferences = result.selected; >> changeset = new ChangeSet(getSelectedServices(), >> result.departures, result.arrivals, oldBest, >> getFirstService(), null, null); >> } finally { >> m_dependency.releaseWriteLockIfHeld(); >> } >> >> m_dependency.onChange(changeset); >> } >> >> > >> > /Bengt >> > >> > >> > >> > >> > >> > >> > >> > >> > >> > 2014-03-03 15:53 GMT+01:00 Bengt Rodehav <[email protected]>: >> > >> >> OK - I now understand what you mean. It seems that the design is >> supposed >> >> to do what I expected then. We think alike :-) >> >> >> >> I'll add some more tracing as you suggested and then get back to you. >> >> >> >> /Bengt >> >> >> >> >> >> 2014-03-03 15:46 GMT+01:00 Clement Escoffier < >> [email protected]> >> >> : >> >> >> >> >> >>> On 3 mars 2014, at 15:18, Bengt Rodehav <[email protected]> wrote: >> >>> >> >>>> Hi Clement, >> >>>> >> >>>> Yes, I use the filter to make sure that the instance does not become >> >>> valid >> >>>> until it has been intercepted - that part seems to work. However, in >> my >> >>>> case, the instance become valid AFTER my accept() method has been >> called >> >>>> but BEFORE my getServiceReferences() method has been called. This is >> >>>> causing my problems. >> >>>> >> >>>> I'm a little curious regarding your wording: >> >>>> >> >>>> "A (mandatory) dependency becomes valid only if the selected service >> >>> set is >> >>>> not empty. In other words, all your interceptors should have been >> called >> >>>> before deciding to set the dependency state to valid." >> >>>> >> >>>> I don't see how the first sentence has anything to do with the second >> >>>> sentence. >> >>> >> >>> This is how iPOJO resolves services. It first considers the services >> from >> >>> the service registry (called base service set). This set is processed >> by >> >>> tracking interceptor (such as LDAP filter...) to get a matching >> service set. >> >>> Then, a ranking interceptor is called to sort the set, and to get the >> >>> selected service set. A mandatory service dependency cannot be valid >> if >> >>> this last set is empty (in theory). That means that both accept and >> >>> getServiceReferences should have been called to determine whether or >> not >> >>> the dependency is valid. The accept method is called to build the >> matching >> >>> service set, while getServiceReferences is called to retrieve the >> selected >> >>> service set. >> >>> >> >>>> >> >>>> I have a dependency declared as follows: >> >>>> >> >>>> @Requires(optional = false, id = "extenders", filter = >> >>>> "(intercepted=true)") >> >>>> private IRouteExtender[] mExtenders; >> >>>> >> >>>> Thus it is mandatory. Also, there are services of type IRouteExtender >> >>>> registered so that part is resolved. But until the accept() method >> has >> >>> been >> >>>> called the "(intercepted=true)" part is not satisfied. When my >> accept() >> >>>> method has been called the "(intercepted=true)" part becomes >> satisfied >> >>> and >> >>>> my instance becomes valid right away instead of waiting for the >> result >> >>> of >> >>>> the getServiceReferences() method. This is the problem because in my >> >>>> getServiceReferences() method I evalutate the matching dependencies >> (by >> >>>> looking at a property) and determine that they are not valid. I >> >>> therefore >> >>>> return an empty set of matching service references and the instance >> now >> >>>> becomes invalid. >> >>>> >> >>>> I do not think it should be possible to validate an instance "in the >> >>> midst >> >>>> of intercepting" as is the case for me. I must be completely done >> >>>> intercepting first. >> >>> >> >>> That should not be the case. Definitely a bug.... The dependency state >> >>> should not be re-evaluated before having notified the ranking >> interceptor. >> >>> >> >>> So far, you are implementing only getServiceReferences, can you >> implement >> >>> and add traces in onServiceArrival ? >> >>> >> >>> Clement >> >>> >> >>> >> >>> >> >>>> >> >>>> /Bengt >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> >> >>>> 2014-03-03 13:51 GMT+01:00 Clement Escoffier < >> >>> [email protected]>: >> >>>> >> >>>>> Hi, >> >>>>> >> >>>>> On 3 mars 2014, at 13:14, Bengt Rodehav <[email protected]> wrote: >> >>>>> >> >>>>>> Hello again Clement! >> >>>>>> >> >>>>>> Skiing trip is now over - time to get back to the interceptors... >> >>>>>> >> >>>>>> Regarding your questions in the last post: Yes, I only add a >> property >> >>> on >> >>>>>> the chosen service reference (intercepted is set to true), I do not >> >>>>> change >> >>>>>> the filter. >> >>>>>> >> >>>>>> I have tested the theory regarding config admin / file install and >> it >> >>> is >> >>>>>> not the problem. >> >>>>>> >> >>>>>> It seems to me that there is no guarantee that both accept() and >> the >> >>>>>> getServiceReferences() are both called before an instance becomes >> >>> valid. >> >>>>> I >> >>>>>> haven't looked at the source code in detail yet but is the design >> such >> >>>>> that >> >>>>>> this is not supposed to be possible or am I requesting a new >> feature? >> >>> In >> >>>>>> other words, have I found a bug or not? >> >>>>>> >> >>>>>> Ideally I think it should work as follows: >> >>>>>> >> >>>>>> - When in "interceptor mode" the state of the instance should not >> >>> change >> >>>>>> until all the interceptors (and all callbacks of the interceptors) >> >>> have >> >>>>>> taken effect. >> >>>>>> >> >>>>>> - Initially then instance should not become valid until all the >> >>>>>> interceptors (and all callbacks of the interceptors) have taken >> >>> effect. >> >>>>>> >> >>>>>> With "interceptor mode" I mean that something has triggered iPojo >> to >> >>>>> begin >> >>>>>> calling the registered interceptors. >> >>>>>> >> >>>>>> Not sure if this is in accordance with your design. How is it >> >>> supposed to >> >>>>>> work? >> >>>>> >> >>>>> >> >>>>> It might be a bug and a new feature. >> >>>>> >> >>>>> I designed interceptors to be highly dynamic, so can come and leave >> at >> >>>>> anytime, and without having the components aware of them. That's why >> >>>>> service dependencies do not know which interceptors handle them. >> >>>>> Unfortunately, this design has some trade-off / drawbacks. If your >> >>> instance >> >>>>> starts before the interceptors, it might be valid for a little >> amount >> >>> of >> >>>>> time, until the interceptors handle the dependency. However in your >> >>> case >> >>>>> you have a filter on the dependency that should avoid this case. >> >>>>> >> >>>>> If you still have this filter, it is definitely a bug. A >> (mandatory) >> >>>>> dependency becomes valid only if the selected service set is not >> >>> empty. In >> >>>>> other words, all your interceptors should have been called before >> >>> deciding >> >>>>> to set the dependency state to valid. >> >>>>> >> >>>>> About the feature, I start thinking that the independence between >> the >> >>>>> interceptor and the dependencies may be problematic. For instance, >> I've >> >>>>> another use case where they implement a new handler (an extension of >> >>> the >> >>>>> dependency handler) to ensure the availability of one specific >> >>> interceptor. >> >>>>> The dependency is invalid until the interceptor arrives. >> >>>>> >> >>>>> Clement >> >>>>> >> >>>>>> >> >>>>>> /Bengt >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> >> >>>>>> 2014-02-24 8:17 GMT+01:00 Clement Escoffier < >> >>> [email protected] >> >>>>>> : >> >>>>>> >> >>>>>>> >> >>>>>>> On 21 févr. 2014, at 14:15, Bengt Rodehav <[email protected]> >> wrote: >> >>>>>>> >> >>>>>>>> Hello Clement, >> >>>>>>>> >> >>>>>>>> Some comments inline below. >> >>>>>>>> >> >>>>>>>> /Bengt >> >>>>>>>> >> >>>>>>>> >> >>>>>>>> >> >>>>>>>> 2014-02-21 12:53 GMT+01:00 Clement Escoffier < >> >>>>>>> [email protected]>: >> >>>>>>>> >> >>>>>>>>> Hi, >> >>>>>>>>> >> >>>>>>>>> On 20 févr. 2014, at 13:22, Bengt Rodehav <[email protected]> >> >>> wrote: >> >>>>>>>>> >> >>>>>>>>>> This is a follow up on another discussion I had with Clement on >> >>> this >> >>>>>>>>>> mailing list: >> >>>>>>>>>> >> >>>>>>>>>> >> >>>>>>>>> >> >>>>>>> >> >>>>> >> >>> >> http://apache-felix.18485.x6.nabble.com/Using-iPojo-interceptors-tt5006168.html#a5006276 >> >>>>>>>>>> >> >>>>>>>>>> I'm now trying to get the interceptor solution into production. >> >>>>>>>>>> >> >>>>>>>>>> Remember that I have to invalidate my instances when their >> >>>>>>> configuration >> >>>>>>>>> is >> >>>>>>>>>> changed. This is because I need to re-evalutate the >> dependencies >> >>> for >> >>>>>>> the >> >>>>>>>>>> instance. >> >>>>>>>>>> >> >>>>>>>>>> Originally, I only called the invalidateSelectedServices() >> method >> >>> on >> >>>>>>> the >> >>>>>>>>>> DependencyModel. This worked mostly but not when starting a >> fresh >> >>>>>>>>> container >> >>>>>>>>>> (I use Karaf and start it with "bin\karaf.bat clean"). My >> instance >> >>>>> then >> >>>>>>>>>> first becomes valid but then becomes invalid. I think this is >> >>> because >> >>>>>>> of >> >>>>>>>>>> the ordering. The accept() method had not been called prior to >> >>>>>>>>>> the getServiceReferences() method. The dependency is therefore >> not >> >>>>> set >> >>>>>>> to >> >>>>>>>>>> "intercepted=true" which makes it invalid. >> >>>>>>>>> >> >>>>>>>>> the filter is updated by the interceptor. (just want to be sure >> I >> >>>>>>>>> understand). In that case, if the interceptor arrives after the >> >>>>> instance >> >>>>>>>>> creation, the filter will be set when the interceptor arrives. >> >>>>>>>>> >> >>>>>>>> >> >>>>>>>> Yes, my interceptor sets intercepted to true on the dependency >> which >> >>>>>>> makes >> >>>>>>>> sure that the filter match. >> >>>>>>> >> >>>>>>> So the filter is not modified by the interceptor, it just add a >> new >> >>>>>>> property on the chosen service reference to match the filter. >> >>>>>>> >> >>>>>>>> >> >>>>>>>> >> >>>>>>>> >> >>>>>>>>> >> >>>>>>>>>> >> >>>>>>>>>> Replacing the call to invalidateSelectedServices() with a >> call to >> >>>>>>>>>> invalidateMatchingServices() seems to do the trick. However, >> >>> there is >> >>>>>>> one >> >>>>>>>>>> small glitch that I would like to fix. >> >>>>>>>>>> >> >>>>>>>>>> If I have a configuration that should not be valid (e g I >> >>> specified >> >>>>> an >> >>>>>>>>>> extender id that is not present) the instance should never be >> >>> valid. >> >>>>>>> But, >> >>>>>>>>>> when starting Karaf (both with "bin\karaf.bat" and >> "bin\karaf.bat >> >>>>>>>>> clean"), >> >>>>>>>>>> the instance becomes valid before it becomes invalid. It does >> end >> >>> up >> >>>>> in >> >>>>>>>>> the >> >>>>>>>>>> right state (invalid in this case) but for a short period of >> time >> >>> it >> >>>>> is >> >>>>>>>>>> valid which will cause a lot of things to happen in my code >> that >> >>> then >> >>>>>>>>> must >> >>>>>>>>>> be reversed when it becomes invalid. >> >>>>>>>>>> >> >>>>>>>>>> I logged the sequence of events and it seems that the accept() >> >>> method >> >>>>>>> is >> >>>>>>>>>> called first. I will then set "intercepted=true". This >> immediately >> >>>>>>> makes >> >>>>>>>>>> the instance valid. Shortly thereafter getServiceReferences() >> is >> >>>>>>> called. >> >>>>>>>>> I >> >>>>>>>>>> will then re-calculate the dependency requirements and when I >> >>> later >> >>>>>>>>>> invalidate the dependencies the instance will become valid. >> >>>>>>>>>> >> >>>>>>>>>> So, there is a short time frame where the instance is valid >> >>> although >> >>>>> it >> >>>>>>>>>> shouldn't be. How can I fix that? >> >>>>>>>>> >> >>>>>>>>> This looks like a bug, as the dependency can be valid only if >> the >> >>> set >> >>>>> of >> >>>>>>>>> selected services is not empty. From what you say, it looks like >> >>> the >> >>>>>>>>> dependency is valid because the set of matching services is not >> >>> empty. >> >>>>>>>>> >> >>>>>>>> >> >>>>>>>> Is there anything I can do to investigate this? Is it possible >> for >> >>> you >> >>>>> to >> >>>>>>>> take a look if there is indeed a "gap" where this can happen? >> >>>>>>> >> >>>>>>> My first guess would be in the ServiceReferenceManager >> coordinating >> >>> the >> >>>>>>> interceptors. >> >>>>>>> >> >>>>>>>> >> >>>>>>>> I think that things are a little complicated since I also listen >> on >> >>>>>>>> configuration changes. I need to recalculate the matching >> services >> >>> when >> >>>>>>> the >> >>>>>>>> configuration of the intercepted instance changes. When starting >> the >> >>>>>>>> container (Karaf), I get more than one configuration change and >> thus >> >>>>> the >> >>>>>>>> dependencies are invalidated more than once. What if the sequence >> >>> were: >> >>>>>>>> >> >>>>>>>> 1. Configuration change causing the dependencies to become >> >>> invalidated >> >>>>>>>> 2. Accept. Will set intercepted to true >> >>>>>>>> 3. getServiceReferences which will calculate the required >> >>> dependencies >> >>>>>>>> 4. Configuration change again causing the dependencies to become >> >>>>>>> invalidated >> >>>>>>>> 5. Accept. Will set intercepted to true >> >>>>>>>> 6. getServiceReferences which will calculate the required >> >>> dependencies >> >>>>>>>> >> >>>>>>>> Not sure if there is any point in which an instance could become >> >>> valid >> >>>>>>> when >> >>>>>>>> it shouldn't. >> >>>>>>>> >> >>>>>>>> I will also try to see if the problem could be the configuration >> >>>>> admin. I >> >>>>>>>> use file install for my configuration. I have a feeling that the >> >>> first >> >>>>>>>> configuration being pushed is a default configuration and not the >> >>> one >> >>>>>>> from >> >>>>>>>> the configuration file. Then that might explain it. >> >>>>>>>> >> >>>>>>> >> >>>>>>> Oh, that's an interesting hint. That's definitely possible. >> >>>>>>> >> >>>>>>> Enjoy your vacations, mine are over.... >> >>>>>>> >> >>>>>>> >> >>>>>>> Regards, >> >>>>>>> >> >>>>>>> Clement >> >>>>>>> >> >>>>>>>> >> >>>>>>>>>> >> >>>>>>>>>> From my point of view this is similar to a transaction. I do >> not >> >>> want >> >>>>>>> the >> >>>>>>>>>> instance to become valid before I have done all my >> "intercepting" >> >>>>> which >> >>>>>>>>> is >> >>>>>>>>>> after BOTH the accept() method AND the getServiceReferences() >> >>> method >> >>>>>>> have >> >>>>>>>>>> been called. >> >>>>>>>>> >> >>>>>>>>> In theory, it is how it should work... >> >>>>>>>>> >> >>>>>>>>>> >> >>>>>>>>>> BTW I also noted that the "dependencies" member in >> >>>>>>>>>> the DefaultDependencyInterceptor class (I extend the >> >>>>>>>>>> DefaultServiceRankingInterceptor class) seems to contain >> >>> duplicates >> >>>>> of >> >>>>>>> my >> >>>>>>>>>> dependency. The same DependencyModel instance occurs twice in >> the >> >>>>> List. >> >>>>>>>>>> Seems like a bug to me. Perhaps the List should be a Set? >> >>>>>>>>> >> >>>>>>>>> Definitely, could you open an issue ? >> >>>>>>>>> >> >>>>>>>>> Clement >> >>>>>>>>> >> >>>>>>>>>> >> >>>>>>>>>> /Bengt >> >>>>>>>>> >> >>>>>>>>> >> >>>>>>>>> >> >>> --------------------------------------------------------------------- >> >>>>>>>>> To unsubscribe, e-mail: [email protected] >> >>>>>>>>> For additional commands, e-mail: [email protected] >> >>>>>>> >> >>>>>>> >> >>>>> >> >>>>> >> >>>>> >> --------------------------------------------------------------------- >> >>>>> To unsubscribe, e-mail: [email protected] >> >>>>> For additional commands, e-mail: [email protected] >> >>>>> >> >>>>> >> >>> >> >>> >> >>> --------------------------------------------------------------------- >> >>> To unsubscribe, e-mail: [email protected] >> >>> For additional commands, e-mail: [email protected] >> >>> >> >>> >> >> >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [email protected] >> For additional commands, e-mail: [email protected] >> >> >

