Convert an AEM Maven project to an Eclipse-based project

In the previous session, we created an AEM project based on an archetype. We explored the project, deployed it into the Felix console, and then accessed the service it exposed. In this session, we will convert the project into an Eclipse project. So that we can import the project into Eclipse. And, later use Eclipse as an IDE for further learning.

Convert project into an Eclipse project
We can use a Maven command to do this.

  1. Navigate to the project directory.
  2. Execute the following command:
    mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true

The project is converted into a Maven project.

Import project into Eclipse and create a Run configuration

  1. In Eclipse, select Import > Existing Project Into Workspace.
  2. Navigate to the project directory and select Finish.
    Bundle and Content projects get imported into the current workspace.
  3. Update the POM files of respective projects, so the bundle and content are created in the aem-company project (that we have been working with.)
    In the bundles’s POM, update the Sling URL property as follows:

    <slingUrl>http://${crx.host}:${crx.port}/apps/aem-company/install</slingUrl>
  4. In the Content POM, change the target configuration from myproject to aem-company:
    <embeddeds>
        <embedded>
          <groupId>${project.groupId}</groupId>
             <artifactId>myproject-bundle</artifactId>
            <target>/apps/aem-company/install</target>
        </embedded>
     </embeddeds>
  5. Create a Run profile.
  6. Select Run > Run Configuration.
  7. Under Maven Build, right-click > New.
  8. Name it as AEM.
  9. Update Base Directory to your project’s base directory.
  10. Add the following:
    Goal: Install
    Profile: AutoInstallBundle
    Save the configuration.
  11. Using CRXDE Lite, navigate to apps/aem-company.
  12. Create a folder named install.
  13. Now run the configuration.

The project is successfully compiled and deployed into Felix console. You can go to CRXDE Lite and check the Install folder that we created now to see the bundle.
(If you didn’t get it correctly, download the project from my GitHub account.)

Create a bundle for AEM using Maven

In this session, you will learn about developing and deploying bundles for AEM development.

(Following is the transcript of the video above. See the video to get the right context. For sample files, visit GitHub.)

Bundles help to modularize Java development using the Open Source Gateway Initiative (OSGi) framework. A bundle is essentially a Jar file that you deploy in the Apache Felix console. Felix console is the OSGi container.

To make it simpler, to accomplish a complex task, you can deploy a bundle in Felix console that runs with AEM, and then avail the services offered by the bundle. We are not going to explore a lot about OSGi bundles. We will see how a bundle can easily be developed, deployed, and used. You need to have installed Maven in your system. I am not going to talk about how it can be done.
There are plenty of information available in the Internet. Please install Maven.

I am on a Windows machine. After installing Maven, if I run mvn in a command prompt, this the the result that I get. You should see something similar if you had a successful installation and you added it to your class path.

I have created directory, aem-company. This is the company name we used for our sample project. Let me move to the directory.

I will run the following command to create an AEM project. (Please refer the video.) The command is long; I have added the command in my GitHub repository.

Using this command, we will create an AEM project using a Maven archetype. Archytype is a project templating toolkit. Basically, it creates a sample project from which you can start your work.
Note that Adobe provides Archetype repository URL for the developers. I don’t want to explain rest of the parameters. It would be too complex for this session. After running the command, a project structure is created.

Let us explore it further. There are two folders: bundle and content. We will see bundle first. It primarily created a Java project. By default, it added the first Java class that you can use as a start.
You can use this project structure to add more classes.

It created an Interface, HelloService. And, it implements a getRepositoryName() method that should return the underlying repository name. In this case, Apache Jackrabbit Oak is the repository we use.

Go to the Impl folder where we have the actual implementation. @service and @content are two JCR annotations we will see later.

The implementation class has a getRepositoryName() implementation that returns the repository name.
Now, let us deploy the project.

Run the following command: mvn -PautoInstallPackage install
Let us wait for it to complete.

Now log into Apache Felix:
http://localhost:4502/system/console/bundles

Locate the bundle by searching for AEM-Company.
You could see the service we deployed now: com.aemcompany.myproject.HelloService

Let us quickly access the service. I have developed a component that uses the service. Obtain it from my GitHub. I used a JSP page as the component’s default script, since it’s easy to access a Java service in a JSP page.

<%
com.aemcompany.myproject.HelloService repositoryService=sling.getService(com.aemcompany.myproject.HelloService.class);
%>
Hello, <B><%= repositoryService.getRepositoryName() %> </B>

Let us go to the AEM page we created. Drag and drop the component to the page.
Note that it displays the repository name.

Download AEM company training complete package

Download the complete package from my GitHub account. Package name is aem-company-site-1.0.zip. I thought it will help you to learn quickly.
Have a great 2016!!

Access client-side scripts (ClientLib) in AEM

In this post, I will cover an important concept – Client Libraries. Client Libraries are primarily JavaScript libraries that you may need to use while developing components and templates. This is an important concept that we didn’t cover in the first part of the training.

[As usual, the sample package is available in my GitHub account.]

So, let us develop a quiz component to see how client-side libraries are used in AEM. Let me show you what exactly I meant by a Quiz component. See the webpage – it asks you a very basic question: How much is 1 + 1?

quiz-component

After a user selects and submits the answer, it provides a message stating if the answer is correct or not. The code to accomplish this looks like as given below:

<html>
<script type="text/javascript" src="check.js">
</script>
<FORM><B>How much is 1 + 1? </B><P>
 <INPUT TYPE=hidden name="answer" VALUE="2">
 <INPUT TYPE=radio NAME="options" VALUE="1">1<br>
 <INPUT TYPE=radio NAME="options" VALUE="2">2<br>
 <INPUT TYPE=radio NAME="options" VALUE="3">3<br>
 <INPUT TYPE=radio NAME="options" VALUE="4">4<br>
 <INPUT TYPE=button NAME="Validate" VALUE="Validate" onClick="checkAnswer(this.form)">
</FORM>
<html>

When a user clicks the Validate button, the checkAnswer function in check.js is called. (We will see the js later.)

Now, when we covert that into a component, we need to accomplish the following:

  • Authors should be allowed to enter question, options, and an answer. After all, content is created by authors. You are a developer, who develops the component. We have already seen that authors enter content to a component using dialogs. I am not going to elaborate about dialogs this time, though they are an integral part of the Quiz component.
  • After an author enters a question, options, and an answer, we should validate the answer entered by an end user and then show the appropriate message. We need to call a JavaScript function to validate the answer. That’s what exactly I will cover in this post.

It’s not a good practice to save JavaScript into the component’s script directly. We save the script inside a ClientLibrary in AEM. And then, call the script to the component’s page.  I am not going to start from the scratch. See my previous posts to know more about components and dialogs. This where I am:

  • Created a component, named Quiz.
  • Created a touch-optimized dialog that has the following fields: Question, Answer, Option A, Option B, Option C, Option D. (See my previous posts to know the details)
  • Created a js that essentially captures all the variables a user enters in the dialog. (Again see my previous post on the same. I don’t want to repeat that.)
  • In the component’s default script, entered the html code to display questions and options to the end users.

Now, I need to have a JavaScript function to call, when the end-user clicks the validate button. That’s what I am going to show in this video.

  1. Go to the /etc/clientlibs folder.
    You save your client library files here.
  2. Create a cq:ClientLibraryFolder folder named aem-company. (I hope you remember our company name – in this way, we can easily identify the location of all the client library files needed for the project.)
  3.  Add another property, categories which is a string array. Give a name as aemcompany.script.
  4. Create another folder, scripts.
    It’s not a mandatory step. This way, you can provide more modularity.
  5. Create a aemcompany.js file inside. Copy and paste the required script. This is the script you saw at the start of the video.
    function checkAnswer(form) 
    {
      for (var i = 0; i < form.options.length; i++) 
      { 
        if (form.options[i].checked)
        {
        break
        }
      }
      if (form.options[i].value == form.answer.value)
        { 
         alert("You selected the correct answer!! :)") 
         } 
         else 
         { 
         alert("You selected an incorrect answer!!") 
         }
    }
  6. Create a js.txt file inside the ClientLibrary folder and add the following:
    #base=scripts
    aemcompany.js

    It says that js file, aemcompany.js, needs to be picked up from the folder scripts. We are done with creating the js file. Now we need to include this into the component.

  7. Open the Quiz component’s default script and add the following:
    <meta data-sly-use.clientlib=”/libs/granite/sightly/templates/clientlib.html” data-sly-call=”${clientlib.all @ categories=’aemcompany.script’}” data-sly-unwrap></meta>Basically, the following scripts add the category that has the JavaScript that we needed.

To test the component we developed:

  1. Basically, the following scripts add the category that has the JavaScript that we needed.
  2. Right-click and select Edit.
  3. Fill the details.
  4. Select OK
  5. Go to the View mode and test.

As usual, I have uploaded the component to the GitHub account.

 

A quick start to Adobe Experience Manager development

With this post, I am concluding the first learning series on Adobe Experience Manager. The idea is to provide you with a head start if you are new to AEM. I hope it will also help you with the basic concepts if you plan to appear for Adobe Certified Exam (ACE) on AEM component development.

There are 20 blog posts, most of them are associated with a video of 5 to 8 minutes duration. You need to have an AEM install to try out the demos. I have provided you with the sample packages in my GitHub account. In each post, I have specified the package that you need to use. Note that you basically need to install the packages one after another.

Here is a quick overview of the posts:

  1. Why do you need Adobe Experience Manager?
  2. Let us start Adobe Experience Manager
  3. Seeing is believing: Explore the AEM installation directory
  4. Adobe Experience Manager authors, and their templates, and components
  5. Introduction to AEM developers, and their templates and components
  6. Create the first AEM template
  7. Summary – Create templates and use packages
  8. Add the Parsys component to template
  9. Enable components in the Components tab
  10. Apply a design to the AEM Sightly template
  11. Summary: Your first Sightly template
  12. Create your first Sightly component (YouTube component !!!)
  13. Create Adobe Experience Manager dialogs (Add a dialog to the YouTube component)
  14. Get data from a dialog using Sightly (Get a custom URL for the YouTube component)
  15. Add a touch-optimized dialog (for the YouTube component)
  16. Create a design dialog (for the YouTube component)
  17. Learn about Edit Config nodes
  18. The AEM – Sling connection simplified
  19. AEM and OSGi
  20. Access Client-Side Libraries

 

AEM and OSGi

I am sure you would had heard about OSGi, the moment you started searching info related to AEM. It is the final topic for this learning series. Open Source Gateway Initiative (OSGi) provides a modular Java development platform. I don’t want to complicate things here. (This is just a general overview of OSGi.)

When you install AEM, you also install a Felix console. Access the console using the following URL: http://localhost:4502/system/console. It’s more like a server where you can deploy your Java programs as bundles.

You can see a lot of bundles here. Bundles are nothing, but Java programs (jar files) running on the server. Each of these bundles is used for accomplishing a specific task. For example, you want to convert your web page to a pdf, things like that. You can create bundles using Eclipse IDE. Adobe provides a plugin for your aid.

I first thought, I will show you how to develop a bundle, deploy it in this console, and access it in one of our pages. I then thought it would be too much for this introductory session.

For the time being, have a basic idea of the OSGi connection. It helps Java developers to create and deploy Java bundles to perform complex tasks.
In the next learning series, we will create, deploy, and access bundles.

This learning series ends here. Hope you enjoyed.

The AEM – Sling connection simplified

Apache Sling is a web framework based on the JCR API. We have seen that the content in AEM is saved as nodes and properties in Oak – a reference implementation of JCR. In most simple term, Sling, in AEM’s context, helps you to issue http requests and render content from Oak repository appropriately.

Use Template Sling Sample.zip from my GitHub account.

Sling uses scripts or servlets to render content. Sling uses the node’s sling:resourceType property to determine the script that renders the content. Let us see what happens when you access a url.

Assume that you access the following url: http://localhost:4502/content/aem-company.html. First the request goes to /content/aem-company. The node has a sling:resourceType property that points to aem-company/components/homepage. Here Sling gets the location of the script or servlet that needs to be used to render the content. It checks for the location in the apps folder and locate the node. And, then render the content based on the default script, body.html. I have explained how body.html becomes the default script in one of the previous posts. Have a look at that.

  1. Now create another script in aem-company/components/homepage. (test.html)
  2. Add a test content: html test page
  3. Let us access the page again with a different url: http://localhost:4502/content/aem-company.test.html

We changed the url by adding test.html which specifies the default script that needs to be used to render the content. (It’s called a selector.) In this way, you can manipulate the url and provide content accordingly. For example, using the same url, but different selector, like  product.html and product.details.html you can provide different and meaningful content.

  1. Create another script at the same location. (details.jsp)
  2. Add a test content: jsp test page
  3. Access the same using the following url: http://localhost:4504/content/aem-company.details.html

See that the page is rendered. In the same location I mentioned above (/apps/aem-company/components/homepage), Sling searches for details.html, obviously couldn’t find it. It then used details.jsp to render the content.

This kind of script resolution mechanism Sling uses is important for you to know. See a cheat sheet Adobe prepared: http://dev.day.com/content/ddc/blog/2008/07/cheatsheet.html
Take a look at this page – there are plenty of information. I hope you got a general idea about Sling now. Consider it as a starting point & happy learning.

See you soon.

Learn about Edit Config nodes

We have learned about dialogs and design dialogs. In this post, I want to familiarize you with another node, called editConfig.

Let us take a look at the image component.

  1. Drag and drop an image component to the page.
  2. Drag and drop an image to the component.
    The action you performed is drag and drop.

To enable this action in the component, you use a different node.
Let us take a look at the Image component using CRXDE Lite.

  1. Navigate to /libs/wcm/foundation/components/image.
  2. See a node named cq:editConfig.

It has another node named cq:dropTargets which provides this functionality. There is a similar node, cq:inplaceEditing, which allows you to update a text in the component without opening the dialog. You should be aware of editConfig nodes to use it appropriately.

In short, node cq:editConfig provides functionalities, such as drag and drop, in place editing, and so on.

Create a design dialog (for the YouTube component)

In this session, I will introduce you to design dialogs.

Use YouTubeComponent-1.0.5.zip from my GitHub account.

We have seen the dialogs associated with components. They can be Touch-Optimized dialogs or Classic dialogs.

Let us quickly take a look at the page we created. You can see three instances of the same YouTube component. We have entered three different URLs in the dialogs and each of them displays a unique video. Means, whatever you enter for a component’s dialog is specific to that instance of the component. This value is not preserved when you use the same component in the web page again.

In certain situations, you may want to use the same value across all the instances of the component. A classic example would be the company icon of your website. You don’t want it to get changed in all the instances. Wherever you use it, the icon is the same. Let us build something similar to it in our YouTube component. Assume that you want to add a copyright information, which is going to be the same in all instance of the component. You would have guessed it, you need to use design dialogs.

Let us start.

  1. Go to the aem-company folder in CRXDE Lite.
  2. Select youtube.
  3. Copy dialog and paste it at the same place.
    It gets pasted as copy of dialog.
  4. Now rename it as design_dialog.
  5. Expand and select the title node, and rename as copyright.
  6. Similarly, change the name value to copyright.
  7. To access this dialog, go to the web page.
  8. Go to the Classic mode.
  9. Select Design and select Edit.
  10. Now, enter the copyright information: Copyrighted by AEM Company
  11. Click OK.

Nothing happens as expected, because we have not written the logic to capture the data entered and display it on the page. Before we do that, let us first see, where this data is written. We have seen that for dialogs, the data is written within the dialog node itself.

  1. Go to /etc/designs/aem-company/jcr:content/homepage/content/youtube.
    Note that the data from design_dialog is written inside the /etc/designs/aem-company. That’s,it can have only one value.
  2. Open the url.js.
  3. Update the code as follows. (I have commented out the update – we had a discussion on the same code earlier. I am not going to do it again.)
use(function () {
 var CONST = {
 PROP_TITLE: "jcr:title",
 PROP_COPYRIGHT: "jcr:copyright"
 }
 var url = {};
 url.text = granite.resource.properties[CONST.PROP_TITLE]
//Capture value from design_dialog
 url.copyright = currentStyle.get(CONST.PROP_COPYRIGHT, "");
 if (url.text ==null)
 {
 url.text = "https://www.youtube.com/embed/dI1yi2mmNuo";
 }
 // Adding the constants to the exposed API
 url.CONST = CONST;
 return url;
});
  1. Open youtube.html and update.
    <div data-sly-use.url="url.js" style="overflow: hidden;">
     <iframe width="600" height="510" src="${url.text}" frameborder="0" allowfullscreen></iframe>
     <h3>${url.copyright}</h3>
    </div>
  2. Refresh the page.
  3. Note that all videos have been updated with the copyright information.

That’s it. Here is the summary: Design_dialog is used to capture information that should be unique across components. It’s stored in /etc/designs/.

Add a touch-optimized dialog (for the YouTube component)

In this short session, you will learn how to add a touch-optimized dialog for the YouTube component. As I mentioned earlier, a touch-optimized GUI is designed for using in hand-held devices, such as iPad, tablets, and so on.

(I have uploaded the package in GitHub. You should use: YouTubeComponent-1.0.3.zip)

Double-click the component that we developed. The dialog you see is called the Classic dialog. It should ideally come up only if you are in the Classic mode. Right now, you are on Touch-Optimized mode; the Classic dialog comes up here, because we have not created a Touch-Optimized dialog.

Let us start working by logging into CRXDE Lite. We will follow the same strategy we used before. Copy and paste a dialog that is already created, and then customize it.

  1. Go to /libs/wcm/foundation/components/title/.
  2. Copy cq:dialog node from there.
  3. Paste the node under the YouTube component.
  4. Expand the node.
    We need only title node here. (We want users to enter only one property; that’s the url.)
  5. Delete the other node.
  6. Change the following properties to match them with what we entered for Classic dialog:
    FieldDescription: Enter YouTube URL
    FieldLabel: YouTube URL
  7. Now refresh the page.
  8. Select the component and select Edit.
    Note that the dialog has changed.
  9. Now, go to the Classic view and see the dialog.
    You see the classic dialog.

To summarize, cq:dialog is used for Touch-Optimized dialogs. You add various fields to it depending on the requirement. Fields are inherited from granite/ui/components/foundation/form/textfield.

That’s about this session. See you soon.