Migration from SCR annotation to OSGI Declarative Service
In this post we will see the migration of aem project from SCR annotation to OSGi Declarative service or R6 annotation.
From beginning we were using SCR annotations for backend aem development. From AEM 6.2 R6 annotation are introduced and recommended to used R6 annotation.
SCR (Service Component Runtime) Annotations : the maven-scr-plugin uses the SCR annotation from corresponding subproject at Apache felix. All annotations are in the org.apache.felix.scr.annotations package. If you want to use scr annotations in your project you have to use below plugin and dependency
But going forward we are going to use R6/DS annotation so replace these plugin and dependency with below R6 plugin and dependency
Dependency in POM
In SCR we were using annotations like @component, @service, @properties @property @slingServlet but in R6 annotation we don't need to use all these annotation we just need to use @component with collaboration of these annotation.
Migration of Component and Service
Component using SCR annotation
Migration of Servlets
Servlet with SCR annotation
Properties migration
With SCR you can Configure properties and metatype for Component/ Services using @properties & @property annotation.
With R6/DS instead of using set of @property annotations Metatype properties can be handled using the class marked with @ObjectClassDefinition R6 annotation.
How to use @ObjectClassDefintion to define metatype information
@Reference remains same in R6 and SCR or you can put it on bind methods in R6
@Reference
private SampleComponent sample;
From beginning we were using SCR annotations for backend aem development. From AEM 6.2 R6 annotation are introduced and recommended to used R6 annotation.
SCR (Service Component Runtime) Annotations : the maven-scr-plugin uses the SCR annotation from corresponding subproject at Apache felix. All annotations are in the org.apache.felix.scr.annotations package. If you want to use scr annotations in your project you have to use below plugin and dependency
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.4</version>
</plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.4</version>
</plugin>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.6.0</version>
<scope>provided</scope>
</dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.6.0</version>
<scope>provided</scope>
</dependency>
But going forward we are going to use R6/DS annotation so replace these plugin and dependency with below R6 plugin and dependency
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.2.0</version> <!-- version 3.2.0 or greater-->
</plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.2.0</version> <!-- version 3.2.0 or greater-->
</plugin>
Dependency in POM
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.metatype.annotations</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.metatype.annotations</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.annotation</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
In SCR we were using annotations like @component, @service, @properties @property @slingServlet but in R6 annotation we don't need to use all these annotation we just need to use @component with collaboration of these annotation.
Migration of Component and Service
Component using SCR annotation
package com.aem.learnaem;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
@Component(name="Sample component", immediate = true, description = "Sample component class")
@Service(SampleComponent.class)
public class SampleComponent {
public String getDesciription() {
return "Sample Component/service created using SCR annotation";
}
}
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
@Component(name="Sample component", immediate = true, description = "Sample component class")
@Service(SampleComponent.class)
public class SampleComponent {
public String getDesciription() {
return "Sample Component/service created using SCR annotation";
}
}
Component using R6 annotation
package com.aem.learnaem;
import org.osgi.service.component.annotations.Component;
@Component(name="Sample component", immediate = true, service = SampleComponent.class)
public class SampleComponent {
public String getDesciription() {
return "Sample component/service created using R6 annotation";
}
}
Going forward it is recommended to use R6 annotation to create component and services.import org.osgi.service.component.annotations.Component;
@Component(name="Sample component", immediate = true, service = SampleComponent.class)
public class SampleComponent {
public String getDesciription() {
return "Sample component/service created using R6 annotation";
}
}
Migration of Servlets
Servlet with SCR annotation
package com.aem.servlets;
import java.io.IOException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
@SlingServlet(paths = "/bin/learnaem",
extensions = "html",
methods = {"POST","GET"})
public class MyServlet extends SlingAllMethodsServlet{
private static final long serialVersionUID = 1L;
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
response.setContentType("text/json");
response.getWriter().write("test data");
}
}
Servlet with DS/R6 Annotation
import java.io.IOException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
@SlingServlet(paths = "/bin/learnaem",
extensions = "html",
methods = {"POST","GET"})
public class MyServlet extends SlingAllMethodsServlet{
private static final long serialVersionUID = 1L;
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
response.setContentType("text/json");
response.getWriter().write("test data");
}
}
package com.aem.servlets;
import java.io.IOException;
import javax.servlet.Servlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
@Component(service = Servlet.class,
property = {
"sling.servlet.methods="+"GET",
"sling.servlet.methods="+"POST",
"sling.servlet.paths="+"/bin/learnaem",
"sling.servlet.extensions="+"html",
}
)
public class MyServlet extends SlingAllMethodsServlet{
private static final long serialVersionUID = 1L;
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
response.setContentType("text/json");
response.getWriter().write("test data");
}
}
Note: The plugin maven-bundle-plugin can handle scr annotations too so it allows you to mix both types of annotations, only you can not mix both annotations in single class.
import java.io.IOException;
import javax.servlet.Servlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
@Component(service = Servlet.class,
property = {
"sling.servlet.methods="+"GET",
"sling.servlet.methods="+"POST",
"sling.servlet.paths="+"/bin/learnaem",
"sling.servlet.extensions="+"html",
}
)
public class MyServlet extends SlingAllMethodsServlet{
private static final long serialVersionUID = 1L;
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
response.setContentType("text/json");
response.getWriter().write("test data");
}
}
Properties migration
With SCR you can Configure properties and metatype for Component/ Services using @properties & @property annotation.
With R6/DS instead of using set of @property annotations Metatype properties can be handled using the class marked with @ObjectClassDefinition R6 annotation.
How to use @ObjectClassDefintion to define metatype information
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@ObjectClassDefinition(name =" sample configuratio", description = "sample configuration for SampleComponent")
public @interface SampleComponentConfig {
@AttributeDefinition(name="user name", description = "description aboout testUserName attribute")
String testUserName() default "";
@AttributeDefinition(name="user description", description = "description aboout testUserDesc attribute")
String testUserDesc() default "";
}
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@ObjectClassDefinition(name =" sample configuratio", description = "sample configuration for SampleComponent")
public @interface SampleComponentConfig {
@AttributeDefinition(name="user name", description = "description aboout testUserName attribute")
String testUserName() default "";
@AttributeDefinition(name="user description", description = "description aboout testUserDesc attribute")
String testUserDesc() default "";
}
@ObjectClassDefinition is used at whole configuration annotation and for each attribute @AttributeDefinition is used using these annotation metatype description for SampleComponentConfig class will be generate now we want to bind this with our component for that we have @Designate annotation.
Specify @Designate annotation on your class as below
Specify @Designate annotation on your class as below
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.metatype.annotations.Designate;
@Component
@Designate(ocd = SampleComponentConfig.class)
public class SampleComponent {
@Activate
protected void activate( SampleComponentConfig config ) {
//do some work here
}
}
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.metatype.annotations.Designate;
@Component
@Designate(ocd = SampleComponentConfig.class)
public class SampleComponent {
@Activate
protected void activate( SampleComponentConfig config ) {
//do some work here
}
}
@Reference remains same in R6 and SCR or you can put it on bind methods in R6
@Reference
private SampleComponent sample;
Comments
Post a Comment