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]

Reply via email to