Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

SOLVED

How do I specify an implementation using @OSGiService

kramer2718
Level 2
Level 2

I have two implementations of an interface. Both are OSGi

public interface MenuService {

//...

}

and

@Component(

    immediate = true,

    service = MenuService.class,

    name = "menuServiceImpl1"

)

public interface MenuServiceImpl1 implements MenuService {

//...

}

and

@Component(

    immediate = true,

    service = MenuService.class,

    name = "menuServiceImpl2"

)

public interface MenuServiceImpl2 implements MenuService {

}

I can inject an implementation using OSGiService like so:

@OSGiService

private MenuService menuService;

But I always get MenuServiceImpl1 and never MenuServiceImpl2

I've tried using @Named like so:

@Named("menuServiceImpl2")

@OSGiService

private MenuService menuService;

but no luck.

Can anyone let me know how I can do this?

1 Accepted Solution
Jörg_Hoh
Correct answer by
Employee
Employee

Hi,

 

When working with services and service references I see exactly 2 usecases:

 

* You get one service reference and you don't care which implementation. You don't want to pin it to a certain service implementation because the service interface gives you the assurance about the implementation to work. If you have 2 services implementing the same interface and you want always to get the first or second service implementation, then your design is flawed. You should use different service interfaces then.

* You want to get a list of service interfaces and then iterate through all of them in order to achieve your goal. Or you do a manual filtering based on some methods of the service interface. You can get this list already sorted according to the service ranking. But in all cases you expect that there are multiple implementations around for this interface and you are ready to deal with it.

 

For your case I would definitly use different service interfaces (and it might be only a marker interface) to reliably achieve this. Of course you can pin a reference to a specific implemntation, but that's not what I would recommend especially if you have full control over the service interfaces, implementations and the classes using them.

 

Jörg

 

ps: See also this thread: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/aem-multiple-implementatio...

View solution in original post

9 Replies
Ratna_Kumar
Community Advisor
Community Advisor

Hi,

Please check the HELPX article link shared by Scott.

Adobe Experience Manager Help | Managing multiple instances of the same Adobe Experience Manager OSG...

Here you can manage multiple instances of Same AEM OSGi service.

Thanks,

Ratna Kumar.

kramer2718
Level 2
Level 2

Maybe I'm misunderstanding your reply but I don't think it answers my question. I don't have two instances of the same Java implementation. I have two different implementations. Your example uses MailServiceImpl but with two different labels allowing independent configuration. Useful, but not what I need. I have something like PopMailServiceImpl and ImapMailServiceImpl.

kramer2718
Level 2
Level 2

One more point is that I'd like to do this purely in code without touching the OSGi console.

Jörg_Hoh
Correct answer by
Employee
Employee

Hi,

 

When working with services and service references I see exactly 2 usecases:

 

* You get one service reference and you don't care which implementation. You don't want to pin it to a certain service implementation because the service interface gives you the assurance about the implementation to work. If you have 2 services implementing the same interface and you want always to get the first or second service implementation, then your design is flawed. You should use different service interfaces then.

* You want to get a list of service interfaces and then iterate through all of them in order to achieve your goal. Or you do a manual filtering based on some methods of the service interface. You can get this list already sorted according to the service ranking. But in all cases you expect that there are multiple implementations around for this interface and you are ready to deal with it.

 

For your case I would definitly use different service interfaces (and it might be only a marker interface) to reliably achieve this. Of course you can pin a reference to a specific implemntation, but that's not what I would recommend especially if you have full control over the service interfaces, implementations and the classes using them.

 

Jörg

 

ps: See also this thread: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/aem-multiple-implementatio...

View solution in original post

Arun_Patidar
Community Advisor
Community Advisor

I agree with Jorg.

If you have different service implementation go for different interface.

because name attribute in component annotation is used to defines PID not to point to implement class

name
Defines the Component name also used as the PID for the Configuration Admin Service

In Sling Model you use @Named annotation

If the field or method name doesn't exactly match the property name, @Named can be used:

E.g.

@Model(adaptables=Resource.class) public class MyModel { @Inject @Named("secondPropertyName") private String otherName; }

If you still want to do that, please go through with below:

https://techrevel.blog/tag/multiple-service-implementation/

kramer2718
Level 2
Level 2

Two interfaces is apparently the best use case in AEM. Unfortunately it is very cumbersome. Coming from a Java background, this is very annoying. AEM really ought to implement the standard Java interfaces (@Inject and @Named). How do I file a change request?

Jörg_Hoh
Employee
Employee

I don't think that this is cumbersome, but rather straight forward 🙂

As all the references are handled by the OSGI container (Apache Felix), I would recommend you to discuss that topic with the OSGI alliance.  But I am quite sure, that this discussion happened already a few times there (Spring is around for years, as well as OSGI), so maybe you start with searching the mail archives first.

Jörg

And of course you can specify a certain implementation of an interface with OSGI

@Reference (target="(component.name=name.of.the.component.as.specified.in.their.component.properties)")

MySuperService service

(https://osgi.org/specification/osgi.cmpn/7.0.0/service.component.html , chapter 112.3.10 "Target selection", check the references)

kramer2718
Level 2
Level 2

Your answer is a cop out.

You don't think it's cumbersome. I think it's cumbersome. I think most Java devs who are new to AEM would think it's cumbersome.

Yes, Apache Experience Manager uses OSGi but it also has its own annotations. Apache could make things easier but it clearly doesn't think this is a priority. That's fine. Companies have priorities, but don't say that they couldn't do it.

Jörg_Hoh
Employee
Employee

I don't think that AEM has it's own annotations when it comes to OSGI references. It uses both SCR (Apache Felix) and OSGI annotations (IIRC starting with R6) and the idea is to move to the OSGI annotations over time.

If you are interested in discussing this with actual Adobe engineers (I am not!), I would suggest to switch over to one the Apache mailing lists. I am very sure that they are open for proposals to switch to more widely used and well-known annotations.