felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Karel Haeck <karel.ha...@telenet.be>
Subject Re: SCR: Issues with static reference mixed with multiple dynamic ref
Date Tue, 29 Nov 2016 07:54:03 GMT

  Roy,

  indeed your field definition is not consistent with the reference 
fieldOption REPLACE.
  DS will log an error that the field is not volatile, but will still 
activate your component as it can work with zero interfaces,
  and effectively ignores your @Reference.

  Basically you have to choose between

  @Reference(policy=ReferencePolicy.DYNAMIC)    // final implies 
fieldOption UPDATE but defaults to STATIC
  private final List<TestInterface> interfaces = new 
CopyOnWriteArrayList<>();

  @Reference // volatile implies both DYNAMIC and REPLACE
  private volatile List<TestInterface> interfaces;

  Alternatively you can add the proper field option to your reference 
annotation.

  @Reference(policy = ReferencePolicy.DYNAMIC, 
fieldOption=FieldOption.UPDATE)
    private List<TestInterface> interfaces = new 
CopyOnWriteArrayList<TestInterface>();

   Note that the ReferenceCardinality.MULTIPLE is redundant, as it 
default is derived from the field type

   regards,
   Karel



On 29/11/2016 1:12, David Jencks wrote:
> I didn’t investigate, so there might be a bug, but note that your field example has
fieldOption REPLACE, so the CopyOnWriteArrayList  you set will never actually be used, DS
will install it’s own list.  What is your evidence that the field is never set?  What happens
if you make the field final, which will result in the UPDATE fieldOption?
>
> thanks
> david jencks
>
>> On Nov 28, 2016, at 2:51 PM, Roy Teeuwen <roy@teeuwen.be> wrote:
>>
>> Hey,
>>
>> Maybe I should start making a new thread for this hehe :). Not sure if this is a
bug or if I'm just using it incorrectly.
>>
>> So created some test classes quickly.
>> Don't know when it used to work with the immediate = true, but I guess it might not
be related then, seeing as it wont work for field even with immediate true.
>> I tried the following two examples. The one with the bind method does work, the one
with field reference does not.
>>
>> # Field reference:
>>
>> @Component(service = TestAggregator.class)
>> public class TestAggregator {
>>
>>     @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.MULTIPLE)
>>     private List<TestInterface> interfaces = new CopyOnWriteArrayList<TestInterface>();
>>
>> }
>>
>> generates following xml:
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0" name="org.apache.felix.osgi.ds.TestAggregator">
>>     <implementation class="org.apache.felix.osgi.ds.TestAggregator"/>
>>     <service>
>>         <provide interface="org.apache.felix.osgi.ds.TestAggregator"/>
>>     </service>
>>     <reference name="interfaces" cardinality="0..n" policy="dynamic" interface="org.apache.felix.osgi.ds.TestInterface"
field="interfaces" field-collection-type="service"/>
>> </scr:component>
>>
>> # Method reference:
>>
>> @Component(service = TestAggregator.class)
>> public class TestAggregator {
>>
>>     @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.MULTIPLE)
>>     protected void bindTestInterface(TestInterface testInterface) {
>>         interfaces.add(testInterface);
>>     }
>>
>>     protected void unbindTestInterface(TestInterface testInterface) {
>>         interfaces.remove(testInterface);
>>     }
>> }
>>
>> generates following xml:
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <component name="org.apache.felix.osgi.ds.TestAggregator">
>>     <implementation class="org.apache.felix.osgi.ds.TestAggregator"/>
>>     <service>
>>         <provide interface="org.apache.felix.osgi.ds.TestAggregator"/>
>>     </service>
>>     <reference name="TestInterface" cardinality="0..n" policy="dynamic"
>>                interface="org.apache.felix.osgi.ds.TestInterface" bind="bindTestInterface"
>>                unbind="unbindTestInterface"/>
>> </component>
>>
>> The field reference one won't bind an existing TestInterface service, the method
reference will.
>>
>> Greets,
>> Roy
>>
>>
>>> On 29 Nov 2016, at 00:28, David Jencks <david.a.jencks@gmail.com> wrote:
>>>
>>> As everyone has said, the immediate setting isn’t going to make any difference
to the binding.  You may be able to investigate what is going on by installing gogo and looking
at the output of scr:info in various circumstances and also by installing an osgi logger and
setting the ds.loglevel=debug framework or ds configuration property and examining the resulting
voluminous log output.
>>>
>>> For the @Reference-on-field question could you show the component xml generated
by bnd (perhaps via the maven-bundle-plugin)?  Which version of bnd is in use?  Some older
versions didn’t figure out the service type very well, and I’m not sure anyone has tested
with the <> “diamond” notation (although I can’t imagine how this could mess anything
up).
>>>
>>> thanks
>>> david jencks
>>>
>>>> On Nov 28, 2016, at 12:33 PM, Roy Teeuwen <roy@teeuwen.be> wrote:
>>>>
>>>> Hey Karel,
>>>>
>>>> Sorry to go further than the original question, but seeing as my question
is related to exactly the same thing, maybe you can help me understand it better.
>>>> Using the exact same example as the in the initial post, if I don't put immediate=true,
it won't bind all of the services get created at startup or get added during the runtime.
Is there a reason why it has to be immediate = true?
>>>>
>>>> I also tried it by using the following notation, and then this it doesn't
even bind any of services:
>>>>
>>>> @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
>>>> private List<StateMachine> stateMachines = new CopyOnWriteArrayList<>();
>>>>
>>>> Greetings,
>>>> Roy
>>>>> On 28 Nov 2016, at 21:39, Karel Haeck <karel.haeck@telenet.be>
wrote:
>>>>>
>>>>> Nicolas,
>>>>>
>>>>> the spec does not specify that static references should be injected before
dynamic,
>>>>> but it does specify that references must be processed in sequence as
specified in the component xml:
>>>>>
>>>>> "When binding services, the references are processed in the order in
which they are specified in the
>>>>> component description. That is, target services from the first specified
reference are bound before
>>>>> services from the next specified reference."
>>>>>
>>>>> In addition the spec specifies how @Reference annotations are ordered:
>>>>>
>>>>> " In the generated Component Description for a component, the references
must be ordered in ascending
>>>>> lexicographical order (using String.compareTo ) of the reference names."
>>>>>
>>>>> Note that the default name is based on the field or method name. In your
case get aclService  for the static reference
>>>>> and "" (empty string) for the dynamic reference as spec states that the
add , bind or set prefix is removed.
>>>>> ( Actually if one uses Java naming conventions the event methods will
have names starting with an upper case character and precede the field references).
>>>>>
>>>>> By specifying e.g.  @Reference( name = "zStateMachine", cardinality =
ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
>>>>> the static reference should be bound first.
>>>>>
>>>>> Note that there is still a potential race condition between the add and
an activate method if present,
>>>>> or between two concurrent add() executions.
>>>>>
>>>>> regards,
>>>>> Karel
>>>>>
>>>>> On 28/11/2016 12:09, Nicolas Brasey wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I have a bind order issue with a component that has :
>>>>>>
>>>>>> 1) A static reference specified with annotation @Reference on the
private
>>>>>> field
>>>>>> 2) A dynamic multiple reference specificed with annotation on a method
>>>>>>
>>>>>> The static reference is not bound before the dynamic ones.
>>>>>>
>>>>>> The code looks like this:
>>>>>>
>>>>>> @Component(immediate = true)
>>>>>> public class MyServiceImpl implements MyService {
>>>>>>
>>>>>>   @Reference
>>>>>>   private AclService aclService;
>>>>>>
>>>>>>   @Reference(
>>>>>>           cardinality = ReferenceCardinality.MULTIPLE,
>>>>>>           policy = ReferencePolicy.DYNAMIC
>>>>>>   )
>>>>>>   public void add(StateMachine stateMachine) {
>>>>>>      ....
>>>>>>       ....
>>>>>>   }
>>>>>>
>>>>>>
>>>>>> According to the Declarative Service specifications, the static references
>>>>>> should always be injected before the activate method.
>>>>>>
>>>>>>
>>>>>> Does anyone have any idea what might be wrong ?
>>>>>>
>>>>>>
>>>>>> My env is Apache Karaf 4.0.5 with Felix SCR 2.0.2
>>>>>>
>>>>>>
>>>>>> Thanks for you help!
>>>>>>
>>>>>> Nicolas
>>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>>>> For additional commands, e-mail: users-help@felix.apache.org
>>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>>> For additional commands, e-mail: users-help@felix.apache.org
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>> For additional commands, e-mail: users-help@felix.apache.org
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Mime
View raw message