Showing posts with label OSGi. Show all posts
Showing posts with label OSGi. Show all posts

Saturday, 12 October 2019

Sitemap Scheulder with Factory Configuration using OSGi annotations

Creating Sitemap for an eCommerce website helps in indexing all the product pages by search engine crawlers. There are situations that sitemap should be created for multiple sites, we can achieve this by adding factory=true and bind methods in schedulers.

Let's see how to create sitemap from an product index file using factory.

  1. Create a service config file
  2. Create a scheduler
  3. Create sitemap read and write service interface and implementation
  4. Create models for parsing the index xml file

Sunday, 29 September 2019

Create Product sitemap in AEM

Creating Sitemap for an eCommerce website helps in indexing all the product pages by search engine crawlers.

Let's see how to create sitemap from an product index file.

Create a service config file
Create a scheduler
Create sitemap read and write service interface and implementation
Create models for parsing the index xml file

Sample XML file hosted on a server, we will be configuring this XML hosted URL in Scheduler 
<aemquickstart
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<channel>
<Item>
<title>
<![CDATA[ AEM Quickstart by Kishore ]]>
</title>
<ProductId>12345</ProductId>
<pubDate>02/28/2017 00:00:00.000000</pubDate>
</Item>
<Item>
<title>
<![CDATA[ Lorel Ipsum ]]>
</title>
<ProductId>56789</ProductId>
<pubDate>02/28/2019 00:00:00.000000</pubDate>
</Item>
<Item>
<title>
<![CDATA[ Create Sitemap in AEM ]]>
</title>
<ProductId>12987</ProductId>
<pubDate>03/28/2019 00:00:00.000000</pubDate>
</Item>
</channel>

</aemquickstart>

Wednesday, 4 September 2019

Creating Configuration Factory Service

This post talks about creating Configuration Factory service using OSGI R6 annotations. In order to create this service we need to create a Service Interface and Implementation class.

Let's create a interface to define the configurations


package com.aemquickstart.core.interfaces;

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

@ObjectClassDefinition(name = "AEM Quickstart Site Configs")
public @interface SiteConfigs {
 
  @AttributeDefinition(name="Site Id", description="Site ID")
     String getSiteId() default "aemquickstart";
  @AttributeDefinition(name="Site Name", description="Site Name")
     String getSiteName() default "AEM Quickstart";
}

Monday, 29 October 2018

Annotation @reference is disallowed for this location

Issue: 
Annotation @reference is disallowed for this location.

Solution: 
There are multiple ways to use @Reference annotations in OSGi annotations.

Option 1: 
@Reference
MyService myService;

Option 2:
private MyService myService;
@Reference
public void bindMyService(MyService myService) {
     this.myService = myService;
}
public void unbindMyService(MyService myService) {
     this.myService = myService;
}

To avoid this error use option 2.

Saturday, 4 November 2017

Get properties in AEM sling servlet

Usecase: I had a situation to fetch properties from node/page/cloud configurations from sling servlet. 

Issue: In wcmusepojo we can get these cloud configuarations using getInheritedPageProperties(). But inheritedPageProperties variable is not accessible in osgi service or sling servlet.

Solution:
To get properties of a node/page/cloud configurations from sling servlet do the following.
Below is sample servlet code.
/**
* Author: Kishore Polsani
*/
@Component(name = "com.kishore.aem.GetProperties", label = "Get Properties", immediate = true, metatype = true)
@Service
@Properties({ @Property(name = "service.description", value = "Get Properties"),
            @Property(name = "sling.servlet.paths", value = "/services/aemquickstart/getproperties", propertyPrivate = true),
            @Property(name = "service.vendor", value = "AEMQuickstart")
         })
    public class GetProperties extends SlingAllMethodsServlet implements Serializable {
        private static final long serialVersionUID = 1L;
        private Logger log = LoggerFactory.getLogger(GetProperties.class);
        
        @Reference
        protected SlingRepository repository;
        @Reference
        private ResourceResolverFactory resolverFactory;
        
        @Override
        protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException
                    {
                  
            try {
                Map<String, Object> param = new HashMap<String, Object>();  
                param.put(ResourceResolverFactory.SUBSERVICE, "readService");
                ResourceResolver resourceResolver=null;
                resourceResolver = resolverFactory.getServiceResourceResolver(param);
                /* Get this path from ajax call request*/
                Resource pageResource = resourceResolver.getResource("/etc/cloudservices/salesforce/kishore/jcr:content");
                Node configNode = pageResource.adaptTo(Node.class);
                configNode.getProperty("accesstoken");
                log.info("Access token from cloud config"+configNode.getProperty("accesstoken"));
                Session session = resourceResolver.adaptTo(Session.class);
                session.save();
            } catch (AccessDeniedException e) {
                log.error(e.getMessage());
            } catch (PathNotFoundException e) {
                log.error(e.getMessage());
            } catch (ItemExistsException e) {
                log.error(e.getMessage());
            } catch (ReferentialIntegrityException e) {
                log.error(e.getMessage());
            } catch (ConstraintViolationException e) {
                log.error(e.getMessage());
            } catch (InvalidItemStateException e) {
                log.error(e.getMessage());
            } catch (VersionException e) {
                log.error(e.getMessage());
            } catch (LockException e) {
                log.error(e.getMessage());
            } catch (NoSuchNodeTypeException e) {
                log.error(e.getMessage());
            } catch (LoginException e) {
                log.error(e.getMessage());
            } catch (RepositoryException e) {
                log.error(e.getMessage());
            }
        }   
}

Check this post to get properties in different way: Registering a Servlet for every Page in AEM

Tuesday, 18 July 2017

org.osgi.framework.BundleException: osgi.wiring.package=com.adobe.cq.mcm.salesforce

Sometimes when we try to deploy code, bundles may not be in active state in AEM 6.1. We can see below error message.

Error Message:
18.07.2017 23:44:01.519 *ERROR* [qtp1756110899-265] org.apache.felix.http.jetty %bundles.pluginTitle: Cannot start (org.osgi.framework.BundleException: Unresolved constraint in bundle com.aem.kishore.bundle-core [654]: Unable to resolve 654.1: missing requirement [654.1] osgi.wiring.package; (&(osgi.wiring.package=com.adobe.cq.mcm.salesforce)(version>=1.1.0)(!(version>=2.0.0))))
org.osgi.framework.BundleException: Unresolved constraint in bundle com.aem.kishore.bundle-core [654]: Unable to resolve 654.1: missing requirement [654.1] osgi.wiring.package; (&(osgi.wiring.package=com.adobe.cq.mcm.salesforce)(version>=1.1.0)(!(version>=2.0.0)))

Solution:
  • Delete (or stop) the ''org.eclipse.equinox.region" bundle from the felix.
  • Delete the existing custom bundle.
  • Restart the server (check without restarting) and then redeploy your code bundle.
This bundle has some dependency with eclipse and should not be in AEM6.1, it was meant for AEM 6.2. But somehow it got introduced in this version.

If still issue is not resolved check this post.

Monday, 24 April 2017

AEM OSGI component is not visible

When new AEM project is created we may find OSGI components are not displayed in /system/console/components or in manifest.mf or in bundle.

To avoid this add the below plugin in the parent pom.xml and rebuild the project

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <version>2.3.7</version>
  <configuration>
         <instructions>
                <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                <Embed-Directory>OSGI-INF/lib</Embed-Directory>
                <Embed-Transitive>true</Embed-Transitive>
         </instructions>
  </configuration>
</plugin>

Saturday, 22 April 2017

Integrate AEM with Docusign - Part 1

Integrate AEM with Docusign to get Docusign account information

What is Docusign?

DocuSign® is The Global Standard for Digital Transaction Management. Accessible anytime, anywhere on any device, global enterprises, business departments, individual professionals, and consumers in all industries solve their paper problems by replacing manual, paper-based methods with DocuSign. The result is accelerated transactions that increase speed to results, reduce costs, improve visibility and control, and delight customers. DocuSign helps you keep business digital with the easiest, fastest, most secure way to send, sign, manage and store documents in the cloud.

Why Docusign?



Monday, 10 April 2017

AEM Component is in satisfied state, not in active

Some times we face OSGI component is in active state when the component is installed for the first time. When we modify the component from configMgr, component state changes to satisfied.

To avoid this and make the component in active state add the annotation @Activate to the activate method. This helps in changing the component state to Active whenever the component is modified.

Saturday, 25 March 2017

Access OSGI ser­vice from the WCMUse-class in Sightly

OSGI service are very helpful once its comes to the development of a module. A Service can be used to perform small task like string operations to big like processing shopping cart. For developers who are shifting to Sightly for better development practices and taking advantage of AEM 6.x features, it might be a troublesome that how a OSGI Service can be accessed in Sightly module.
Zoom out a bit and you will be able to see things more clear. Here’s all that needs to be done,
  1. You have to create a OSGI service as usual by creating a interface and implementing it.
  2. Create a class extending WCMUse and get the instance of your OSGI service. 
  3. Class created in step #2, use this in Sightly component to get the values / output

Saturday, 18 March 2017

OSGi Configuration via JCR Nodes

The reasons to configure OSGi services via content nodes is obvious:
  • Configurations are deployed with the code
  • Configurations can be transferred with content packages
  • Configurations can be managed with source control
Defining an OSGi configuration with content nodes is pretty simple:
You create a sling:Folder 'config' and add nodes below it of type sling:OsgiConfig. This node has to have the name of the persistence ID, usually that's the fully qualified class name of the service you want to configure, e.g. com.day.cq.wcm.core.impl.VersionManagerImpl.
Therefore, you can configure the service with an xml file in the folder /apps/yourproject/config with the name com.day.cq.wcm.core.impl.VersionManagerImpl.xml and the following content:
<?xml version="1.0" encoding="UTF-8">
<jcr:root
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primartyType="sling:OsgiConfig"
versionmanager.maxNumberVersions="{Long}5"
versionmanager.ivPaths="/"
versionmanager.purgePaths="[/etc/feeds,/home/users/public,/home/groups/public]"
versionmanager.createVersionOnActivation="{Boolean}true"
versionmanager.maxAgeDays="{Long}3"
versionmanager.purgingEnabled="{Boolean}true" />
You can add factory configurations (multiple settings for one configuration) by adding a unique identifier to the file name, separated by a hyphen. Setting up the MCM configuration e.g. can be done by providing a file named com.day.cq.mcm.impl.MCMConfiguration-myConfiguration.xml. This will create a binding to the configuration.
Only one open topic remains: You usually have one code base, but multiple configuration according to the various systems: An integration test author system has different configurations compared to a production publish system. The instances can be distinguished by using different runmodes, and the configurations can be runmode specific as well:
Just add the name of the runmode the set of configurations apply to the config-folder, like 'config.author' or 'config.publish'. By this you can maintain all applicable configurations in the version control, deploy the code, activate the packages - and the instance itself picks the proper settings. Pretty neat, isn't it?

Managing multiple instances of the same Adobe Experience Manager OSGi service

When developing custom services for Adobe Experience Manager, you can define a service that requires properties that are configured by using the Felix Configuration screen.

AEM Configuration screen

Wednesday, 22 February 2017

Custom bundles are in installed state after AEM server restart

Many a times while working with AEM we find various errors related to bundles.Sometimes it is very dificult to find as to why AEM bundles are going to installed state.

Adobe has given us a HOTFIX for this issue.
"AEM bundles going to installed sate" HOTFIX comes in the form of a small JAR file.
he AEM bundle hotfix comes in the form of org.eclipse.equinox.region jar file. 



Solution 1:

If you have tried other ways and just couldn't get it working and still see various AEM system
bundles in installed state then try to install this JAR into your Felix console /system/console/bundles

Click here to Download Jar

This is a good fix which works most of the time. Also trying this solution will not hurt.You can
always delete the bundle if it didn't do the job. 

NOTE:
AEM will refresh all the bundles. So please wait 5 minutes after installing the Equinox HOTFIX.
Solution 2:
For AEM version 6.1 only.

If the above method didn't resolve your problem then try to remove equinox related JAR file.
Look for a bundle with this name "Region Digraph(org.eclipse.equinox.region)"

Now remove this bundle. Also remove the bundle you installed in Solution 1 if necessary.
Long story short, there should not be any equinox jars installed.

Why this Happens?

According to Adobe the equinox eclipse bundle has some dependency with eclipse and should not be in AEM6.1, it was meant for AEM version 6.2. But this bundle got introduced in this version.

Other Version of Jar file:
1. Click here to Download

Friday, 19 August 2016

Injecting a DataSourcePool Service into an Adobe Experience Manager OSGi bundle



This development article discusses how to inject a DataSourcePool service into an OSGi component. By injecting a DataSourcePool, your OSGi bundle can connect to a relational database such as MySQL. You configure a DataSourcePool using Adobe Experience Manager.

Sunday, 10 January 2016

Create a OSGI Configuration Listener in AEM 6.1

Following article demonstrate business scenario where you need to execute a job, call a method or simply log when there in change in XYZ OSGI configuration. Taking forward the OSGI Configuration Management and Reading of OSGI Configuration, I will show you how you can create a OSGI Configuration listener. Before that’s take a look at below…
ConfigurationListener[Interface] objects are registered with the Framework service registry and are notified with a ConfigurationEvent object when an event is fired. ConfigurationListenerobjects can inspect the received ConfigurationEvent object to determine its type, the pid of theConfiguration object with which it is associated, and the Configuration Admin service that fired the event.
I have used com.day.cq.wcm.notification.email.impl.EmailChannel service but you can use any service based on your requirements and will read property email.from when their is a change. Let’s get started..
1. Create a Service which Implement ConfigurationListener interface

Sunday, 6 December 2015

Creating Adobe CQ OSGi bundles that use the Query Builder API

Discusses how to create an OSGi bundle that contains the AEM Query Builder API. This OSGi operation contains application logic to search the AEM repository. This article also discusses how to create a web page that invokes an operation exposed by the OSGi bundle and display the results in a grid control.    
This article uses an Adobe Maven Archetype project to build an OSGi bundle. If you are not familiar with an Adobe Maven Archetype project, it is recommended that you read the following article: Creating your first AEM Service using an Adobe Maven Archetype project.
This article has been updated to replace the use of a SlingRepository instance with a ResourceResolverFactory instance. TheResourceResolverFactory is used to create a Session instance that is required to use the AEM Query Builder API. Now a Session instance is created by using the adaptTo method:
resourceResolver.adaptTo(Session.class);
This article has been updated to use this Maven command to build the OSGi bundle:
mvn archetype:generate -DarchetypeRepository=https://repo.adobe.com/nexus/content/groups/public/ -DarchetypeGroupId=com.day.jcr.vault -DarchetypeArtifactId=multimodule-content-package-archetype -DarchetypeVersion=1.0.2 -DgroupId=custom.querybuilder -DartifactId=querybuilder -Dversion=1.0-SNAPSHOT -Dpackage=custom.querybuilder -DappsFolderName=myproject -DartifactName="My Project" -DcqVersion="5.6.1" -DpackageGroup="My Company"

Wednesday, 18 November 2015

Reading AEM OSGi Configuration Values

You can define OSGi configuration values by using CRXDE lite and dynamically read these values from within an OSGi service. By defining configuration values, you can define values used by an OSGi service and use these values while the service is running. Unlike hard-coding values in an AEM OSGi service, defining values in CRXDE lite lets you modify configuration values without re-compiling and re-deploying the OSGi bundle.



OSGi configuration values defined at /apps/system/config


As shown in the previous illustration, you can define OSGi configuration values in CRXDE lite. To define configuration values, you define a node of type sling:OsgiConfig. Then you define properties which are the configuration values. 

Configuration values that are defined as properties of a sling:OsgiConfig node


This development article guides you through creating an OSGi bundle that reads OSGi configuration values that are defined in CRXDE lite.

Monday, 16 November 2015

Convert jar files into bundles

There is a community article covering jar to OSGI bundle.
Link:- https://helpx.adobe.com/experience-manager/kb/ConvertAJarIntoOsgiBundle.html
Here's a very simple way of turning an existing jar file in an OSGi bundle, while keeping control on exported packages.
The example creates an OSGi bundle from the attached junit-4.4.jar.
Note: The method below only works in a scenario where the jar file has no dependencies on other external jar files.

  1. Start by creating a the jar's manifest file:
    Manifest-Version: 1.0
    Created-By: myself
    Bundle-ManifestVersion: 2
    Bundle-Name: JUnit 4.4 bundle
    Bundle-Description: Package junit 4.4 in an OSGi bundle
    Bundle-Version: 4.4.0
    Bundle-ClassPath: .,junit-4.4.jar
    Bundle-SymbolicName: org.junit.framework
    Export-Package: junit.framework,junit.extensions,org.junit.runner,org.junit,junit.textui
    
     
    • Bundle-ClassPath header is set to allow embedding the original jar as is. Make sure its value matches the filename of the jar that you are going to embed in the bundle.
    • Export-Package is a list of packages contained in the jar that you would like to make available to other bundles running in the OSGi Container.
  2. Jar file
    Get the jar file, in our case fromhttp://mirrors.ibiblio.org/pub/mirrors/maven2/junit/junit/4.4/junit-4.4.jar
  3. Create the bundle jar file by running the following command:
    jar cvfm junit-4.4-bundle.jar manifest.txt junit-4.4.jar 
    

    Where manifest.txt is the name of the manifest file created above.

    That's it - the resulting jar file (attached to this page as an example) is an OSGi bundle the exports the packages listed in Export-Package above, using the classes of the embedded junit-4.4.jar.

Friday, 13 November 2015

Disabling the XML and JSON render in Adobe CQ5/AEM

To disable the XML or JSON renderer, navigate to the OSGI configuration manager at the following URL:

http://localhost:8080/system/console/configMgr

Click on Apache Sling GET Servlet, uncheck “Enable XML” and Enable JSON , then click save.

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

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 Configuratinn
            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 );
}