Aha, I had completely missed that. Thanks for the info, I now have a lot of @Controller's that need to be changed to @ServiceController's.
/Bengt 2013/10/3 Clement Escoffier <[email protected]> > Hi, > > On 3 oct. 2013, at 12:09, Bengt Rodehav <[email protected]> wrote: > > > 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? > > > > You should use the service controller and set the default value to false. > Thus, the service exposed by your instance will not be published until you > assign the field to true. When, I say default value, I mean: > > @ServiceControler(value=false) > private boolean m_controller; > > > The @ServiceController controls the exposition of the services exposed by > your instance without changing the instance state. The @Controller impacts > the instance's state. It should only be used when something 'terrible' > happen, and the instance cannot become valid again without a restart or a > reconfiguration. > > Regards, > > Clement > > > > > > /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] > >> > >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > >

