Important Notice

This blog has been moved! Visit the new location at https://medium.com/@arunpatidar26/list/aem-dbc5a3e4df7c.

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