Thursday 11 July 2019

AEM - Create OSGI Configuration Factory Service using R6 annotations

This article shows how to create OSGI Configuration Factory Service using OSGi R6 annotations.

OSGi Factory Service

Declaring the Service interface

public interface FileService {
public String getFileData();
}

Declaring the Service Configuration

@ObjectClassDefinition(name = "File Factory Service Configuration", description = "Factory Service Configurations")
public @interface FileServiceFactoryConfig {

@AttributeDefinition(name = "filetype", description = "File Type", type = AttributeType.STRING)
String file_type() default "xml";

@AttributeDefinition(name = "size", description = "Max Size of file(KB)", type = AttributeType.LONG)
long max_size() default 10240L;

}

Service implementation

@Component(service = FileService.class, immediate = true)
@Designate(ocd = FileServiceFactoryConfig.class, factory=true)

public class FileServiceImpl implements FileService {
private String data;

@Override
public String getFileData() {
return "File data from Service:" + this.data;
}

@Activate
@Modified
protected void activate(final FileServiceFactoryConfig Config) {
this.data = PropertiesUtil.toString(Config.file_type() + " - " + Config.max_size(), "No Config found");
}
}




In the above code, the @Designate annotation has "factory=true" which makes this config as a factory.

Now Let’s create two service configurations from the factory which can be consumed by a test servlet that we are going to write next.



Configuration 1:

config 1


Configuration 2:

config 2



factory config

Sling Servlet

@Component(service = Servlet.class, property = { Constants.SERVICE_DESCRIPTION + "=Demo Servlet to access factory configs",
"sling.servlet.methods=" + HttpConstants.METHOD_GET, "sling.servlet.paths=" + "/bin/demo/facttest" })
public class FactConfigTestServlet extends SlingSafeMethodsServlet {

private static final long serialVersionUID = 2598426539166789516L;

@Reference(target="(file.type=xml)")
FileService fs1;

@Reference(target="(file.type=pdf)")
FileService fs2;


@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp)
throws ServerException, IOException {
try {
resp.setContentType("text/html");
resp.getWriter().write("<br>"+fs1.getFileData());
resp.getWriter().write("<br>"+fs2.getFileData());
resp.getWriter().close();
} catch (Exception e) {
e.printStackTrace();
}
}
}



This Reference with target parameter will directly points to the service which has the file.type as xml
@Reference(target="(file.type=xml)")
FileService fs1;

@Reference(target="(file.type=pdf)")
FileService fs2;


Call this servlet by using http://localhost:4502/bin/demo/facttest
which should return the configuration data based on target attribute of Reference annotations

Output


servlet output


Note: Without the target attribute i.e. only with a @Reference annotation the data binding will be random, more info at  https://osgi.org/javadoc/r6/cmpn/org/osgi/service/component/annotations/Reference.html

Code

Code used in this article can be found at GitHub
https://github.com/arunpatidar02/aem63app-repo/tree/master/java/r6/factory


2 comments:

  1. Is there a way to target the reference with dynamic value?
    like @Reference(target="(file.type=DYNAMIC_VALUE)")

    ReplyDelete
    Replies
    1. Hi, There is no way to do that but you can do it like https://github.com/arunpatidar02/aem63app-repo/blob/master/java/r6/factory/GreeterManagerDemo.java

      Delete

AEMaaCS - Core Component's Children Editor

If you are using core components, you should be familiar with the children-editor for Tabs, Accordion, and Carousel. These components are th...

About Me

My photo
https://www.linkedin.com/in/arunpatidar26/ https://experienceleaguecommunities.adobe.com/t5/user/viewprofilepage/user-id/6786635 https://community.adobe.com/t5/user/viewprofilepage/user-id/12372253 https://forums.adobe.com/people/Arun+Patidar