I just discovered https://issues.apache.org/jira/browse/FELIX-4129 which is
fixed. Sounds like this would make it possible to change the optionality
dynamically like I needed - is that right?

This fix plus interceptors then seem like the perfect fit for me.

/Bengt


2013/10/3 Bengt Rodehav <[email protected]>

> 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]
>>
>>
>

Reply via email to