felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bengt Rodehav <be...@rodehav.com>
Subject Re: iPOJO and dynamic requires
Date Thu, 03 Oct 2013 06:33:16 GMT
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?

/Bengt




2013/10/2 Bengt Rodehav <bengt@rodehav.com>

> 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 <clement.escoffier@gmail.com>
>
>> Sent from my iPhone
>>
>> > On 2 oct. 2013, at 20:32, Bengt Rodehav <bengt@rodehav.com> 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 <clement.escoffier@gmail.com>
>> >
>> >> 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 <bengt@rodehav.com> 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 <heavy@ungoverned.org>
>> >>>
>> >>>>
>> >>>>> 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<
>> >> users-unsubscribe@felix.apache.org>
>> >>>> For additional commands, e-mail: users-help@felix.apache.org
>> >>
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> >> For additional commands, e-mail: users-help@felix.apache.org
>> >>
>> >>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message