Hi,
I’ve done some testing:
1) I’m able to retrieve the properties
2) I’m not able to retrieve the value
Here is my accept method:
@Override
public <S> TransformedServiceReference<S> accept(DependencyModel
dependency, BundleContext context, TransformedServiceReference<S> ref) {
ConfigurationHandlerDescription h = (ConfigurationHandlerDescription)
dependency.getComponentInstance().getInstanceDescription()
.getHandlerDescription("org.apache.felix.ipojo:properties");
if (h == null) {
return null;
}
PropertyDescription description = h.getPropertyByName(“extenders");
if (description == null) {
return null;
}
System.out.println(description.getValue() + " / " + Arrays.toString(
(String[]) description.getCurrentValue()));
return ref;
}
I’ve added the getCurrentValue() to PropertyDescription to retrieve the current
property value (gonna commit this ASAP).
(full code here: https://gist.github.com/cescoffier/7705901)
Clement
On 28 nov. 2013, at 15:06, Bengt Rodehav <[email protected]> wrote:
> Thanks!
>
>
> 2013/11/28 Clement Escoffier <[email protected]>
>
>>
>> On 28 nov. 2013, at 14:36, Bengt Rodehav <[email protected]> wrote:
>>
>>> Hello Clement,
>>>
>>> I changed to the following line:
>>>
>>> PropertyDescription[] propDescs =
>>> configHandlerDescription.getProperties();
>>>
>>> But I still get an NPE. Have you tried to call these methods from within
>> an
>>> interceptor?
>>
>> Not this method, but I did something pretty similar. Will investigate to
>> see why you get an NPE.
>>
>> Clement
>>
>>>
>>> /Bengt
>>>
>>>
>>> 2013/11/28 Clement Escoffier <[email protected]>
>>>
>>>>
>>>> On 28 nov. 2013, at 12:17, Bengt Rodehav <[email protected]> wrote:
>>>>
>>>>> Hello again Clement!
>>>>>
>>>>> I was away on business yesterday which is why I'm late replying.
>>>>>
>>>>> I've come a bit further now but still have problems accessing my
>>>>> component's "extenders" property. Here is what my code looks like now:
>>>>>
>>>>> * public List<ServiceReference> getServiceReferences(DependencyModel
>>>>> theDependencyModel,*
>>>>> * List<ServiceReference> theMatching) {*
>>>>>
>>>>> * ComponentInstance instance =
>>>>> theDependencyModel.getComponentInstance();*
>>>>> * InstanceDescription instanceDescription =
>>>>> instance.getInstanceDescription();*
>>>>> * ComponentTypeDescription componentTypeDescription =
>>>>> instanceDescription.getComponentDescription();*
>>>>> * String factoryName =
>>>>> componentTypeDescription.getFactory().getFactoryName();*
>>>>>
>>>>> * if (FACTORY_NAME.equals(factoryName)) {*
>>>>> * System.out.println("Found a GenericService2");*
>>>>> * ConfigurationHandlerDescription configHandlerDescription =
>>>>> (ConfigurationHandlerDescription) instanceDescription*
>>>>> *
>> .getHandlerDescription("org.apache.felix.ipojo.properties");*
>>>>> * int state = instanceDescription.getState();*
>>>>> * System.out.println("State: " + state);*
>>>>> * if(ComponentInstance.VALID == instanceDescription.getState()) {*
>>>>> * PropertyDescription propDesc =
>>>>> configHandlerDescription.getPropertyByName("extenders"); // NPE*
>>>>> * if(propDesc != null) {*
>>>>> * String extenders = propDesc.getValue();*
>>>>> * System.out.println("Extenders: " + extenders);*
>>>>> * }*
>>>>> * else {*
>>>>> * System.out.println("Extenders is null");*
>>>>> * }*
>>>>> * }*
>>>>> * }*
>>>>>
>>>>> I check the factory name to determine if this is a component that I
>>>> should
>>>>> intercept. Presently I wait until the component is valid but I'm not
>> sure
>>>>> if I can wait since my interceptor has to kick in before that.
>> Presently
>>>> I
>>>>> get a null pointer exception when I try to retrieve my property. Do you
>>>>> have any idea why? It doesn't seem possible to retrieve properties at
>>>> this
>>>>> pont.
>>>>
>>>> Did you try to inter ate over the set of properties and see what are
>> they ?
>>>>
>>>>>
>>>>> I also noticed that the method PropertyDescription.getValue() always
>>>>> returns a String. In my case the underlying object is an array of
>> String
>>>>> (String[]). Is it possible to get the value in the correct type?
>>>>
>>>> Yes, there is a getObjectValue(BundleContext context) method, but you
>> need
>>>> to give a bundle context object used if it needs to load classes.
>>>>
>>>> Clement
>>>>
>>>>>
>>>>> /Bengt
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2013/11/27 Clement Escoffier <[email protected]>
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On 26 nov. 2013, at 16:00, Bengt Rodehav <[email protected]> wrote:
>>>>>>
>>>>>>> I'm getting a bit closer regarding the interceptors. Still two
>> problems
>>>>>> for
>>>>>>> me:
>>>>>>>
>>>>>>> a) I still don't understand how to get hold of my intercepted
>> instance
>>>>>> from
>>>>>>> within my interceptor. I get a reference to a DependencyModel from
>>>> which
>>>>>> I
>>>>>>> can get a ComponentInstance. But how do I go from there to my
>>>> ComponentA
>>>>>>> class. I need to access the property "extenders" in order for my
>>>>>>> interceptor to do its job.
>>>>>>>
>>>>>>
>>>>>> It depends how how is managed the extender property, let’s imagine
>> it’s
>>>> a
>>>>>> @Property. In this case, from the Dependency Model, you can retrieve
>> the
>>>>>> component instance. From the instance, you have access to the
>>>> introspection
>>>>>> layer (getInstanceDescription()), which let you analyze the iPOJO
>>>> container.
>>>>>>
>>>>>> To be a bit more clear, let’s see some code:
>>>>>>
>>>>>> //First retrieve the configuration handler description from the
>> instance
>>>>>> container:
>>>>>> ConfigurationHandlerDescription description =
>>>>>> (ConfigurationHandlerDescription)
>>>>>>
>>>>
>> model.getComponentInstance().getInstanceDescription().getHandlerDescription("org.apache.felix.ipojo.properties”);
>>>>>> // Find the extenders property
>>>>>> String extenders =
>>>> description.getPropertyByName("extenders").getValue();
>>>>>> // You have your value !
>>>>>>
>>>>>>> b) Also, when the property "extenders" is changed, I need to force
>> the
>>>>>>> interceptor to recalculate the dependencies. How can I accomplish
>> that?
>>>>>>
>>>>>> It also depends on how this reconfiguration happen. Let’s say that the
>>>>>> instance is reconfigured from the configuration admin or iPOJO
>>>>>> reconfiguration abilities. In these case being notified is quite
>>>> simple, as
>>>>>> you can register a ConfigurationListener on the
>>>>>> ConfigurationHandlerDescription object:
>>>>>>
>>>>>> description.addListener(new ConfigurationListener() {
>>>>>> public void configurationChanged(ComponentInstance instance,
>>>>>> Map<String, Object> configuration) {
>>>>>> // The extender property may have been modified
>>>>>> }
>>>>>> });
>>>>>>
>>>>>> Don’t forget to unregister the listener when the interceptor is
>>>> unplugged
>>>>>> from the instance.
>>>>>>
>>>>>>>
>>>>>>> Getting deeper into iPojo than I've been before…
>>>>>>
>>>>>> It’s just the beginning…. (contributions are welcome if you see some
>>>>>> dark(er) area)
>>>>>>
>>>>>>>
>>>>>>> /Bengt
>>>>>>>
>>>>>>>
>>>>>>> 2013/11/26 Bengt Rodehav <[email protected]>
>>>>>>>
>>>>>>>> Thanks Clement!
>>>>>>>>
>>>>>>>>
>>>>>>>> 2013/11/26 Clement Escoffier <[email protected]>
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> On 25 nov. 2013, at 20:19, Bengt Rodehav <[email protected]>
>> wrote:
>>>>>>>>>
>>>>>>>>>> Hello Clement and as always thanks for your detailed answer!
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> You’re welcome.
>>>>>>>>>
>>>>>>>>>> It does seem a bit complicated to "require" an interceptor.
>> Perhaps
>>>> an
>>>>>>>>>> easier way of doing this might be possible in the future.
>>>>>>>>>
>>>>>>>>> I think it would be a good addition. Thinking about it.
>>>>>>>>>
>>>>>>>>>> Anyway, I'm not
>>>>>>>>>> exactly sure that I understood what you meant. Just to clarify:
>>>>>>>>>>
>>>>>>>>>> My Component A (the component to be intercepted) has the following
>>>>>> code:
>>>>>>>>>>
>>>>>>>>>> @Property(name = "extenders", mandatory = false)
>>>>>>>>>> private String[] mExtenderIds;
>>>>>>>>>>
>>>>>>>>>> @Requires(optional = true, id = "extenders")
>>>>>>>>>> private IExtender[] mExtenders;
>>>>>>>>>>
>>>>>>>>>> Do you mean that I should put a filter on the @Requires with
>>>>>>>>> id="extenders"
>>>>>>>>>> (the intercepted = true) so that it can only be satisfied if my
>>>>>>>>> interceptor
>>>>>>>>>> has added that property?
>>>>>>>>>
>>>>>>>>> Exactly.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> But how do I then handle the situation where my Component A does
>> not
>>>>>>>>>> require any extenders? In that case I was planning on setting the
>>>>>>>>>> dependency to optional to make my instance valid without any
>>>>>> extenders.
>>>>>>>>>>
>>>>>>>>>> Or, perhaps I could first set the @Requires to mandatory (with the
>>>>>>>>> filter):
>>>>>>>>>>
>>>>>>>>>> @Requires(optional = false, id = "extenders",
>>>>>>>>> filter="(intercepted=true)")
>>>>>>>>>> private IExtender[] mExtenders;
>>>>>>>>>>
>>>>>>>>>> Then, if my interceptor sees that the instance does not require
>> any
>>>>>>>>>> extenders it can set the dependency to become optional. This way I
>>>>>> both
>>>>>>>>>> require the interceptor (via the filter) and I ensure that the
>> only
>>>>>> way
>>>>>>>>> to
>>>>>>>>>> allow the instance to be valid without the dependency is if the
>>>>>>>>> interceptor
>>>>>>>>>> has explicitly set the dependency to optional.
>>>>>>>>>
>>>>>>>>> That would work. You can change the optionality status of the
>>>>>> dependency
>>>>>>>>> from the dependency model you get in the interceptor.
>>>>>>>>>
>>>>>>>>> Regards,
>>>>>>>>>
>>>>>>>>> Clement
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> /Bengt
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 2013/11/25 Clement Escoffier <[email protected]>
>>>>>>>>>>
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 25 nov. 2013, at 11:04, Bengt Rodehav <[email protected]>
>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> I've started to investigate using iPojo interceptors. I'm using
>>>>>> iPojo
>>>>>>>>>>>> version 1.11.0. I want to accomplish the following:
>>>>>>>>>>>>
>>>>>>>>>>>> Component A can be "extended" by specifying a list of (required)
>>>>>>>>>>>> "extenders" (actually their id's), like this:
>>>>>>>>>>>>
>>>>>>>>>>>> @Property(name = "extenders", mandatory = false)
>>>>>>>>>>>> private String[] mExtenderIds;
>>>>>>>>>>>>
>>>>>>>>>>>> @Requires(optional = true, id = "extenders")
>>>>>>>>>>>> private IExtender[] mExtenders;
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The property is optional but if any extenderId's are listed then
>>>> the
>>>>>>>>>>>> @Requires should require that IExtender's with the corresponding
>>>>>>>>>>> extenderId
>>>>>>>>>>>> is started.
>>>>>>>>>>>>
>>>>>>>>>>>> The IExtender interface contains the following method:
>>>>>>>>>>>>
>>>>>>>>>>>> public String getExtenderId();
>>>>>>>>>>>>
>>>>>>>>>>>> Thus, every extender has an extenderId and if that id is listed
>>>> in a
>>>>>>>>>>>> components "extender" property then the corresponding service
>>>> should
>>>>>>>>> be
>>>>>>>>>>>> required, otherwise not.
>>>>>>>>>>>>
>>>>>>>>>>>> My idea (actually Clement's idea from a previous conversation on
>>>>>> this
>>>>>>>>>>>> list). is to use a RankingInterceptor that returns an empty
>> array
>>>>>>>>> until
>>>>>>>>>>> all
>>>>>>>>>>>> required services are present.
>>>>>>>>>>>>
>>>>>>>>>>>> I think this is doable but in order for my RankingInterceptor to
>>>>>>>>> work, it
>>>>>>>>>>>> must have access to the component's "extenders" property. It
>> would
>>>>>>>>> then
>>>>>>>>>>> go
>>>>>>>>>>>> through all the services implementing the IExtender interface
>> and
>>>> if
>>>>>>>>>>> there
>>>>>>>>>>>> are extenders corresponding to the required extenderId's it
>> would
>>>>>>>>> return
>>>>>>>>>>>> all of those, otherwise it would return an empty list. Also, if
>> a
>>>>>>>>> list of
>>>>>>>>>>>> extenderId's was specified, then the service dependency is set
>> to
>>>>>>>>>>>> mandatory, otherwise to optional.
>>>>>>>>>>>>
>>>>>>>>>>>> My problem is how to gain access to the configuration property
>>>> (the
>>>>>>>>>>>> "extenders" property) of my component from the interceptor. How
>>>> can
>>>>>> I
>>>>>>>>> do
>>>>>>>>>>>> this?
>>>>>>>>>>>
>>>>>>>>>>> When the interceptor is hooked to a dependency, it receives the
>>>>>>>>> dependency
>>>>>>>>>>> model object. From this object you can retrieve the component
>>>>>> instance
>>>>>>>>> and
>>>>>>>>>>> get the introspection metadata.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Another question I have is how to make sure that the interceptor
>>>> is
>>>>>>>>>>> active.
>>>>>>>>>>>> If the interceptor is not active then my component could become
>>>>>>>>>>> erroneously
>>>>>>>>>>>> valid. Would it be feasible to have a mandatory dependency on
>> the
>>>>>>>>>>>> interceptor?
>>>>>>>>>>>
>>>>>>>>>>> Unfortunately not, at least not easily. What you can do is a
>>>>>>>>> combination
>>>>>>>>>>> between a filter and two interceptors: the ranking interceptors
>> as
>>>>>> you
>>>>>>>>> did,
>>>>>>>>>>> and a tracking interceptor. Let me explain:
>>>>>>>>>>>
>>>>>>>>>>> Let’s imagine your consumer with your service dependency. Add a
>>>>>> filter
>>>>>>>>>>> that will be resolved only if your interceptor is there,
>> something
>>>>>>>>> like:
>>>>>>>>>>> (intercepted=true).
>>>>>>>>>>> Your interceptor implement both tracking and ranking
>> interceptors.
>>>>>> When
>>>>>>>>>>> the accept method is called on your interceptor, it can
>>>> ‘transform’
>>>>>>>>> the
>>>>>>>>>>> original service reference to add the ‘intercepted’ property
>>>>>>>>>>> (ref.addProperty(“intercepted”, true);) This modified service
>>>>>> reference
>>>>>>>>>>> matches your filter. Then, do your ranking policy are we
>> discussed.
>>>>>>>>>>>
>>>>>>>>>>> This solution ensure that your dependency can only be resolved if
>>>>>> your
>>>>>>>>>>> interceptor is there. Indeed without the interceptor, the filter
>>>> does
>>>>>>>>> not
>>>>>>>>>>> match.
>>>>>>>>>>>
>>>>>>>>>>> Regards,
>>>>>>>>>>>
>>>>>>>>>>> Clement
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> /Bengt
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>> ---------------------------------------------------------------------
>>>>>>>>>>> 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]
>>>>
>>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [email protected]
>> For additional commands, e-mail: [email protected]
>>
>>