Article summary

Summary

Discusses how to programmatically retrieve AEM resources from the Java Content Repository (JCR) using Sling APIs. Also discusses how to use the adaptTo method to convert an AEM resource to another type.

Digital Marketing Solution(s) Adobe Experience Manager
Audience
Developer (intermediate)
Required Skills
Java
AEM Versions(s) Adobe Experience Manager 6.4
Video N/A

Introduction

Adobe Experience Manager 6.4 contains a Java Content Repository (JCR) that stores nodes and properties. A node located in the JCR is considered a resource. You can use the JCR API to retrieve resources from the JCR. For information about using the JCR API, see Querying Adobe Experience Manager 6.4 JCR data.

However, you can also retrieve content from the JCR using the Sling Strongly-typed API. In fact, a resource is a central part of Sling and it assumes everything in the JCR is a resource. You can use Sling to retrieve a resource from within an OSGi bundle using the Sling Strongly-typed Java API.

The following example shows the title retrieved from a page node that was retrieved using the Sling API.

client
An Experience Manager component displaying JCR data

Application logic that queries data from the JCR is implemented as an OSGi bundle that is built using Declarative Services (DS) and Maven. DS is used to inject a ResourceResolverFactory instance into the service. The OSGi bundle is a managed component, which means that the OSGi service container creates the ResourceResolverFactory instance.

Create an Experience Manager System User

Create an Experience Manager System User that can access JCR data. The user account must have privileges to acccess the JCR.  

To successfully query JCR data, create an Experience Manager System user by performing these tasks. 

1. Open http://localhost:4502/crx/explorer/index.jsp.

2. Login as admin.

3. Click User Administration.

4. Click Create System User. Name the user data (data is used in this article).

5. Set the UserId. 

6. Click Save

7.  Access the user page at http://localhost:4502/useradmin. 

8.  Select the data user.

9. From the right-hand pane, select the Permissions tab. 

10. Expand the content tab and then select the employees row. 

11. Click all the checkboxes that represent the permissions (click the top row in permissions for this example). 

12. Click the Save button located in the top menu bar (located above the Path heading).  

Configure the Sling Mapper Service

The next step is to configure the Apache Sling Service User Mapper service by adding a new entry. Enter the following value:

slingAPI64.core:datawrite=data

where:

  • slingAPI64.core – is the Bundle-SymbolicName value of the OSGi bundle this is developed in the upcoming sections of this article.
  • datawrite – the name of the sub service (you reference this value in a Java Map object)
  • data – the system user account with data privileges for the JCR 

 

To create an entry in the Apache Sling Mapper service, perform these tasks:

1. Go to the Apache Sling Mapper service at http://localhost:4502/system/console/configMgr. 

2. Click OSGI, Configurations. 

2. Scroll to an entry named Apache Sling Service User Mapper Service.

3. Enter the value slingAPI64.core:datawrite=data.

4. Click Save

Create an Experience Manager Maven 13 archetype project

You can create an Experience Manager archetype project by using the Maven archetype plugin. In this example, assume that the working directory is C:\AdobeCQ. 

Maven
Default files created by the Maven archetype plugin

Note:

Before you can create a Maven archetype project, you need to setup Maven. For details, see Creating an Adobe Experience Manager 6.4 Project using Adobe Maven Archetype 13.

To create an Experience Manager archetype project, perform these steps:

1. Open the command prompt and go to your working directory (for example, C:\AdobeCQ).

2. Run the following Maven command:

mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeGroupId=com.adobe.granite.archetypes -DarchetypeArtifactId=aem-project-archetype -DarchetypeVersion=13 -DarchetypeCatalog=https://repo.adobe.com/nexus/content/groups/public/

3. When prompted, specify the following information:

  • groupId - slingAPI64
  • artifactId - slingAPI64
  • version - 1.0-SNAPSHOT
  • package - com.adobe.aem
  • appsFolderName - slingAPI64
  • artifactName - slingAPI64
  • componentGroupName - slingAPI64
  • contentFolderName - slingAPI64
  • cssId - slingAPI64
  • packageGroup - slingAPI64
  • siteName - slingAPI64

4. When prompted, specify Y.

5. Once done, you will see a message like:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:42 min
[INFO] Finished at: 2016-04-25T14:34:19-04:00
[INFO] Final Memory: 16M/463M
[INFO] ------------------------------------------------------------------------

6. Change the working directory to slingAPI64 and then enter the following command.

mvn eclipse:eclipse

After you run this command, you can import the project into Eclipse as discussed in the next section.

Add Java files to the Maven project using Eclipse

To make it easier to work with the Maven-generated project, import it into the Eclipse development environment, as shown in the following illustration.

project
The Eclipse Import Project dialog

Add the following Java files to the com.adobe.aem.core package:

  • A Java interface named QueryPage.
  • A Java class named QueryPageImp that implements the QueryPage interface.

QueryPage interface

The following code represents the QueryPage interface. 

package com.adobe.aem.core;

public interface QueryPage {
	
	
	public String getJCRData() ;

}

QueryPageImp class

Once you have a Resource instance, you can call the adaptTo method that converts (adapt) the resource to another type. For example, assume that the resource is a page (cq:Page). You can create a com.day.cq.wcm.api.Page instance by calling the adaptTo method as shown in the following example.

//Adapt the resource to another type - in this example to a com.day.cq.wcm.api.page
Page page = res.adaptTo(Page.class);
String title = page.getTitle();

The following Java code represents the QueryPageImp class that uses the Sling API. In this example, a We Retail page is used as an example. 

package com.adobe.aem.core;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.engine.EngineConstants;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference; 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map; 
import java.util.HashMap; 

//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory ; 
import org.apache.sling.api.resource.ResourceResolver; 
import org.apache.sling.api.resource.Resource; 
import com.day.cq.wcm.api.Page; 



import org.apache.jackrabbit.commons.JcrUtils;
import javax.jcr.Session;
import javax.jcr.Node; 
 
@Component
public class QueryPageImp implements QueryPage {
	
	 /** Default log. */
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
             
    private Session session;
                 
    //Inject a Sling ResourceResolverFactory
    @Reference
    private ResourceResolverFactory resolverFactory;
     
	
	public String getJCRData()
	{
		 Map<String, Object> param = new HashMap<String, Object>();
	        param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
	        ResourceResolver resolver = null;
	        String location = "/content/we-retail/us/en/men" ; 
	           
	        try {
	                      
	            //Invoke the adaptTo method to create a Session used to create a QueryManager
	            resolver = resolverFactory.getServiceResourceResolver(param);
	            Resource res = resolver.getResource(location);    
	             
	            //Adapts the resource to another type - in this example to a     com.day.cq.wcm.api.page
	            Page page = res.adaptTo(Page.class);
	            String title = page.getTitle(); // Get the title of the web page
	            return title ; 
	          
	                     
	                        
	        }
	        catch(Exception e)
	        {
	         e.printStackTrace();
	        }
	        return null;
	        }

}

Modify the HelloWorldModel class

The following Java code represents the HelloWorldModel class. This class invokes the custom service and displays the page title. Notice that an instance of the service is obtained using the @Inject annotation.  

package com.adobe.aem.core.models;

import javax.annotation.PostConstruct;
import com.adobe.aem.core.QueryPage; 
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.settings.SlingSettingsService;

@Model(adaptables=Resource.class)
public class HelloWorldModel {

   
	@Inject
	QueryPage page ;  
	
	@Inject
    private SlingSettingsService settings;

    @Inject @Named("sling:resourceType") @Default(values="No resourceType")
    protected String resourceType;

    private String message;

    @PostConstruct
    protected void init() {
        message = "\tHello World!\n";
        message += "\tThis is instance: " + settings.getSlingId() + "\n";
        message += "\tThe page name is : " + page.getJCRData() + "\n";
    }

    public String getMessage() {
        return message;
    }
}

Modify the Maven POM file

Add the following POM dependency to the POM file located at C:\AdobeCQ\slingAPI64.

<dependency>
    <groupId>com.adobe.aem</groupId>
    <artifactId>uber-jar</artifactId>
    <version>6.4.0</version>
    <classifier>apis</classifier>
    <scope>provided</scope>
</dependency>
               
  <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-atinject_1.0_spec</artifactId>
       <version>1.0</version>
       <scope>provided</scope>
   </dependency>

When you add new Java classes under core, you need to modify a POM file to successfully build the OSGi bundle. You modify the POM file located at C:\AdobeCQ\slingAPI64\core. The following code represents this POM file.

<?xml version="1.0" encoding="UTF-8"?>
<!--
 |  Copyright 2017 Adobe Systems Incorporated
 |
 |  Licensed under the Apache License, Version 2.0 (the "License");
 |  you may not use this file except in compliance with the License.
 |  You may obtain a copy of the License at
 |
 |      http://www.apache.org/licenses/LICENSE-2.0
 |
 |  Unless required by applicable law or agreed to in writing, software
 |  distributed under the License is distributed on an "AS IS" BASIS,
 |  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  See the License for the specific language governing permissions and
 |  limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>slingAPI64</groupId>
        <artifactId>slingAPI64</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <artifactId>slingAPI64.core</artifactId>
    <packaging>bundle</packaging>
    <name>slingAPI64 - Core</name>
    <description>Core bundle for slingAPI64</description>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.sling</groupId>
                <artifactId>maven-sling-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <!-- Import any version of javax.inject, to allow running on multiple versions of AEM -->
                        <Import-Package>javax.inject;version=0.0.0,*</Import-Package>
                        <Sling-Model-Packages>
                            com.adobe.aem.core
                        </Sling-Model-Packages>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- OSGi Dependencies -->
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-atinject_1.0_spec</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.cmpn</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>osgi.annotation</artifactId>
        </dependency>
        <!-- Other Dependencies -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.adobe.aem</groupId>
            <artifactId>uber-jar</artifactId>
            <classifier>apis</classifier>
        </dependency>
        <dependency>
            <groupId>org.apache.sling</groupId>
            <artifactId>org.apache.sling.models.api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
        </dependency>
        <dependency>
            <groupId>junit-addons</groupId>
            <artifactId>junit-addons</artifactId>
        </dependency>
    </dependencies>
</project>

Build the OSGi bundle using Maven

To build the OSGi bundle by using Maven, perform these steps:

  1. Open the command prompt and go to the C:\AdobeCQ\slingAPI64.
  2. Run the following maven command: mvn -PautoInstallPackage install.
  3. The OSGi component can be found in the following folder: C:\AdobeCQ\slingAPI64\core\target. The file name of the OSGi component is slingAPI64.core-1.0-SNAPSHOT.jar.

The command -PautoInstallPackage automatically deploys the OSGi bundle to Experience Manager.

After you deploy the OSGi bundle, you will be able to see it in the Apache Felix Web Console (http://localhost:4502/system/console/configMgr).

View the output of the HTL component

To access the component, enter the following URL:

http://localhost:4502/editor.html/content/slingAPI64/en.html

The following illustration shows the HelloWorld HTL component displaying the results of the QueryPage service.

client

See also

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License  Twitter™ and Facebook posts are not covered under the terms of Creative Commons.

Legal Notices   |   Online Privacy Policy