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?
Solved! Go to Solution.
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...
Views
Replies
Total Likes
Hi,
Please check the HELPX article link shared by Scott.
Here you can manage multiple instances of Same AEM OSGi service.
Thanks,
Ratna Kumar.
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
One more point is that I'd like to do this purely in code without touching the OSGi console.
Views
Replies
Total Likes
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...
Views
Replies
Total Likes
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/
Views
Replies
Total Likes
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?
Views
Replies
Total Likes
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)
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.
Views
Replies
Total Likes
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.
Views
Replies
Total Likes
Hi,
Was looking for similar query and found this, hope any new reader finds it useful:
N.B: Its always recommended to use single interface for single service implementation.
// incase of injecting the service inside a sling model
@OSGIService (filter="(component.name=menuServiceImpl2)")
MenuService menuService;
// incase of injecting the service inside any other backend module like services/servlets
@Reference (target="(component.name=menuServiceImpl2)")
MenuService menuService;
The reason why in your case its always taking the first service and not the second is because during the bundle activation the first service is getting a service ID that is lower than second service ID, so if you always want to trigger the menuServiceImpl2:
@component(...)
@ServiceRanking(1000)
public class menuServiceImpl2 implements MenuService {
}
@Component(...)
@ServiceRanking(1001)
public class menuServiceImpl2 implements MenuService {
}
The higher Service ranking will have higher priority (unlike the service id where lower is higher priority)
Hope this helps!
Views
Replies
Total Likes
Views
Likes
Replies