In AEM (Adobe Experience Manager), OSGi (Open Service Gateway Initiative) services can be filtered and targeted based on specific criteria using the @Reference annotation. This allows you to specify which implementation of a service to use when multiple implementations are available in the OSGi container.
Here is an example of using filters and targets with the @Reference annotation:
1. Create an OSGi service interface
This interface defines the methods that the OSGi service will provide. For example:
package com.example.service;
public interface MyService {
String getMessage();
}
2. Create multiple implementations of the OSGi service interface
These classes provide different implementations of the methods defined in the OSGi service interface. For example:
package com.example.service.impl;
import com.example.service.MyService;
import org.osgi.service.component.annotations.Component;
@Component(service = MyService.class, property = { "message=impl1" })
public class MyServiceImpl1 implements MyService {
@Override
public String getMessage() {
return "Hello from implementation 1!";
}
}
package com.example.service.impl;
import com.example.service.MyService;
import org.osgi.service.component.annotations.Component;
@Component(service = MyService.class, property = { "message=impl2" })
public class MyServiceImpl2 implements MyService {
@Override
public String getMessage() {
return "Hello from implementation 2!";
}
}
In this example, we have created two implementations of the MyService interface, and have used the @Component annotation to mark them as OSGi components. The property attribute in the @Component annotation is used to specify a custom property that identifies each implementation.
3. Filter and target the OSGi service
To filter and target the OSGi service based on the custom properties, use the @Reference annotation with the filter and target attributes. For example:
package com.example.servlets;
import com.example.service.MyService;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(service = Servlet.class, property = { "sling.servlet.paths=/bin/my-servlet" })
public class MyServlet extends SlingSafeMethodsServlet {
@Reference(filter = "(message=impl1)", target = "(service.pid=com.example.service.impl.MyServiceImpl1)")
private MyService myService;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
response.getWriter().write(myService.getMessage());
}
}
In this example, the MyServlet class injects the MyService instance using the @Reference annotation, and filters and targets the implementation using the filter and target attributes. The filter attribute specifies the custom property used to identify the implementation, and the target attribute specifies the OSGi service PID (persistent identifier) of the implementation.
That’s it! You have now used filters and targets to specify which implementation of an OSGi service to use in AEM.