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

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

Thursday, 12 November 2015

Creating OSGi Bundles

Problem: I have a third party Java library that I need to use in my CQ component.  It’s available as a standard jar file. I want to drop this in a lib folder somewhere and have access to the classes. But AEM doesn’t support libraries this way. How do I import and use this code?
Solution: AEM manages libraries as OSGi bundles.  OSGi bundles are essentially the same thing as standard jar files, but they contain extra metadata. This metadata relates to versioning and dependencies, and is stored in a jar’s \META-INF\MANIFEST.MF file.  AEM requires this metadata, so in order to use a third-party jar library in AEM, you must add that to the library’s jar file, turning it into what’s called an OSGi bundle.
How: Our case study will be a Java API for a third-party mailing list manager:  Ecwid’s MailChimp API.
Note that if all you want is a quick step-by-step solution, without images or explanations, seehere.
Step 0: Since the source code for our third party library happens to be stored in git, and happens to be compiled with maven, we’ll need to install clients for each.  I’ll be using the windows command line clients with cygwin.
Step 1:  Build and compile the library
mailchimp-step-1
git clone https://github.com/Ecwid/ecwid-mailchimp.git
Note that the URL was simply copied from “clone URL” field on the repository page linked above
cd ecwid-mailchimp
mvn clean package dependency:copy-dependencies -DskipTests=true
Note that I skipped the tests because they break without some API key configuration (which we can do later) and copy the dependencies for a reason I’ll explain in the next step.
Step 2: Figure out how to create a OSGi bundle jar file
There are many ways to build a jar as an OSGi bundle.  Here’s what we will not be doing
a) Manually writing up the MANIFEST.MF file.  This is untenable for even slightly complicated OSGi bundles because the file format is so fickle.  And mistakes don’t yield friendly errors.
b) Use a Maven OSGi plugin and modify the project poms.  Configuring this the first time can be nearly as complicated as manually building the manifest file.
c) Use bndtools to create one.  This is a good tool but is kind of indiscriminate into what it includes as dependencies.  This brings us to our next problem.
Problem: OSGi bundles won’t load unless their dependencies are loaded as OSGi bundles.
“Ideal” Solution: Track down each of the dependencies and recompile those as OSGi bundles.  Do the same for each of their dependencies, all the way down the chain.  In an ideal world, all jars would be OSGi capable.  But few libraries are currently packaged this way, and we’re not going to spend this kind of time on code that’s not ours.
Quick and Dirty Solution: Package the main jar and all its dependency jars as a single, combined OSGi bundle.  (Note how we explicitly copied those dependency jars in the maven command above).  There are downsides, and this defeats some of the points to OSGi dependency management, but it’s the most practical solution for moderately complex libraries.
Why are we downloading a specialized version of Eclipse for something seemingly unrelated to what we’re doing?  Because it has a fantastic OSGi builder and interface!  Download and install the latest version somewhere.  Then open it.
Note that you can also just add “Eclipse Plug-in Devlopment Environment” to your existing Eclipse environment.
Step 3: Create OSGi project in Eclipse
New -> Other -> Plugin Development -> Plug-in from Existing JAR Archives
Add External
Select all the jars in the target folder (target\ecwid-mailchimp-2.0.0.1-SNAPSHOT.jar and target\dependencies\*.jar)
Set a project name
Check "Analyze library contents and add dependencies"
Select "an OSGi framework"
Select "standard"
Uncheck "Unzip the JAR..."
Finish
Step 4: Export the project as an OSGi bundle
Right click on project -> Export
Plug-in Development -> Deployable plug-ins and fragments
Select a directory
Click Finish
Open that directory -> Plugin folder
Copy the jar file
Step 5: Install the OSGi bundle into CQ
Open CRXDE
Navigate to apps\(project)\install
Paste jar file
Step 6: Verify OSGi bundle deployed in CQ
Open CQ OSGi Console
OSGi -> Bundles
Type "mailchimp" (or whatever project name was) into search bar and click "Apply Filter"
Use arrow to expand description of bundle
Scroll through imported packages
Note anything that is highlighted in red because it's unresolvable
Go back into eclipse and the OSGi project
Click "dependencies"
Remove the project dependencies under Imported Packages
Step 7: Redeploy OSGi bundle
Export OSGi bundle again from Eclipse as in previous step
Open CRXDE and delete the old OSGi bundle
Copy-paste the new one in
Verify no issues and an Active status within CQ's OSGi console
Step 8: Use it in a component.
Here’s some sample code from a component jsp that consumes this library, along with its position relative to the OSGi jar.
structure
<%@include file="/apps/cardinal/global.jsp"%>
<%@ page import="com.ecwid.mailchimp.*,
com.ecwid.mailchimp.method.list.*" %><%
%>
<%
String apikey = currentStyle.get("apikey", "null");
String listid = properties.get("listid", "null");
MailChimpClient mailChimpClient = new MailChimpClient();
ListsMethod listsMethod = new ListsMethod();
listsMethod.apikey = apikey;
ListsMethodFilters listsMethodFilters = new ListsMethodFilters();
listsMethodFilters.list_id = listid;
listsMethod.filters = listsMethodFilters;
ListsResult listsResult = mailChimpClient.execute(listsMethod);
String listUrl = listsResult.data.get(0).subscribe_url_short;
%>
Conclusion:
Adding third party code to CQ the “right way” isn’t necessarily trivial, but using some standard tools can be done without too much overhead. Suggestions and questions are welcome; based on feedback I may be appending or following up on this topic with more details and explanations.