Re: [osgi-dev] Double config

2018-08-25 Thread David Leangen via osgi-dev

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

2018-08-25 Thread Alain Picard via osgi-dev
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