Thanks Clement. I'll check out trunk and see how far I'll get. /Bengt
2013/11/29 Clement Escoffier <[email protected]> > Hi, > On 29 nov. 2013, at 16:21, Bengt Rodehav <[email protected]> wrote: > > > Thanks Clement! > > > > I compared our code it turns out I had a type: I had specified the > handler > > to "org.apache.felix.ipojo.properties" instead of > > "org.apache.felix.ipojo:properties".. I had a period instead of a colon. > > That explains my NPE. > > I probably did a mistake while explaining. The syntax is > namespace:handlername. > > > > > Now I can also retrieve the property. I can also call the getValue() > method > > that returns the value in "toString" format. Can't get the > getObjectValue() > > to work though. Looking forward to the new getCurrentValue() method. > > Unfortunately the getObjectValue only work for immutable properties. > > > > > Is it just the org.apache.felix.ipojo artifact I need to check out and > > build on trunk? > > The following version contains the new method: > > https://repository.apache.org/content/repositories/snapshots/org/apache/felix/org.apache.felix.ipojo/1.11.1-SNAPSHOT/org.apache.felix.ipojo-1.11.1-20131129.182110-3.jar > > Clement > > > > > /Bengt > > > > > > > > > > 2013/11/29 Clement Escoffier <[email protected]> > > > >> 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] > >>>> > >>>> > >> > >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > >

