April 10, 2020
Estimated Post Reading Time ~

Create an AEM (CQ) project using Maven

This article is mainly focused on setting up an only project structure for the CQ/AEM project using maven and guides you through how you can do your day to day development of AEM/CQ project with eclipse. In the next article, we’ll see how to develop templates, components and other things in detail.

Before you go through this article is highly recommended that you have a fair knowledge of Maven and at least the folder structure of an AEM/CQ project. If you are in a hurry, I’ll try to provide a very high-level explanation of these two things but, I’ll recommend you explore that in detail.

1) Typical AEM/CQ project: any web application is mainly composed of view (HTML, JSP, etc.), CSS, JavaScript, and some server-side code. An AEM application is nothing different than this. A typical AEM application will have the following folder structure:
  • /apps (Top level folder that is the parent for all the code that you’ll develop)
  • /apps/[YOUR_APP_NAME]/components/[CQ templates and components] (contains mostly JSP or other scripts responsible for rendering)
  • /apps/[YOUR_APP_NAME]/config (contains configuration for a project)
  • /apps/[YOUR_APP_NAME]/install (contains bundles/jar for server-side logic) /etc/design/[design assets for your site] (Typically all CSS, JavaScript etc. are stored here and access using CQ Client lib. More information about ClientLibs can be found here: http://suryakand-shinde.blogspot.in/2012/01/clientlib-cq-static-resource-management.html)
  • /content/dam/[images, docs, any other digital assets]
  • /content/[YOUR_SITE_ROOT] 
2) A maven is a tool for managing project dependencies, build management and automation framework. There are many maven plugins available in the market to automate various tasks. In this article also we’ll use a few maven plug-ins to automate the task of CQ package creation & installation etc.

Before we go into details, let’s see a few benefits of configuring CQ project with maven and doing development in eclipse:

You can break your project into smaller modules that can be managed individually.
You can do build automation for maven projects easily using Jenkins etc.
Unit testing becomes easier. Writing test cases becomes easier when you have broken down your project in separate modules (components, templates in one module and your java code for bundles in another module) Before we start creating the actual project, the following installations should be there on your machine:

Maven
CQ/AEM author environment

Eclipse with Vault Plug-in (VLT Plug-in for eclipse can be downloaded from http://sourceforge.net/projects/vaultclipse)
Create the AEM/CQ Maven Project Source code for this project can be found here: https://suryakand.googlecode.com/svn/aem/simple-aem-maven-project

We have seen some benefits of maven for CQ projects and have basic knowledge of the CQ project structure by now. Typically, a CQ/AEM Maven project will be a modular maven project with multiple modules. For this article, we’ll create a top-level project that contains two modules “bundles” and “content”.

Follow these steps to create a maven project:
Step 1: Create a maven project using adobe AEM's maven archetype. When you run the command it’ll as for project information on command prompt that you’ll need to provide:
mvn archetype:generate -DarchetypeGroupId=com.day.jcr.vault -DarchetypeArtifactId=multimodule-content-package-archetype -DarchetypeVersion=1.0.2 -DarchetypeRepository=adobe-public-releases

This will create a maven project with two modules one for the bundle and another one for content as shown in Fig: AEM eclipse project. a) content: this is where you'll put your templates, components, etc. b) bundle: all java code that is responsible for creating bundle will go here.

Step 2: Verify the project After the project is created, run the following command just to make sure that everything generated as expected. The build should complete without any error:
mvn clean install

Step 3: Import project into eclipse Once the build is successful, import the project in to eclipse using File-> Import -> Existing Maven Projects -> browse to the directory where you have parent pom.xml file -> Finish


Fig. 1: Typical AEM/CQ project structure

Step 4: Import project into CQ Now that we have a project ready, the next thing that we’ll do is try to install the project (content and bundle) in the local authors (http://localhost:4502). Execute the following command from the directory where we have the parent project’s pom.xml file:
mvn clean install –PautoInstallPackage

NOTE: “autoInstallPackage” is a maven profile that is defined in the “content” project’s pom.xml file. Go to the CRXDLite and check whether the apps folder contains your project or not?

Most of the stuff has been done for us by maven plug-in but, it is important to understand what is going on behind the scene before we start our day to day development so, let’s see what maven did for us. As evident from the screenshot above maven created a parent project with 2 module projects (bundle and content) for us. “bundle” and “content” are also maven projects and they have their own pom.xml file. Let’s look at each pom.xml carefully:

1) pom.xml of parent project: See the comments/NOTE in below XML file for more information about various sections and their usage. I have omitted some part of XML to keep it short so that we can focus on important sections:

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.surya.aem</groupid> <artifactid>blog-sample</artifactid> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Blog Sample - Reactor Project</name> <description>Maven Multimodule project for Blog Sample.</description> <prerequisites> <maven>3.0.2</maven> </prerequisites> <properties> <crx .host="">localhost</crx> <crx .port="">4502</crx> <crx .username="">admin</crx> <crx .password="">admin</crx> <publish .crx.host="">localhost</publish> <publish .crx.port="">4503</publish> <publish .crx.username="">admin</publish> <publish .crx.password="">admin</publish> <project .build.sourceencoding="">UTF-8</project> <project .reporting.outputencoding="">UTF-8</project> </properties> <dependencymanagement> <dependencies> </dependencies> </dependencymanagement> <repositories> <repository> <id>adobe</id> <name>Adobe Public Repository</name> <url>http://repo.adobe.com/nexus/content/groups/public/</url> <layout>default</layout> </repository> </repositories> <pluginrepositories> <pluginrepository> <id>adobe</id> <name>Adobe Public Repository</name> <url>http://repo.adobe.com/nexus/content/groups/public/</url> <layout>default</layout> </pluginrepository> </pluginrepositories> <build> <pluginmanagement> <plugins> <plugin> <groupid>org.apache.sling</groupid> <artifactid>maven-sling-plugin</artifactid> <version>2.1.0</version> <configuration> <username>${crx.username}</username> <password>${crx.password}</password> </configuration> </plugin> <plugin> <groupid>com.day.jcr.vault</groupid> <artifactid>content-package-maven-plugin</artifactid> <version>0.0.20</version> <extensions>true</extensions> <configuration> <failonerror>true</failonerror> <username>${crx.username}</username> <password>${crx.password}</password> </configuration> </plugin> <plugin> <groupid>org.eclipse.m2e</groupid> <artifactid>lifecycle-mapping</artifactid> <version>1.0.0</version> <configuration> </configuration> </plugin> </plugins> </pluginmanagement> </build> <profiles> <profile> <id>autoInstallBundle</id> <build> <plugins> <plugin> <groupid>org.apache.sling</groupid> <artifactid>maven-sling-plugin</artifactid> <executions> <execution> <id>install-bundle</id> <goals> <goal>install</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> </profiles> <modules> <module>bundle</module> <module>content</module> </modules> </project>

2) pom.xml of bundle module:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd "> <modelversion>4.0.0</modelversion> <parent> <groupid>com.surya.aem</groupid> <artifactid>blog-sample</artifactid> <version>1.0-SNAPSHOT</version> </parent> <artifactid>blog-sample-bundle</artifactid> <packaging>bundle</packaging> <name>Blog Sample Bundle</name> <dependencies> </dependencies> <build> <plugins> <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> <plugin> <groupid>org.apache.felix</groupid> <artifactid>maven-bundle-plugin</artifactid> <extensions>true</extensions> <configuration> <instructions> <bundle-symbolicname>com.surya.aem.blog-sample-bundle</bundle-symbolicname> </instructions> </configuration> </plugin> <plugin> <groupid>org.apache.sling</groupid> <artifactid>maven-sling-plugin</artifactid> <configuration> <slingurl>http://${crx.host}:${crx.port}/apps/blog/install</slingurl> <useput>true</useput> </configuration> </plugin> </plugins> </build> </project>

3) pom.xml of the content project:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelversion>4.0.0</modelversion> <parent> <groupid>com.surya.aem</groupid> <artifactid>blog-sample</artifactid> <version>1.0-SNAPSHOT</version> </parent> <artifactid>blog-sample-content</artifactid> <packaging>content-package</packaging> <name>Blog Sample Package</name> <dependencies> <dependency> <groupid>${project.groupId}</groupid> <artifactid>blog-sample-bundle</artifactid> <version>${project.version}</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/content/jcr_root</directory> <filtering>false</filtering> <excludes> <exclude>**/.vlt</exclude> <exclude>**/.vltignore</exclude> </excludes> </resource> </resources> <plugins> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-resources-plugin</artifactid> <configuration> <includeemptydirs>true</includeemptydirs> </configuration> </plugin> <plugin> <groupid>com.day.jcr.vault</groupid> <artifactid>content-package-maven-plugin</artifactid> <extensions>true</extensions> <configuration> <group>Blog Sample</group> <filtersource>src/main/content/META-INF/vault/filter.xml</filtersource> <embeddeds> <embedded> <groupid>${project.groupId}</groupid> <artifactid>blog-sample-bundle</artifactid> <target>/apps/blog/install</target> </embedded> </embeddeds> <targeturl>http://${crx.host}:${crx.port}/crx/packmgr/service.jsp</targeturl> </configuration> </plugin> </plugins> </build> <profiles> <profile> <id>autoInstallPackage</id> <build> <plugins> <plugin> <groupid>com.day.jcr.vault</groupid> <artifactid>content-package-maven-plugin</artifactid> <executions> <execution> <id>install-content-package</id> <phase>install</phase> <goals> <goal>install</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> <profile> <id>autoInstallPackagePublish</id> <build> <plugins> <plugin> <groupid>com.day.jcr.vault</groupid> <artifactid>content-package-maven-plugin</artifactid> <executions> <execution> <id>install-content-package-publish</id> <phase>install</phase> <goals> <goal>install</goal> </goals> 

<configuration> <targeturl>http://${publish.crx.host}:${publish.crx.port}/crx/packmgr/service.jsp</targeturl> 
 <username>${publish.crx.username}</username> <password>${publish.crx.password}</password> 
 </configuration> 
 </execution> </executions> 
 </plugin> 
 </plugins> 
 </build> 
 </profile> 
 </profiles> 
</project>

At this point, you have a working AEM/CQ maven project in eclipse. With this maven project, you can do a lot of things like build automation, better unit testing, and deployment management. One aspect that we have not covered so far is how to use this project for everyday development.

Let’s consider a very common use case. You have an AEM project for which you maintain your source code in SVN (or any other SCM) and you are using eclipse & CRXDELite for development. The reason I mentioned CRXDELite along with eclipse is that there are certain tasks that are easy to perform with CRXDELite e.g. creating a new component or template with a wizard. When you create anything in CRXDELite, you need a way to pull content created in the CQ repository out in the maven project (or file system) so that it can be source controlled in SVN so, how to do that? There are two ways to do this and both these ways use the “vlt” tool provided by AEM/CQ. Here are two ways:
  1. Eclipse Vault (vlt) plug-in OR,
  2. Maven Vault plug-in I’ll try to provide some information on how to use both these methods in my other blog posts as soon as possible.
Source: http://suryakand-shinde.blogspot.com/2014/05/create-aemcq-project-using-maven.html


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.