Re: [osgi-dev] Double config
Hi, Thank you again for all the great tips in this thread. I have taken the time to review concurrency, reread all the blogs, articles, and email messages in detail, and I have done a fairly thorough review of all my code. I have identified a lot of places where there was potential for concurrency errors, and I made a lot of simplifications (mostly by eliminating any clever use of concurrency or synchronization when it wasn’t really providing any tangible benefit, and only introducing risk). I also reviewed again the DS lifecycle, as well as Trackers. I am pretty confident that my understanding of the concurrent issues, and consequently my system, are now in good shape. I think I can handle the dynamics now in a robust way (though I still don’t know how to test for it to confirm). However, I am experiencing one problem on startup still that baffles me. Take this component: @Component( factory = ..., configurationPid = ..., configurationPolicy = ConfigurationPolicy.REQUIRE) public class D implements Descriptor { @Reference( scope = ReferenceScope.PROTOTYPE_REQUIRED ) private WriterFactory.JsonWriterFactory factory; @Activate void activate( Configuration.Config config ) { ... } ... } There is really nothing more to the component that this. One static reference (which is satisfied), and a required config (which is available). The factory basically looks like this (called from a different component that instantiates this tracker): public class ComponentFactoryTracker extends ServiceTracker { public ConfinementAwareComponentFactoryTracker( BundleContext context, Filter filter ) { super( context, filter, null ); } @Override public ComponentInstance addingService( ServiceReference reference ) { final ComponentFactory cf = context.getService( reference ); final Dictionary properties = new Hashtable<>(); properties.put( ... ); final ComponentInstance instance = cf.newInstance( properties ); return instance; } @Override public void removedService( ServiceReference reference, ComponentInstance instance ) { context.ungetService( reference ); instance.dispose(); } } Fairly simple. The system starts up, and the D component (and others like it) also starts. Then bouncing happens. When things finally settle down after one bounce, D (and others like it) gets deactivated. This is where I start pulling my hair out. **Why** does it get deactivated??? —> The one and only static reference is available. Check. —> The configuration is available. Check. —> The ComponentFactory services are enabled. Check. However, despite all the prerequisites being available, D (and others) are getting deactivated. I even created an immediate service that references D (and others) to ensure that somebody was calling it. Nothing. Nada. All that I can validate is that as D (and others) get deactivated, they are unbound from this test service. If I restart any bundle that causes D to refresh, then the state of the system comes up correctly. It is only upon initial startup that this problem occurs. If I try injecting some service that potentially changes startup order, sometimes it works, but I have not yet figured out the pattern. In any case, since the prerequisites for the service are available, I don’t see why on Earth that should matter, anyway. Unless maybe there is a bug in SCR for some edge case (felix version 2.0.2). I am at a loss... Cheers, =David > On Jul 14, 2018, at 4:05, David Leangen via osgi-dev > wrote: > > > Hi Tim, > >>> What is a good way to test for robustness against this phenomenon? >> >> Again, I wish to go on record as saying that bouncing does not mean that >> anything is wrong, nor is it intrinsically bad. > > Thanks. Understood. I did not mean to imply anything about “goodness” or > “badness”, but it is good to have that on record. > > So, my question was: knowing that this happens, is there a good way to test > against it? My understanding is that currently there is not. > > > Cheers, > =David > > ___ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev ___ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev
Re: [osgi-dev] Retrieving service configuration implementation in reference method
I had an idea to try using @ComponentPropertyType and searched and found that while not specifically covered by the documentation, in the cpmn there is at least one case of a Class property in ExportedService and that the code seems to support it (ComponentPropertyTypeDataCollector#valueToProperty) So I went ahead and tried it and it works, but I'm having a more general issue with the ComponentProperty type. I am attaching the test project. The encountered issues are twofold. First what is happening is that the values supplied to the annotation are seen in the component, are seen in the reference method of the using service, but not in its activate method, where I get the default values from the annotation. Second, my service that references the one annotated with my component annotation won't start if I use a method signature that references the annotation type instead of using a map. Please enlighten me. Alain On Fri, Aug 24, 2018 at 5:52 AM Tim Ward wrote: > Right, so in this case it looks like you’re running a whiteboard, is it > possible you would be better off not using the service properties for this > filtering? For example: > > @Reference(policy=DYNAMIC, cardinality=MULTIPLE) > private final List renderers = new CopyOnWriteArrayList<>(); > > public ZKRenderer getRendererFor(Object o) { > return renderers.stream() > .filter(r -> r.supports(o)) > .collect(Collectors.maxBy((a,b) -> > a.getPriority(o).compareTo(b.getPriority(o > .orElseThrow(() -> new IllegalArgumentException("No renderer for > object " + o)); > } > > Tim > > On 24 Aug 2018, at 10:34, Alain Picard wrote: > > They represent classes, which is why I would have like to have a Class > annotation so I could do "tester=MyTester.class". instead of > "tester="com.acme.mypkg.MyTester". > > For example I have a number of components implementing a service and as > part of their property they define their "filter conditions" which are then > passed on to the 3rd party library, and there are 2 types of testers, etc: > Component(service=ZKRenderer.class, factory=ZKRenderer.CONFIG_FACTORY, > property= { ZKRenderer.CONFIG_STATIC_TEST + > "=c.c.i.tester.ReferenceTree", > ZKRenderer.CONFIG_STATIC_TEST_PRIORITY + ":Integer=9" }) > > If I move my ReferenceTree tester in the above case, no compiler would > catch it and I'm just looking for pain in the future. > > I am not sure I grasp your approach. Here clients just ask for a renderer > (an instance of the service) for some "object" that is passed in and an > appropriate and "highest ranking" one is returned. So the client is never > specifying the class string at all. Here we are providing the full class > name so it can be loaded, hence it would be much more natural to provide a > Class object. > > When we have cases where the component and reference must have to match we > do as such: > public static final String CONFIG_QUALIFIER = > OsgiConstants.SERVICE_QUALIFIER + "=ReferenceList"; //$NON-NLS-1$ > public static final String CONFIG_TARGET = "(" + CONFIG_QUALIFIER + > ")"; //$NON-NLS-1$ //$NON-NLS-2$ > > and here the component use the 1st line in its property and the reference > target uses the 2nd constant and that is not an issue. > > Alain > > > > Alain Picard > Chief Strategy Officer > Castor Technologies Inc > o:514-360-7208 > m:813-787-3424 > > pic...@castortech.com > www.castortech.com > > > On Fri, Aug 24, 2018 at 5:16 AM Tim Ward wrote: > >> Do these properties “represent” classes or are they actually classes? If >> they are just representations (which would be a good thing) then you can >> define a static string constant representing the class which is mapped >> internally to the correct class name (which can then change over time). >> Clients then filter based on the string representation which will not >> change. >> >> Tim >> >> >> On 24 Aug 2018, at 10:07, Alain Picard wrote: >> >> Tim & all, >> >> My immediate use case is that my components have some properties and some >> of those represent classes (this interfaces with 3rd party libraries, I >> would probably design it differently if I could, but it has to be >> configuration as it is used to determine if the component is a match, much >> like for target filters). Properties in the component annotation are >> String[] and that forces the specification of classes as String which is >> very bad since if the class is moved, renamed, deleted, etc, it will cause >> no error or warning and blow up later on. And since annotations only >> support compile time constants, you can't do a MyClass.class.getName() to >> even get a String. My idea was since the implementation class is part of >> the component description, if I could get a hold of it, to have a static >> method in the class to provide this "constant". >> >> How can I work around the limitations of Properties as String and Java >> compile time constants. Am I stuck to introduce a new separate annotation >> to track