I've now tested against trunk and I've come a lot further. Another question for you...
I need access to my service object in the getServiceReferences() method. It is possible if I have the BundleContext. In the accept() method I get the BundleContext passed as a parameter but not in the getServiceReferences(). Why is that? How can I access the service object from the ServiceReference in the getServiceReferences() method? Perhaps the signature of the getServiceReferences() method should be changed to take a BundleContext as well? /Bengt 2013/11/29 Bengt Rodehav <[email protected]> > 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] >> >> >

