OK - thanks. I can skip the @Modified then. I've had some more problems unfortunately. It seems like, although I use a @Controller, which has the value "false", my instance still becomes valid. Shortly thereafter it becomes invalid again but this "false start" gives me problems.
It's like the @Controller doesn't take effect immediately but only after a while. Does this has anything to do with the fact that I set "immediate=true" on my @Component? /Bengt 2013/10/3 Clement Escoffier <[email protected]> > Hi, > > On 3 oct. 2013, at 08:33, Bengt Rodehav <[email protected]> wrote: > > > A question related to my workaround Clement. > > > > To make sure that my lifecycle controller's value is up to date I need to > > recalculate it every time the array of required services change. My code > > for this looks as follows: > > > > @Requires(optional = true, id = "processors") > > private IOrchestrationProcessor[] mProcessors; > > > > @Bind(id = "processors") > > public void bindProcessors() { > > updateAggregateValid(); > > } > > > > @Unbind(id = "processors") > > public void unbindProcessors() { > > updateAggregateValid(); > > } > > > > @Modified(id = "processors") > > public void modifiedProcessors() { > > updateAggregateValid(); > > } > > > > The function updateAggregateValid() checks if all my configurable > > requirements are met and then sets the controller value to true, > otherwise > > to false. I'm not sure when the @Modified method is called. At first it > > seemed like @Modified would be the only callback I needed but it does not > > seem to be called on "unbind". Now I suspect that it is enough with @Bind > > and @Unbind - @Modified seems unnecessary. > > > > What callbacks do I need to handle in order to react on all changes to > the > > list of required services? > > > > Bind and Unbind are covering your case. The modified callbacks mean that > one service has been updated (its service properties have changed) but it > still matches the filter. In your case, it's not relevant. > > Clement > > PS: `still matches the filter` means, from the interceptor perspective, > has been accepted by all tracking interceptors, including the filter, > managing the dependency. > > > > /Bengt > > > > > > > > > > 2013/10/2 Bengt Rodehav <[email protected]> > > > >> Thanks for your detailed response Clement! > >> > >> Sounds very interesting indeed although the fact that I can't change the > >> optionality sounds like a show stopper to me. In my case the list of > >> services to require can be >= 0. If, using config admin, I specify an > empty > >> list then the service dependency must be optional. If the list is > non-empty > >> then it must not be optional. I can't see how I can solve this using the > >> interceptors (although I haven't read the documentation yet :-)). > >> > >> /Bengt > >> > >> > >> 2013/10/2 clement escoffier <[email protected]> > >> > >>> Sent from my iPhone > >>> > >>>> On 2 oct. 2013, at 20:32, Bengt Rodehav <[email protected]> wrote: > >>>> > >>>> Interesting. Do you think it would also be possible to do an > >>> all-or-nothing > >>>> approach? E g if I want to require A and B, I could check if both A > and > >>> B > >>>> are available. If not, I would make the list empty thus making my > >>> instance > >>>> invalid? Or can I just say that the dependency is unresolved without > >>> having > >>>> to change the list? > >>> > >>> Yes you can to that. I would say that the easiest way is to implement > >>> a ranking interceptor that returns an empty array until both services > >>> are there. When both are there, it returns both. > >>> > >>> Notice that returning an empty array invalidates the dependency. For > >>> the instance it would just means : no services. > >>> > >>>> > >>>> BTW I did experiment a little with dynamically changing the > "optionable" > >>>> property of the requires dependency using the dependency manager. I > >>> never > >>>> did get that to work. It always stayed at the same value it got > through > >>> the > >>>> Requires annotation. Is that as designed or a bug? > >>>> > >>> > >>> Optionality cannot be changed, however the filter can. I can't > >>> remember the exact reason for that. > >>> > >>>> I currently did a workaround using the life cycle controller as > adviced > >>> by > >>>> Richard. Whenever anything changes that could affect the validity of > the > >>>> instance I recalculate the life cycle controller value to reflect > that. > >>> For > >>>> instance if the list of dependencies change I recalculate and check if > >>> all > >>>> my required services are in the list. If not I set the controller > value > >>> to > >>>> false. > >>>> It works but the code is not very nice and easy to understand. It'll > >>> have > >>>> to do for now. > >>>> > >>> > >>> I did like this several times and was never happy of the result, > >>> especially it may mix, in your component code, business logic with > >>> higher-level rules and data. Very hard to maintain on the long term, > >>> unclear ad likely spaghetti-like. That's one of the reason we came up > >>> with the interceptors. > >>> > >>> > >>>> Clement, is the 1.10.x version released? I'm on a pretty old version > and > >>>> should probably upgrade. Also, is there any documentation regarding > the > >>>> interceptors you mentioned? > >>> > >>> The 1.10.1 was released in june. A 1.11 is under preparation (feature > >>> complete, bug-fix complete, lacks some tests and documentation). We > >>> plan to release it next week. > >>> > >>> The good news is that it includes the interceptor documentation. > >>> > >>> Clement > >>> > >>> > >>>> /Bengt > >>>> > >>>> > >>>> 2013/10/2 Clement Escoffier <[email protected]> > >>>> > >>>>> Hi, > >>>>> > >>>>> Not sure it would meet your requirements, but in the 1.10.x, we added > >>>>> service dependency interceptors. Interceptors are external entities > >>>>> involved in the service resolution. We have 3 types on interceptors: > >>>>> > >>>>> - tracking interceptors allow hiding services, or selecting the set > of > >>>>> services seen by the service dependency (the LDAP filter is a > tracking > >>>>> interceptor) > >>>>> - ranking interceptors can change the order of the services (the > >>>>> comparator is a ranking interceptor) > >>>>> - binding interceptors can change the injected service objects (to be > >>> used > >>>>> with caution ;-)) > >>>>> > >>>>> You can, without too much effort, write an interceptor that will > shape > >>> the > >>>>> processor list as you want. > >>>>> > >>>>> As said above, interceptors are external entities. Actually, they are > >>>>> services with a special 'target' property indicating in which > >>> dependencies > >>>>> they want to be involved. So, an interceptor can select one very > >>> specific > >>>>> dependency, all dependencies of an instance, all dependencies > >>> targeting a > >>>>> specific interface… > >>>>> > >>>>> Unfortunately, there is a long overdue issue about interceptors: > >>>>> FELIX-4136 Document service dependency interceptors. > >>>>> > >>>>> Best regards, > >>>>> > >>>>> Clement > >>>>> > >>>>> > >>>>>> On 2 oct. 2013, at 15:57, Bengt Rodehav <[email protected]> wrote: > >>>>>> > >>>>>> Thanks for your reply Richard. > >>>>>> > >>>>>> I am using a lifecycle controller already to make it possible to > >>>>>> enable/disable my services via a GUI. I'll see if I can use it for > >>> this > >>>>>> purpose. > >>>>>> > >>>>>> I've also tried the following approach: Keep track of all possible > >>>>> services > >>>>>> that expose the interface I'm intererested in as follows: > >>>>>> > >>>>>> @Requires(optional = true) > >>>>>> private IOrchestrationProcessor[] mProcessors; > >>>>>> > >>>>>> In runtime, when my service is being activated (prior to creating > the > >>>>> camel > >>>>>> route) I check to see if all required processors exist, if not I > >>> throw an > >>>>>> exception. Unfortunately I have no control of in what order the > >>> services > >>>>>> will be activated so its hard to ever get the camel route created > this > >>>>> way. > >>>>>> A lot of the time a "required" services is activated a bit later. > >>>>>> > >>>>>> /Bengt > >>>>>> > >>>>>> > >>>>>> > >>>>>> 2013/10/2 Richard S. Hall <[email protected]> > >>>>>> > >>>>>>> > >>>>>>>> On 10/2/13 08:42 , Bengt Rodehav wrote: > >>>>>>>> > >>>>>>>> I'm creating a dynamic processing component using iPOJO and Camel. > >>> The > >>>>>>>> idea > >>>>>>>> is to dynamically specify (via config admin) a number of processor > >>>>> id's. > >>>>>>>> In > >>>>>>>> runtime I want to find the matching processors (the processors are > >>>>> Camel > >>>>>>>> processors published as OSGi services) with the correct id. > >>>>>>>> > >>>>>>>> E g if I specify a list of services to {A,B} (FileInstall > recognizes > >>>>> this > >>>>>>>> as a list). I want to require those services in order for my iPojo > >>>>>>>> instance > >>>>>>>> to become valid. It was much harder than I thought. > >>>>>>>> > >>>>>>>> I've tried something like: > >>>>>>>> > >>>>>>>> @Property(name = "processors", mandatory = false, value = "") > >>>>>>>> public void setProcessors(String[] theProcessorIds) { > >>>>>>>> mProcessorIds = theProcessorIds; > >>>>>>>> updateProcessorFilter(); > >>>>>>>> } > >>>>>>>> > >>>>>>>> @Requires > >>>>>>>> private Processor[] mProcessors; > >>>>>>>> > >>>>>>>> The idea is that whenever the configuration property "processors" > is > >>>>>>>> updated, I dynamically update the ldap filter on the dependency > >>>>>>>> mProcessors. I've used this approach before and it has worked when > >>>>> using a > >>>>>>>> single dependency (not an array). > >>>>>>>> > >>>>>>>> The problem is that I want to specifically require each specified > >>>>>>>> processor. In the example above, I require one processor with id=A > >>> AND > >>>>> one > >>>>>>>> processor with id=B. It's not enough with anyone of them since I > >>> want > >>>>> to > >>>>>>>> invoke them one after another. > >>>>>>>> > >>>>>>>> Can I use a filter for this? I've been thinking of something like > >>> this: > >>>>>>>> > >>>>>>>> (|(processorId=A)(processorId=**B)) > >>>>>>>> > >>>>>>>> This would match both my processors but if one of them were > missing > >>> my > >>>>>>>> instance would still become valid which I don't want. > >>>>>>> > >>>>>>> I don't think there is anyway to do what you want. This is > >>> essentially > >>>>> an > >>>>>>> "N cardinality" requirement, where you want to say that you require > >>>>>>> specifically N of something. Such requirements had been discussed > >>> over > >>>>> the > >>>>>>> years for Service Binder, Declarative Services, etc., but we could > >>> never > >>>>>>> agree on their usefulness or how to do them, so we just left it as > >>> it is > >>>>>>> now (i.e., optional, at least one...). > >>>>>>> > >>>>>>> Other than adding some sort of threshold to service dependencies, I > >>>>> don't > >>>>>>> see this happening. You could potentially create an iPOJO lifecycle > >>>>>>> controller that would keep your component invalid until it matched > >>> the > >>>>>>> required number of services (if you can get this information in the > >>>>>>> handler)...or perhaps write/extend the service dependency handler. > >>>>>>> > >>>>>>> -> richard > >>>>>>> > >>>>>>> > >>>>>>>> /Bengt > >>>>> > >>> > ------------------------------**------------------------------**--------- > >>>>>>> To unsubscribe, e-mail: users-unsubscribe@felix.**apache.org< > >>>>> [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] > >

