This article shows how to create OSGI Configuration Factory Service using OSGi R6 annotations.
public String getFileData();
}
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;
}
@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:
Configuration 2:
"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
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
https://github.com/arunpatidar02/aem63app-repo/tree/master/java/r6/factory
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 GitHubhttps://github.com/arunpatidar02/aem63app-repo/tree/master/java/r6/factory
Is there a way to target the reference with dynamic value?
ReplyDeletelike @Reference(target="(file.type=DYNAMIC_VALUE)")
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