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
<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>

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>

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>

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";
}
}

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.
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
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.

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 "";
}

@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

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
}
}

@Reference remains same in R6 and SCR or you can put it on bind methods in R6
@Reference
private SampleComponent sample;

Comments

Popular posts from this blog

AEM in docker

Sling API vs JCR API

Creating or finding .M2 folder