Multiple Interface Implementations - AEM/CQ - OSGi
Asked Answered
M

1

6

There is an service interface HelloService, this is implemented by 2 Service implementations

HelloService Interface

public interface HelloService {
    public String getRepositoryName();
}

HelloServiceImpl1 implementation

@Service
@Component(metatype = false)
public class HelloServiceImpl1 implements HelloService {

    @Reference
    private SlingRepository repository;

    public String getRepositoryName() {
        return repository.getDescriptor(Repository.REP_NAME_DESC);
    }
}

HelloServiceimpl2 implementation

@Service
@Component(metatype = false)
public class HelloServiceImpl2 implements HelloService {

    public String getRepositoryName() {
        return "Response from HelloServiceImpl2";
    }
}

Now to use the service we use

@Reference
HelloService helloService;

Inside required method, call is made as

helloService.getRepositoryName();

I am getting response always from HelloServiceImpl1. Checked another example in AEM APIs, SlingRepository is extended by AbstractSlingRepository and AbstractSlingRepository2, how is the implementation picked internally, as while consuming we specify only @Reference SlingRepository repository;

How is this handled in AEM OSGi?


Update based on response

Checked on the syntax for this, following are observations

For using service ranking, use following with Service Implementation

@Properties({
    @Property(name = Constants.SERVICE_RANKING, intValue = 100)
})

For this no change in consumption, higher service ranking implementation is picked up, control is with provider

@Reference
HelloService helloService;

For using target filter, use following annotation to specify property

@Properties({
   @Property(name="type", value="Custom")
})

While consuming based on filter, specify target, control is with consumer

 @Reference (target="(type=Custom)")
 HelloService helloService;

If both service ranking and filter are used, filter is taking precedence.

Menace answered 22/3, 2016 at 6:13 Comment(4)
You might have a really valid reason for doing it, but consider too why it is that you want to wire in a given implementation of a service. (Just feels like it runs counter to the idea of Declarative Services)Talmud
Yes anotherdave, this was out of curiosity, question came to my mind seeing the 2 SlingRepository implementations, wanted to check how exactly it works :)Menace
Cool, just said I'd check :)Talmud
May I ask why it runs counter to the idea of Declarative Services? From your discussion I feel like I didn't get the point of DS.Damoiselle
S
7

This is related to how Declaratives Services wires a @Reference. From the specification:

If the reference has a unary cardinality and there is more than one target service for the reference, then the bound service must be the target service with the highest service ranking as specified by the service.ranking property.

If there are multiple target services with the same service ranking, then the bound service must be the target service with the highest service ranking and the lowest service id as specified by the service.id property.

ie, it depends of the "Service Ranking" of the component. If this ranking is not specified, then you can have any implementations (you usually get the oldest service). You can use a filter if you want to target a specific implementation.

Sprawl answered 22/3, 2016 at 7:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.