March 29, 2020
Estimated Post Reading Time ~

Migration of SCR annotations to OSGi R6 annotations in AEM 6.3

I have recently gone through a migration project from an older version of AEM to AEM 6.3 and the major challenge while migrating java classes is that sometimes the API become deprecated in the newer version.

From AEM 6.2, One of our favorite Apache Felix Maven SCR Plugin has been deprecated and in place of this, Maven Bundle Plugin (version 6.2 or greater) has been introduced.

It always take a small effort to adapt new things, But change is the nature’s law. So here we will discuss how OSGi plugin has replaced all SCR annotations in AEM.

Packages:
Now the package “org.apache.felix.scr.annotations.*” will be replaced with “org.osgi.service.component.annotations.*” and “org,osgi.service.metatype.annotations.*”

While using Maven SCR plugin, we can find the Declarative Service(DS) output under /target/classes/OSGi-INF but using OSGi Bundle Plugin our DS output are found in /OSGI-INF, packaged under the compiled JAR File.

Note: The Apache Felix SCR annotations are replaced in AEM 6.3 projects with OSGi R6 annotations

How To start with OSGi Annotations?
1. Add a plugin in Parent Pom.xml
<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>    <version>3.2.0</version>    <inherited>true</inherited>
</plugin>


2. Add the following maven dependencies.
<dependency>
    <groupId>org.osgi</groupId>    <artifactId>org.osgi.service.component.annotations</artifactId>    <version>1.3.0</version>
</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.metatype.annotations</artifactId>    <version>1.3.0</version>
</dependency>


<dependency>
    <groupId>org.osgi</groupId>    <artifactId>org.osgi.compendium</artifactId>    <version>4.2.0</version>    <scope>provided</scope>
</dependency>


Note: Make sure that while building the code,plugin is working fine.

Migration of OSGi Components and Service
Before: In SCR Annotations:

@Component(name=”Test Service”,immediate=true,description="this is description")
@Service(TestService.class)
public class TestService {
public String getName()
{
return "testService";
}
}

After: In OSGi Annotations
@Component(name=”Test Service” service=TestService.class,immediate=true)
public class TestService {
public String getName()
{
return "testService";
}
}


Migration of Servlet
OSGi annotations has reduced our effort to remember a lot of Annotations.

In the Sling Servlets:
We used to use @Component, @Service @SlingServlet @Properties in SCR Annotations.
OSGi annotation just have @Component with the collaboration of all these annotations.

Before: In SCR Annotations:
@SlingServlet(paths="/bin/servlet",selectors = {"test","test1"},extensions = "html")
public class Test extends SlingSafeMethodsServlet{
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)throws IOException
{
response.getWriter().print(" I am in doGet Method");
}
}

After:In OSGi Annotations
@Component(service=Servlet.class,
property={
Constants.SERVICE_DESCRIPTION + "=Simple Demo Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.resourceTypes="+ "com.poc.osgiannotation/components/structure/page",
"sling.servlet.paths="+ "/bin/servlet",
"sling.servlet.extensions=" + "txt"
})
public class SimpleServlet extends SlingSafeMethodsServlet {
{
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)throws IOException
{
response.getWriter().print(" I am in doGet Method");
}
}

Custom OSGi Configuration in AEM
OSGi annotations provided a flexibility to create configuration in a separate interface and we can use it in any place.

The OSGi Configurations generates metatype specification that provides a way to describe configuration of the component.Such a metatype information can be used at runtime to generate forms to edit/create the configuration of a component. For example the Apache Felix web console does exactly that.

Let’s understand how to make OSGi configurations in AEM using OSGi Bundle Plugin.

package com.poc.osgiannotation.core.servlets;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.osgi.service.metatype.annotations.Option;

@ObjectClassDefinition(name = "SGAEM User Account Configuration", description = "Configure the user Details")
public @interface UserConfiguration {

@AttributeDefinition(name = "user.name", description = "User Name")
String getUserName() default "";

@AttributeDefinition(name = "userpassword", description = "Password of the user account", type = AttributeType.PASSWORD)
String getPassword() default "";

@AttributeDefinition(name = "user.isAdminUser", description = "is it admin user or not?")
boolean isAdminUser() default false;

@AttributeDefinition(name = "user.environments", description = "Define the all environment where this user will be available")
String[] getEnvironments() default {};

@AttributeDefinition(name = "user.validity", description ="Validity of user account", defaultValue = "10", required = true, type = AttributeType.INTEGER, min = "10")
int getValidity() default 10;

@AttributeDefinition(name = "memberof.name", description = "Member of the group", options = {
@Option(label = "Approval", value = "approve"),
@Option(label = "Editor", value = "editor"),
@Option(label = "Workflow Editor", value = "workflow.editor"),
@Option(label = "Administrator", value = "admin")})
String getMemberOf() default "";
}

view rawUserConfiguration.java hosted with ❤ by GitHub


package com.poc.osgiannotation.core.servlets;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.Designate;

@Component(service=UserAccountDetail.class,immediate=true)
@Designate(ocd = UserConfiguration.class)
public class UserAccountDetail {

private String userName;

private String password;

private Boolean isAdminUser;

private String memberOf;

private int validity;

private String[] environments;

@Activate @Modified
protected void activate(final UserConfiguration userConfiguration) {
userName = userConfiguration.getUserName();
password = userConfiguration.getPassword();
isAdminUser = userConfiguration.isAdminUser();
memberOf = userConfiguration.getMemberOf();
validity = userConfiguration.getValidity();
environments = userConfiguration.getEnvironments();
}

/**
* @return the userName
*/
public String getUserName() {
return userName;
}

/**
* @return the password
*/
public String getPassword() {
return password;
}

/**
* @return the isAdminUser
*/
public Boolean getIsAdminUser() {
return isAdminUser;
}

/**
* @return the memberOf
*/
public String getMemberOf() {
return memberOf;
}

/**
* @return the validity
*/
public int getValidity() {
return validity;
}

/**
* @return the environments
*/
public String[] getEnvironments() {
return environments;
}
}


Fig- OSGi COnfiguration in felix Console

Migration of Custom Workflow Process Step

Before: In SCR Annotations
@Component(immediate = true, enabled = true, metatype = true)
@Service(value = WorkflowProcess.class)
@Property(name = "process.label", value = "Activate Page", propertyPrivate = true)
public class RejectionMailProcess implements WorkflowProcess {
public void execute(WorkItem workitem, WorkflowSession wfsession,MetaDataMap metaDataMap)
{
System,.out.println(“ I am in execute method”);
}
}


After: In OSGi Annotations
@Component(service = WorkflowProcess.class, property = {"process.label=Activate Page" })
public class TestWorkflow implements WorkflowProcess {
public void execute(WorkItem workitem, WorkflowSession wfsession,MetaDataMap metaDataMap)
{
System,.out.println(“ I am in execute method”);
}
}


How to use @Reference Annotations in OSGi Annotations?
There are multiple ways to use @Reference annotations in OSGi annotations:

1. @Reference
TestService testService;

2.
private TestService testService;

@Reference
public void bindTestService(TestService testService) {
this.testService = testService;
}

public void unbindTestService(TestService testService) {
this.testService = testService;
}


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.