[ 
https://issues.apache.org/jira/browse/FELIX-5453?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15762703#comment-15762703
 ] 

Pierre De Rop commented on FELIX-5453:
--------------------------------------

Hi Jeroen;

So I took a look into your example. I think there is no bug per se, and your 
intuition is correct: Indeed when you remove aspect1, the ServiceRequiringX is 
not called in its swapped callback because it is still bound to the aspect2. 

However, at the point when you remove aspect1, it is the aspect2 which is 
swapped with the original service XImpl. (before your removed aspec1, aspect2 
was bound to aspect1).

If you want the aspect2 to know that is it swapped with the original service 
(if this is what you would like to achieve), then it is possible to define the 
swap callback on the aspect2 itself. For example:

{code}
Component aspect2 = manager.createAspectService(X.class, null, 200, "set", 
null, null, "swap")
                                     .setImplementation(Aspect2.class);
manager.add(aspect2);
{code}

Also, I would like to say that I noticed from your Activator that you called 
"setCallbacks(null, null, null, null)" method on the aspect components like 
this:

{code}
Component aspect2 = manager.createAspectService(X.class, null, 200)
                                                  
.setImplementation(Aspect2.class).setCallbacks(null, null, null, null);
manager.add(aspect2);
{code}

but here, the setCallbacks  method is used for lifecycle callbacks ("init", 
"start", "stop", "destroy") method.

If you need to specify "add","change","remove","swap" callbacks, then you have 
to invoke the createAspectService with the "add","change","remove","swap" 
callback signatures (see 
http://felix.apache.org/apidocs/dependencymanager/r7/org/apache/felix/dm/DependencyManager.html#createAspectService-java.lang.Class-java.lang.String-int-java.lang.String-java.lang.String-java.lang.String-java.lang.String-)

Now, if what you would like to achieve is allow the ServiceRequiringX to detect 
itself that the aspect2 is swapped with the lower ranked aspect1, then I think 
it is not directly possible using the DM api because when you create the 
service dependency, the highest ranked service is injected, and if one lower 
ranked aspect is removed, the aspect which is on top of the removed aspect will 
be the only one which will be swapped, not the ServiceRequiringX (which will 
remain bound to aspect2).

But there is a work around: if your ServiceRequiringX really need to detect 
swap events for aspects of X, then you can use the DM ServiceTracker. This 
class is the same as the osgi ServiceTracker, except that it has an open method 
which allows to detect all added/changed/removed aspects for a given service. 
So, you can then create such tracker from the ServiceRequiringX.init()  method, 
and make your ServiceRequiringX implements the 
ServiceTrackerCustomizerInterface.

I'm not sure why you would need to do this, but can you take a look at the 
attached Activator2 sample code ? I just modified your original Activator in 
order to use the DM ServiceTracker in order to detect if lower ranked aspect 
are swapped. Notice that the filter used contains "DependencyManager.ASPECT=*" 
because all DM aspects contain such property.

In the Activator2, I also configured the aspects so they are called in their 
swap callbacks. (not sure if you need this ?)

So, using the Activator2, you will see the following logs:

{code}
Add: XImpl
Swap old: XImpl, new: Aspect1
Tracker: add: Aspect1
Swap old: Aspect1, new: Aspect2
Tracker: add: Aspect2
Tracker: remove: Aspect1
Aspect2 swapped: old=Aspect1, new=XImpl
Swap old: Aspect2, new: XImpl
Tracker: remove: Aspect2
{code}

So, when the aspect1 is removed, the tracker will detect that the aspect1 is 
removed (check "Tracker: remove: Aspect1" log), and the Aspect2.swap method 
will be invoked (check "Aspect2 swapped: old=Aspect1, new=XImpl" log).

Let me know if Activator2 sample code helps ? Does it do what you are trying to 
achieve ?


> Swap callback not called when there are multiple aspects on a service and one 
> of the aspects with lower rank is removed
> -----------------------------------------------------------------------------------------------------------------------
>
>                 Key: FELIX-5453
>                 URL: https://issues.apache.org/jira/browse/FELIX-5453
>             Project: Felix
>          Issue Type: Bug
>          Components: Dependency Manager
>    Affects Versions: org.apache.felix.dependencymanager-r8
>            Reporter: Jeroen Daanen
>         Attachments: Activator.java, Activator2.java
>
>
> If you have multiple aspects on a service with interface X and one of the 
> aspects with a lower rank is removed, the service requiring service X does 
> not get the swap callback.
> See the attached Activator with example code.
> The swap method is not called when 'aspect1' is removed.
> Actual output of running the activator:
> {noformat}
> Add: XImpl
> Swap old: XImpl
> Swap new: Aspect1
> Swap old: Aspect1
> Swap new: Aspect2
> Swap old: Aspect2
> Swap new: XImpl
> {noformat}
> I can understand why swap is not called, because for ServiceRequiringX 
> Aspect1 does not get really 'swapped' (the service stays Aspect2) But is 
> there any way to find out this is happening?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to