Showing posts with label Service. Show all posts
Showing posts with label Service. Show all posts

May 27, 2020
Estimated Post Reading Time ~

How to Add and Read Bundle / Service Configurations(String, Dropdown, Array/Multifield )

Adding Properties to the Bundle/ OSGI CQ Service
String / TextField
@Property(value = "GET")
static final String STRING_VAL = "string.textfield";

String Array / Multifield
@Property ( unbounded=PropertyUnbounded.ARRAY, value={"*"},label="Template paths",description="eg: /apps/devtools/templates/page-home" )
private static final String MUTIFIELD_EX = "multifield.test";

Boolean Field
@Property(boolValue={false}, label="Boolean values", description="Booealn test")
private static final String BOOLEN_TEST = "boolean_test";
Dropdown
@Property( options={
@PropertyOption(name="blue", value="color-blue"),
@PropertyOption(name="green", value="color-green"),
@PropertyOption(name="red", value="color-red"),
@PropertyOption(name="yellow", value="color-yellow"),
private static final String SELECTION_TEST = "dropdown.test";

Reading Properties of Bundle/ OSGI CQ Service

1) You to get the ConfigurationAdmin reference
@Reference
ConfigurationAdmin configAdmin;

2) Get Bundle Configuration
Configuration config = configAdmin.getConfiguration(this.getClass().getCanonicalName());

3) Get properties of conguration
Dictionary<?, ?> configProperties = config.getProperties();

4) Red Properties
Reading String/TextField
String texfiledValue = (String) configProperties.get( STRING_VAL );
Reading the Dropdown
String dropdownTest = (String) configProperties.get( SELECTION_TEST );
Reading Boolean
Boolean booealnTest = ( Boolean ) configProperties.get( BOOLEN_TEST );
Reading Array/Multifield
String[] multifieldVlaues = (String[]) configProperties.get( MUTIFIELD_EX );

for( String value : multifieldVlaues ){
out.println( value );
}


By aem4beginner

May 19, 2020
Estimated Post Reading Time ~

Getting a Handle on Service Implementations in AEM

OSGi- A Brief Introduction
OSGi is a complex framework consisting of several design paradigms, architectures, and technical specifications. Entire books can be written on just a single aspect of it. In this blog, we’ll only focus on the idea of using OSGi services from its service registry.

OSGi originally set out to define a set of specifications to allow the development of highly modular enterprise systems for the Java language. It was founded in 1999 as the Connected Alliance, and comprised researchers from  Ericsson, IBM, Motorola, and Sun Microsystems. Today, the alliance is made from more than 35 multinational technology companies. OSGi has evolved to support a wide variety of platforms, including, systems for mobile phones, the web, and automobiles.1

Services in OSGi are identical to the services we introduced in the previous blog. Recall that they are basically just Java interfaces. The service registry, in the meantime, is a database of all the services that are available in the current environment and is a crucial component of the framework. The OSGi service registry, which is itself a service, acts as a real-time broker that matches a client-code to any services it wishes to use.

Getting a Service Using Core OSGi API’s
Before we show the code to obtain a service, we have to populate a service-provider into OSGi’s service registry. Historically, this was done by a class that implements a special kind of interface called a ‘BundleActivator’. Classes that implement this interface are provided with an execution environment variable called the ‘BundleContext’ object. The following classes register an email service:

Class EmailRegistrationProvider implements BundleActivator {
  @Override
  Public void start(BundleContext context) throws Exception {
    EmailService gmailService = new GmailProvider();
    context.registerService(EmailService.class.getName(),gmailService,null);
  }
}
Where, GmailProvider is a service-provider and may look as the follows:

Class GmailProvider implements EmailService {
  @Override
  Public String checkEmail(){
    // code to check against the gmail server
  }
  @Override
  Public String sendEmail(){
    // code to send email via the gmail smtp
  }
}

Now any class/client-code that wishes to use this service would have to go through the steps of looking into the same ‘BundleContext’ object to get a handle to the service provider. An example of client code is as follows:
(Note that the client also needs to have implemented the ‘BundleActivator’ interface, so that the appropriate environment variable, i.e the BundleContext object is available for inspection.)

Class EmailServiceClient implements BundleActivator {
  @Override
  Public void start(BundleContext context) throws Exception {
    ServiceReference ref = context.getServiceReference(EmailService.class.getName());
    If (ref !=nul ){
      EmailService emailService = (EmailService) context.getService(ref);
      If (emailService != null){
          emailService.sendEmail();
      }
    }
  }
}

Getting Services Using the DS Annotations
In the first section, we saw briefly how to deal with services using the core OSGi APIs. However, the community quickly realized that a lot of boilerplate code was needed to do even the most basic things. Hence, they came up with a set of specifications that allowed the development of OSGi components using pure Java annotations. They were subsequently called DS (Declarative Services) annotations and had the potential for alleviating almost all OSGi framework code in a client application while sacrificing only a minuscule amount of code-dexterity. In Neil’s book2, he mentions that ~90% of the use cases are supported by DS annotations, and for cases where they don’t suffice, one can always drop down to the API’s. Here, we give an example of both-

Getting a Service Using Only a DS Annotation:
Using a service using just the DS Annotations is the easiest. In the code below, the ‘@Component’ annotation defines this class as an OSGi component. An OSGi component, just like a sling-model, is also a container-managed entity but is now being managed by OSGi. In fact, the entire AEM framework is nothing more than a collection of proprietary components and services running inside OSGi. Thus OSGi is the unifying concept to which everything is glued.

@Component // This is an OSGI specific-annotation
class EmailServiceClient {
  // Use the OSGI annotation to get a service provider
  @Reference
  EmailService emailService;
  public String getMail() {
    // do something useful with the service now, e.g.
     results = emailService.checkEmail();
     return results
   }
}

Getting a Service Using a Mix of OSGi Annotations and Lower-level OSGi APIs
Consider a use-case where we have more than one service provider for the same interface. This could perhaps come as individual email clients that each connect to a different email host. Say, for example, we have an email provider to check from a Yahoo email account:

Class YahooMailProvider implements EmailService {
  @Override
  Public String checkEmail(){
    // code to check against the yahoo server
  }
  @Override
  Public String sendEmail(){
    // code to send email via yahoo’s email server
  }
}

The client-code that could use both the email providers would then be constructed as follows:

@Component
class ServiceUser{
  ...
  List services
  @Activate
  protected void init(ComponentContext context){
     services = new ArrayList<>()
     BundleContext bundleContext = context.getBundleContext()
     ServiceReference[] references = bundleContext.getAllServiceReferences(EmailService.class.getName(), null)
     for (ServiceReference reference: references) {
        EmailService service = (EmailService) bundleContext.getService(reference)
        parsers.add(service)
     }
     checkEmail(services);
  }
  private void checkEmail(List services){
    for(EmailService service: services){
      service.checkEmail(); // invoke each service to check against a unique mail server
    }
  }
}

The above examples are some of the ways that implementation of a service (i.e. Service Providers) can be used in AEM or any OSGI compliant code-base. The methods shown above are not exhaustive, by any means, but provide coverage for a vast majority of cases. Using services is a highly encouraging pattern for developing AEM code, and should be leveraged as much as possible because of its ease of use and ability to work smoothly in most cases.


By aem4beginner

May 13, 2020
Estimated Post Reading Time ~

Common Error with AEM Services

In this post, I will explain a common mistake we make, when we create a simple service class for AEM. Sometimes we create a service class using @Service annotation & build our project using –

mvn clean install -P<profileName>
command. We found an error as shown below –
[ERROR] Failed to execute goal org.apache.felix:maven-scr-plugin:1.7.4:scr (generate-scr-descriptor) on project blog-bundle: SCR Descriptor parsing had failures (see log) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <goals> -rf :blog-bundle


the error description provided by logs is not enough to identify this error easily & when we try to use -X switch for debugging our code then we got some kind of mojo exception as shown below –

[ERROR] Failed to execute goal org.apache.felix:maven-scr-plugin:1.7.4:scr (generate-scr-descriptor) on project blog-bundle: SCR Descriptor parsing had failures (see log) -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.felix:maven-scr-plugin:1.7.4:scr (generate-scr-descriptor) on project blog-bundle: SCR Descriptor parsing had failures (see log)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Caused by: org.apache.maven.plugin.MojoFailureException: SCR Descriptor parsing had failures (see log)
at org.apache.felix.scrplugin.mojo.SCRDescriptorMojo.execute(SCRDescriptorMojo.java:204)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
… 19 more
Caused by: org.apache.felix.scrplugin.SCRDescriptorFailureException: SCR Descriptor parsing had failures (see log)
at org.apache.felix.scrplugin.SCRDescriptorGenerator.execute(SCRDescriptorGenerator.java:370)
at org.apache.felix.scrplugin.mojo.SCRDescriptorMojo.execute(SCRDescriptorMojo.java:192)
… 21 more
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <goals> -rf :blog-bundle


at our IntelliJ IDEA we got neither an error nor a simple warning. but when we build our project we found a maven-scr-plugin error. Reason for this error is –
Generally, when we create a class with @Service annotation we implement an interface as shown –
@Component
@Service
public class CommonErrorImpl implements CommonError{
……….
}

This is the best practice so normally we don’t forget to implement an interface but sometimes we forgot to implement an interface and create a class as follows
@Component
@Service
public class CommonErrorImpl{
……….
}


this is the case where we found the error. So to resolve this error we can do 3 things –

1). Implement an interface
2). Define a same class name in @Service annotation as –
@Component
@Service(CommonErrorImpl.class)
public class CommonErrorImpl{
……….
}


3). Check org.apache.felix:maven-scr-plugin:<version> plugin in your project module’s pom.xml file it should be in this format –
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>


By aem4beginner

May 10, 2020
Estimated Post Reading Time ~

Serving Assets with Selectors

In a project, we recently had the requirement to serve assets with a selector. The reason for adding the selector was that all CUG protected assets need to be served from a specific dispatcher farm.

Unfortunately, the extension of assets is part of the node name in AEM. A sample geometrixx asset is stored as node “GeoCube_Datasheet.pdf” under /content/dam/geometrixx/documents .

When we try to access this with a selector /content/dam/geometrixx/documents/GeoCube_Datasheet.secure.pdf, the resource cannot be resolved, resulting in a 404.

After checking the Sling source code, we’ve found a way to get to the document with the selector: add all the selectors after the extension, and then add extension .res.

Why? that’s quite complicated:

adding the selectors after the original extension makes sure that the resource is actually found during resource resolution
rendering of resources needs to be done by the org.apache.sling.servlets.get.impl.helpers.StreamRendererServlet, but the servlet only accepts resources without an extension or with .res
But our troubles are not quite over yet: If we render this as a .res resource, Apache will serve this as content-type application/x‐dtbresource+xml

The following rewrite rule should take care of that for pdf documents:

RewriteRule ^/content/dam/(.*).secure.pdf /content/dam/$1.pdf.secure.res [PT,L,T=application/pdf]

With this rewrite rule, the asset is actually available for end users at the desired url /content/dam/geometrixx/documents/GeoCube_Datasheet.secure.pdf, hiding the .res extension workaround from the end user.


By aem4beginner

OSGi Components and Services

ComponentServices
The component is started immediatelyComponents providing a service are activated only when they’re actually referenced by some other component/service.
Every component is not a service.Every service is a component.
 Its a software(java class) managed by a component container. The only container can create and manage the component(class) object. The object cannot be instantiated by us. The container can also pass some inputs to the component.It's a component which also provides some service, implements one or more interfaces and service used by other components or services.
 Declarative Services (DS) is one way of developing components and services for OSGiBlueprint, Apache Felix iPojo, Apache Felix Dependency Manager etc. are other approaches
@Component
public class MyComponent {@Activate
protected void activate() {
//Gets called when a component is instantiated by the conatiner.
// do something
}@Deactivate
protected void deactivate() {
//when gets deactivated by the container.
// do something
}
}
These methods can be of any name,have to be protected with no return value.
@Component
@Service(value=ServiceInterface.class)
public class MyService implements ServiceInterface{@Activate
protected void activate(final Map<String, Object> config) {}
}
It can implement multiple interfaces.
@Component
@Service(value={ServiceInterface1.class,ServiceInterface2.class})
public class MyService implements ServiceInterface1,ServiceInterface2
 Component Container manages the lifecycle of component.Services are initialized when used, when unused for some time, it gets destroyed.
To create a service-Define the service API, implement this API.
A service implementation should never be public but in a private package
 Usage example: Sling SchedulerUsage:
A component can use other services by using the @Reference SCR annotation.
Before the component gets activated, the services used get initialized. If service is unavailable component will be deactivated.
The component is registered by the Component class name itself.Services are registered by their interface they implement
The component can be made configurable:
@Activate
protected void activate(final Map<String, Object> configs) {
// use the configuration
//
}
Services can be configurable:
@Component(metatype=true)

@component(immediate=true)
With immediate set to true, the component is activated as soon as possible and kept as long as possible.This increases things like startup time, memory consumption etc.
 To create a service which should be active for every request, component should be set to immediate=true
If an interface is registered by multiple components, then one with max service ranking will be used.


By aem4beginner

May 8, 2020
Estimated Post Reading Time ~

Configuring AEM as a Service on CentOS

This article details how to set up AEM as a service on CentOS/Linux
Step-by-step guide
Prerequisites:
You will need root access
Download these 2 files
1. Filename: aem
#!/bin/bash
#
# /etc/rc.d/init.d/aem6
#
#
# # of the file to the end of the tags section must begin with a #
# character. After the tags section, there should be a blank line.
# This keeps normal comments in the rest of the file from being
# mistaken for tags, should they happen to fit the pattern.>
#
# chkconfig: 35 85 15
# description: This service manages the Adobe Experience Manager java process.
# processname: aem6
# pidfile: /crx-quickstart/conf/cq.pid# Source function library.
. /etc/rc.d/init.d/functions

SCRIPT_NAME=`basename $0`
AEM_ROOT=/opt/aem6
AEM_USER=aem

########
BIN=${AEM_ROOT}/crx-quickstart/bin
START=${BIN}/start
STOP=${BIN}/stop
STATUS=”${BIN}/status”

case “$1” in
start)
echo -n “Starting AEM services: ”
su – ${AEM_USER} ${START}
touch /var/lock/subsys/$SCRIPT_NAME
;;
stop)
echo -n “Shutting down AEM services: ”
su – ${AEM_USER} ${STOP}
rm -f /var/lock/subsys/$SCRIPT_NAME
;;
status)
su – ${AEM_USER} ${STATUS}
;;
restart)
su – ${AEM_USER} ${STOP}
su – ${AEM_USER} ${START}
;;
reload)
;;
*)
echo “Usage: $SCRIPT_NAME {start|stop|status|reload}”
exit 1
;;
esac
2. Filename: aem.service
[Unit]
Description=Adobe Experience Manager[Service]
Type=simple
ExecStart=/usr/bin/aem start
ExecStop=/usr/bin/aem stop
ExecReload=/usr/bin/aem restart
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

3. Open aem script file and update the below

  • AEM_ROOT (e.g: /mnt/crx is the root, where /mnt/crx/crx-quickstart is the full path)
  • AEM_USER (e.g: aem)
4. SCP these files to the server
Copy aem to /usr/bin/aem
Example: From terminal on your desktop $ scp <filename> user@1.1.1.1:/usr/bin/aem
Copy aem.service to /etc/system.d/system/aem.system
Example: From terminal on your desktop $ scp <filename> user@1.1.1.1:/etc/system.d/system/aem.system
5. SSH to your server
ssh user@1.1.1.1
6. Give permissions to the files
sudo chmod u+rwx /usr/bin/aem
sudo chmod u+rwx /etc/system.d/system/aem.system
7. Update
cd /etc/system.d/system
systemctl enable aem.system
You can restart the server or run the below commands to start AEM. Make sure 

8. you run Pre-requisite Step 2 before running this command.

Commands to START, RESTART and STOP AEM
  • Start AEM – sudo service aem start
  • Restart AEM – sudo service aem restart
  • Stop AEM – sudo service aem stop
Notes
  • The example above was tested on CentOS 7
  • AEM 6.3 version was used. Although the above process should work for AEM 6.x
Source: https://techinpieces.com/configuring-aem-as-a-service-on-centos-skip-to-end-of-metadata/


By aem4beginner

How to get a service reference or BundleContext with no OSGi context

Issue
In Adobe Experience Manager (AEM) projects developers are working a lot in services, filters, servlets and handlers. All of these classes are OSGi components and services using the Felix SCR annotations or the newer OSGi DS annotations. But sometimes you need an OSGi service or the BundleContext also in non OSGi / DS controlled class

Solution
You can use the OSGi FrameworkUtil [1] to get the reference to the bundle context from any object. The code below shows how to get reference to the BundleContext and the service.

Most of the time, you have the SlingHttpServletRequest ready to pass:

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import java.util.Objects;
public class ServiceUtils {
    /**
     * Gets the service from the current bundle context.
     * Return null if something goes wrong.
     *
     * @param <T>     the generic type
     * @param request the request
     * @param type    the type
     * @return        the service
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> T getService(SlingHttpServletRequest request, Class<T> type) {
        SlingBindings bindings = (SlingBindings) request.getAttribute(SlingBindings.class.getName());
        if (bindings != null) {
            SlingScriptHelper sling = bindings.getSling();
            return Objects.isNull(sling) ? null : sling.getService(type);
        } else {
            BundleContext bundleContext = FrameworkUtil.getBundle(type).getBundleContext();
            ServiceReference settingsRef = bundleContext.getServiceReference(type.getName());
            return (T) bundleContext.getService(settingsRef);
        }
    }
}

Or you just use the class that was loaded over a bundle classloader.

package com.sanitas.aem.core.utils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
public class ServiceUtils {
     
    /**
     * Gets the service from the current bundle context.
     * Return null if something goes wrong.
     *
     * @param <T>     the class that was loaded over a bundle classloader.
     * @param type    the service type.
     * @return        the service instance.
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> T getService(Class clazz, Class<T> type) {
        Bundle currentBundle = FrameworkUtil.getBundle(clazz);
        if (currentBundle == null) {
            return null;
        }
        BundleContext bundleContext = currentBundle.getBundleContext();
        if (bundleContext == null) {
            return null;
        }
        ServiceReference<T> serviceReference = bundleContext.getServiceReference(type);
        if (serviceReference == null) {
            return null;
        }
        T service = bundleContext.getService(serviceReference);
        if (service == null) {
            return null;
        }
        return service;
    }
}

[1] https://osgi.org/javadoc/osgi.core/7.0.0/org/osgi/framework/FrameworkUtil.html



By aem4beginner

April 27, 2020
Estimated Post Reading Time ~

org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught Throwable java.lang.LinkageError: loader constraint violation - AEM

Sometimes we may receive the following exception while invoking the Adobe Experience Manager(AEM) services.

20.12.2014 11:15:31.816 *ERROR* [0:0:0:0:0:0:0:1 [1419054331815] GET /services/EmailServlet HTTP/1.1] org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught Throwable java.lang.LinkageError: loader consaint violation: when resolving interface method "com..commerce.connector.CommerceService.getSession(Ljavax/servlet/http/HttpServleequest;Ljavax/servlet/http/HttpServleesponse;)Lcom//commerce/connector/session/CommerceSession;" the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) of the current class, com///servlet/EmailServlet, and the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) for resolved class, com//commerce/connector/CommerceService, have different Class objects for the type connector.CommerceService.getSession(Ljavax/servlet/http/HttpServleequest;Ljavax/servlet/http/HttpServleesponse;)Lcom//commerce/connector/session/CommerceSession; used in the signature
at com...servlet.EmailServlet.doPost(EmailServlet.java:67)
at com...servlet.EmailServlet.doGet(EmailServlet.java:56)
at org.apache.sling.api.servlets.SlingSafeMethodsServlet.mayService(SlingSafeMethodsServlet.java:268)
at org.apache.sling.api.servlets.SlingAllMethodsServlet.mayService(SlingAllMethodsServlet.java:139)


This error will be thrown while invoking the service of one bundle from another bundle.

To fix this issue, make sure the required packages from the target bundle is imported to the source bundle.


By aem4beginner

Referencing the services between OSGI bundles

This post explains how to refer the services between OSGI bundles in Adobe Experience Manager.

Export-Package:
Bundles may export zero or more packages from the JAR to be consumable by other bundles. The export list is a comma-separated list of fully-qualified packages, often with a version attribute. If not specified, the version defaults so 0.0.0.

In the target bundle the packages contains the required services and the classes exposed to the other bundles should be exported.


Import-Package
The Import-Package header is used to declare dependencies at a package level from the bundle. At runtime, the bundle will be wired up with whatever (compatible) bundle offers the package.

In the source bundle the packages contains the required services and classes referred from other bundle should be imported.


Approaches for reference the following two approaches can be used to refer the services from other bundle.

Through Reference
@Reference
private CommerceServiceFactory sFactory;

Through bundle context
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
CommerceServiceImpl factoryFromBundle=(CommerceServiceImpl)bundleContext.getService(bundleContext.getServiceReference(CommerceServiceFactory.class)).getCommerceService();


By aem4beginner

April 14, 2020
Estimated Post Reading Time ~

Creating an Adobe Experience Manager 6.4 custom workflow step that uses the MessageGatewayService API

You can develop a custom Adobe Experience Manager 6.4 workflow step that sends email messages to users. A custom workflow step is implemented as an OSGi bundle that you can build using Maven and the AEM Workflow API that belong to the com.adobe.granite.workflow.exec package. For information, see Package com.adobe.granite.workflow.exec.

The following video shows the workflow developed in this article successfully sending an email using the MessageGatewayService API.

To read this development article, click https://helpx.adobe.com/experience-manager/using/message_service_gateway_api_64.html.


By aem4beginner

Creating Custom Data Importer Services for Adobe Experience Manager

You can develop a custom data importer service for Adobe Experience Manager (AEM) that lets you import data. To address some business requirements, importing external data into your AEM site is an important use case. For example, you can import data from an external social media site. In this development article, a cus­tom node type, cq:PollConfig, is used to import data at a specific inter­val.
 

To create a custom data importer service, use the com.day.cq.polling.importer.Importer API and create an OSGi bundle, as shown in the following illustration.


To read this development article, click http://helpx.adobe.com/experience-manager/using/polling.html.



By aem4beginner

Passing JCR Node Objects to Adobe Experience Manager Custom Services

In some business use cases, you have to pass JCR nodes from a front-end component to a back-end custom Adobe Experience Manager (AEM) custom service. For example, you can pass a Node object (for example, a currentNode in a JSP) to an AEM service (a javax.jcr.Node Java object) and use the JCR API to read its properties and perform application logic on the values. This development article walks you through how to pass a node object from a JSP to custom service. The custom service uses the JCR API to read a property and pass back the value as the service's return value.



To read this development article, click https://helpx.adobe.com/experience-manager/using/passing_nodes.html.


By aem4beginner

April 13, 2020
Estimated Post Reading Time ~

Creating a Custom Reporting Service for Adobe Experience Manager

You can create a custom reporting service for Adobe Experience Manager (AEM) that stores AEM data. A benefit of creating a custom service is you can develop it to meet your business requirements and integrate the reporting service to use data queried from an AEM service. For example, you can create an AEM solution that queries enterprise data that a digital marketer is interested in viewing. Then you can write out the data to a report and store the report in the AEM Java Content Repository (JCR).

This development article extends an AEM application that is built by following another AEM development article that queries data from MySQL using a DataSourcePool. Before following this article, create the DataSourcePool application by following this article: Injecting a DataSourcePool Service into an Adobe Experience Manager OSGi bundle.

In this article, an option is added to the web application that lets a user specify if the queried data is written to a custom report. Consider the following AEM web application.

An AEM web application that lets a user generate a custom report with the result set

This development article walks you through how to build this custom reporting service. To read this development article, click http://helpx.adobe.com/experience-manager/using/aem-reporting-service.html.

Note: Adobe Experience Manager supports reports without creating a custom reporting service. You can create a report by configuring JCR nodes and properties. For information, see Developing Reports.


By aem4beginner

Creating your first AEM Service using an Adobe Maven Archetype project

This development article was written due to a request from the AEM community. It discusses how to create your first Adobe Experience Manager (AEM) custom service by using Maven and an Adobe Archetype project.

In some business use cases, you create an OSGi bundle when creating an Adobe Experience Manager (AEM) application. Although there are different ways to create an OSGi bundle, a recommended way is to use Maven and the Adobe Maven Archetype. This development article walks you through creating a basic OSGi bundle that contains a simple service named KeyService. All this service does is accept an input value and sets a key value. It also exposes a method that returns the key value and the value can be displayed within an AEM web page.

To read this development article, click, http://helpx.adobe.com/experience-manager/using/first-osgi.html.


By aem4beginner

April 10, 2020
Estimated Post Reading Time ~

Part 4: AEM with Angular 2 - Unit Testing Angular Components & Services

In this post, we’ll learn about Unit testing Angular code base and collecting code coverage matrix.

Unit testing is very important from a code quality perspective and it becomes even more important when the project is large and multiple teams are working on the same project. In large projects, dividing large systems into small and loosely coupled modules is a best practice but then, it becomes very critical to test each of these modules independently without explicit depending on each other. This is very critical from a unit testing perspective.

In AEM, we have reusable components that can be used to create a variety of content and it becomes very important to test each component. Typically, an AEM component has:
  1. User Interface (JSP, Sightly, etc.) and JavaScript (Angular.js, React.js, etc.)
  2. Some backing object/Sling Model
  3. And/or WCM Use class (Java or JavaScript-based)
In a well-designed and architected application, each of these 3 pieces should be independently unit testable. In this article, we’ll be focusing on testing User Interface i.e. #1

Unit testing UI is simple as compared to developing AEM components using Angular 2. It is simple because, for testing we are not doing anything different just because we are using AEM, testing will be done in the usual way as we would do when we are not using AEM.

NOTE: Since we have our custom build script for building projects, we won’t be using Angular CLI and standard project structure for testing.

I am going to use same project from my github repository and will add everything that we need for unit testing UI (Angular code).

Before we proceed, let’s refresh a few things:
Code for this project is here: https://github.com/suryakand/aem-angular2
In previous articles in this series we learned that we have two separate builds:

“gulp build” – builds project so that everything can be testing as if it is regular angular application. This build generates artifacts on build folder and you can run following command to run the application “npm run start”
“gulp build:aem” – build projects in such a way that everything is packaged as crx package that can be deployed into AEM

Testing Frameworks
For UI unit testing we’ll be using:
Jasmine - Jasmine is a JavaScript testing framework that supports a software development practice called Behavior Driven Development, or BDD for short
Karma - Manually running Jasmine tests by refreshing a browser tab repeatedly in different browsers every-time we edit some code can become tiresome. Karma is a tool that lets us spawn browsers and run jasmine tests inside of them all from the command line. The results of the tests are also displayed on the command line. Karma can also watch your development files for changes and re-run the tests automatically. Karma lets us run jasmine tests as part of a development toolchain which requires tests to be runnable and results in inspectable via the command line.
Istanbul - a JS code coverage tool written in JS.

Project Configuration
To write and execute we need to add/update some configuration files. In this section, we’ll see go over these changes.

1. Update package.json – You can see changes here https://github.com/suryakand/aem-angular2/commit/4dc287c6b661fec227263b136df2d853f5d387be

include UI unit testing and test runner dependencies in package.json file and “run npm” install again


Add a task to run a unit test


2. Add karma runner configuration (karma.conf.js) – Complete configuration file is here https://github.com/suryakand/aem-angular2/commit/316bdc3e2426f74c2d42a6d8339753f3cda4d485#diff-a068ef752f58b4eda47e5254ca70802d

This file defines where to look for JS files that need to be considered for testing, which testing framework to use for testing, what reporters (code coverage framework) to use and what port Karma should run etc.

Write Unit Test Cases
I have added a new folder called “ui.tests“ where we’ll write all test cases for our Angular code. The new folder structure looks like this

From Angular perspective, there are 2 main entities for which we need to write test cases:
  1. Angular Components
  2. Angular Services
Let’s write a test case for the Angular component. For this article, we’ll write a very basic test case for “about.component”. You can refer to the full example of “about.component” test case here https://github.com/suryakand/aem-angular2/blob/master/ui.apps/src/main/content/jcr_root/apps/ngaem/components/ui.tests/components/about.component.spec.ts

Here are the basic steps involved in writing a test case:
Import mock test dependencies, components, and services needed for testing

Initialize mock Angular environment/TestBed (as if we do in with real application in browser) by loading/initializing angular components and services. This mock angular environment initialized for testing is referred to as TestBed. To simplify this I have created a utility class “UtilTestBed”. You can use this class initialize mock TestBed in one line, see line# 19 below

Write logic/asset statements to test components. In this step, we create an instance of a component that we want to test and verify that it has been rendered properly. Verification can be done in various ways e.g. verify that expected HTML element is rendered (line# 30 below), text/value of the rendered element (line# 37 below)

The same method can be followed for writing test cases for angular services too. Once you have writing test cases, you can execute them using the following command:
“npm run test”

You should see the following output after execution is completed:


Verifying Code Coverage Report
Once all test cases are finished, navigate to the “/aem-angular2/ui.apps/target/reports/coverage/report-html” folder and open index.html to see code coverage report. The report would look like this:


I hope this article will help you to implement unit tests for your front end code and will help you to maintain your code quality.

Source: http://suryakand-shinde.blogspot.com/2018/01/part-4-aem-with-angular-2-unit-testing.html


    By aem4beginner

    April 9, 2020
    Estimated Post Reading Time ~

    Register Groovy class as Component/Service in CQ

    Being a CQ5 developer, I have to register components and services almost every day. Knowing how powerful Groovy is, I wanted to replace all Java code with Groovy. The first step towards it was being able to compile Groovy.

    Although I was facing the following problem even after this:
    – I was not able to register the component as a service or component. In fact, none of the SCR annotations seemed to work with Groovy. I had the following maven-scr plugin configuration.

    <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-scr-plugin</artifactId>
    <executions>
    <execution>
    <id>generate-scr-descriptor</id>
    <goals>
    <goal>scr</goal>
    </goals>
    </execution>
    </executions>
    </plugin>


    Tried a lot of things for this and this is how I got it to work(thanks to suggestions from a group):

    <plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-scr-plugin</artifactId>
    <configuration>
    <scanClasses>true</scanClasses>
    </configuration>
    <executions>
    <execution>
    <id>generate-scr-descriptor</id>
    <goals>
    <goal>scr</goal>
    </goals>
    </execution>
    </executions>
    </plugin>


    By default, the maven-scr plugin compiles only Java Classes. To make it aware of Groovy classes also, a configuration “scanClasses” has to be set to true.

    Updated:
    There are 2 more configuration changes that are needed:
    1) I had to change the version of maven-scr-plugin from 1.7.4 to 1.17.0
    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-scr-plugin</artifactId>
        <version>1.17.0</version>
    </plugin>


    2) Change version of Felix scr annotation to 1.9.8
    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.scr.annotations</artifactId>
        <version>1.9.8</version>
        <scope>provided</scope>
    </dependency>


    Adding this code worked like a charm.
    Source: https://www.tothenew.com/blog/register-groovy-class-as-componentservice-in-cq/


    By aem4beginner

    April 6, 2020
    Estimated Post Reading Time ~

    OSGi Component vs Service in AEM

    AEM ships with an OSGi container Apache felix that implements Declarative Services (DS) component model. Most of the developers who are new to AEM often gets confused between OSGi components and services.

    OSGi Component
    If you want the life of your object to be managed by the OSGi container, you should declare it as a component. Using DS annotations, you could make a POJO a OSGi component by annotating it with@Component With this, you will get the ability to start, stop and configure the component using the felix web console.

    OSGi Service
    OSGi components can be made as OSGi service by marking it with @Service annotation. All it mandates is that an interface – Services should implement an interface (1 or more). When you mark a component as service, you could refer (call) this service from other osgi components.

    OSGi Component Vs Service
    All objects managed by OSGi container are components. You qualify components as services. This means that all services are components but not vice-versa.

    Components can refer/call (using container injection – @Reference) other services but not components. In other words, a component cannot be injected into another component / service. Only services can be injected into another component.

    OSGi Component Example
    We have a weather printing component that creates a thread when activated (started) and calls the weather service (an OSGi service) to pull the weather details from the yahoo server.

    package com.computepatterns.apppatterns.osgi;

    import java.io.IOException;
    import java.util.Map;

    import org.apache.felix.scr.annotations.Activate;
    import org.apache.felix.scr.annotations.Component;
    import org.apache.felix.scr.annotations.Reference;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    @Component(
    label = "Compute Patterns - Weather details printing osgi component.",
    description = "Sample OSGi component that uses thread and a OSGi service to print weather details in log.",
    immediate = true)
    public class WeatherPrintingComponent {
    private static final Logger log = LoggerFactory.getLogger(WeatherPrintingComponent.class);

    /* Yahoo weather api end point */
    private static final String weatherApiEndpoint =
    "http://weather.yahooapis.com/forecastrss?p=80020&u=f";

    @Reference
    WeatherService weatherService;

    @Activate
    protected void activate(Map<String, String> config) {
    log.info("Weather printing component - activiated");
    // Set up a thread which wakes up every 5s and make a make a service call to fetch weather info
    // and print it in the log.
    Runnable task = () -> {
    try {
    while (!Thread.currentThread().isInterrupted()) {
    Thread.sleep(5000);
    try {
    log.info(weatherService.getWeatherFeed(weatherApiEndpoint));
    } catch (IOException e) {
    log.error("Unable to get weather details.", e);
    }
    }
    } catch (InterruptedException e) {
    log.error("Weather printing thread interrupted", e);
    }
    };

    Thread weatherThread = new Thread(task);
    weatherThread.setName("Compute Patterns - Weather printing");
    weatherThread.start();
    }
    }


    WeatherPrintingComponent class has been marked with @Component annotation (line# 12). A service WeatherService is injected into the component (line #.24). Remember that a component can refer to other services.
    Here’s the source code for the WeatherService interface and its implementation.

    package com.computepatterns.apppatterns.osgi;

    import java.io.IOException;

    /**
    * Service to provide weather details.
    */
    public interface WeatherService {

    /**
    * Get weather feed using given endpoint.
    *
    * @param apiEndPoint Url endpoint to hit and get the weather feed. Example - Yahoo weather end
    * point.
    * @return Weather feed in xml format.
    * @throws IOException Exception in connecting to the url.
    */
    String getWeatherFeed(String apiEndPoint) throws IOException;
    }


    package com.computepatterns.apppatterns.osgi.impl;

    import java.io.IOException;
    import java.util.Map;

    import org.apache.felix.scr.annotations.Activate;
    import org.apache.felix.scr.annotations.Component;
    import org.apache.felix.scr.annotations.Service;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.HttpStatus;
    import org.apache.commons.httpclient.methods.GetMethod;
    import org.apache.commons.lang.StringUtils;

    import com.computepatterns.apppatterns.osgi.WeatherService;

    /**
    * Weather service implementation. Connects to the provided end point using apache http client to
    * fetch the feed.
    *
    */
    @Component(label = "Compute Patterns - Weather Service.",
    description = "Connects to the weather apis and fetches weather details.")
    @Service
    public class WeatherServiceImpl implements WeatherService {
    private static final Logger log = LoggerFactory.getLogger(WeatherServiceImpl.class);

    @Activate
    protected void activate(Map<String, String> config) {
    log.info("Weather Service - ACTIVATED");
    }

    @Override
    public String getWeatherFeed(String apiEndPoint) throws IOException {
    // Sanity check the arguments.
    if (StringUtils.isBlank(apiEndPoint)) {
    return StringUtils.EMPTY;
    }
    // Create a http client and hit the server.
    HttpClient httpClient = new HttpClient();
    GetMethod httpMethod = new GetMethod(apiEndPoint);
    // Return the response body if the request is successfully executed.
    if (httpClient.executeMethod(httpMethod) == HttpStatus.SC_OK) {
    log.trace("Successfully fetched data from the endpoint.");
    return httpMethod.getResponseBodyAsString();
    }
    log.trace("Connection not successful.");
    return StringUtils.EMPTY;
    }
    }


    OSGi Component – Use cases
    Now, you must be wondering, why you shouldn’t be marking every component as service. Yes, you want your objects to be used outside its body. However, in certain use-cases modeling your object as component (not marking it as service) makes sense. Here are a few of them.
    • A server object in your application which listens to a socket.
    • A filter object which intercepts the requests.
    • An object which monitors a resource and report.
    • An Objects which pulls data from the external system and writes to the repository.


    By aem4beginner

    How to Configure an OSGi Service before Starting an AEM Instance

    1. Unpack AEM by running the following command.
    2. java –jar cq-quickstart-6.jar -unpack
    3. Create a folder named crx-quickstart\install in the installation directory.
    4. Create a file with the name <service pid>.cfg. [From AEM 6.0 this should be .config] For example – org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStoreService.cfg in the newly created folder.
    5. Edit the file and set the configuration options line by line.
    6. For example – tarmk.size=256MB


    By aem4beginner

    April 3, 2020
    Estimated Post Reading Time ~

    Generic way to get Service Reference CQ5

    @Reference sometimes fails to get reference out from felix.

    To get away with this problem you can use cardinality. Cardinality ensures that if the service reference is not available then your class will not startup.

    The other way of getting service reference out of any class in a java file is as below.

    This is equivalent to sling.getService in a jsp.

    public static <T> T getServiceReference(final Class<T> serviceClass) {
    T serviceRef;
    /**
    * Get the BundleContext associated with the passed class reference.
    */
    BundleContext bundleContext = FrameworkUtil.getBundle(serviceClass).getBundleContext();
    ServiceReference osgiRef = bundleContext
    .getServiceReference(serviceClass.getName());
    serviceRef = (T) bundleContext.getService(osgiRef);
    return serviceRef;
    }



    By aem4beginner

    April 2, 2020
    Estimated Post Reading Time ~

    Sample runmode-based servlet/component/service restriction

    QuestionAssume you have a couple of OSGi services/servlets within a bundle, among that one of the components required to run in author instance only. What is the best approach to deal with such kind of requirement?

    Note: I have seen some of the implementation checking for specific run modes in the component & it is not a good idea. Also seen some implementation disabled the auto-start option by "@scr.component enabled="false" & then doing the manual task to start the service on the author instance.

    SolutionTake advantage of DS’s built-in integration with the Configuration Admin service. Make the component/servlet require a configuration (policy=ConfigurationPolicy.REQUIRE) and Then create a run mode dependent configuration for that component.

    ConfigurationPolicy REQUIRE implementation exampleStep1: For the component that requires a restriction to run in specific run mode define using OSGi Declarative Services @Component(policy=ConfigurationPolicy.REQUIRE)
     


    Step2: Build a bundle. In Felix console, you will notice the component is not created and will be in the unsatisfied state.

    Step3: In the above example the component blog.sample.MyComponent will only be created if a configuration records with the PID blog.sample.MyComponent exists. Assume you need this component for runmode author only then create the configuration in respective runmode.


    Step4: In the author's instance you will notice component will be created and in a satisfying state.


    Click Here to Download this sample bundle


    By aem4beginner