Article summary

Summary
Discusses how to create an Adobe Experience Manager mobile form that lets mobile users submit data to Experience Manager. The mobile form is developed by using the JQuery Mobile API. The submitted data is stored in the Experience Manager JCR.
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
Java, Maven, JQuery Mobile API
Version Experience Manager  5.6

Introduction

You can create an Experience Manager mobile form using the JQuery Mobile API. When a mobile user fills in the form and clicks the submit button, the form data is submitted to Experience Manager. You can develop an OSGi bundle operation to process the submitted form data to meet your business requirements. For example, consider the following mobile insurance claim form.

MobileForm

When a mobile user fills in this mobile claim form and submits the data, an OSGi bundle processes the data by persisting it in the Adobe JCR. A claim number is generated on the server and returned to the mobile device and displayed in the first field (see the previous illustration).

This development article guides you through creating a mobile form using the JQuery Mobile API and an OSGi bundle that handles the form submission. The JCR application logic is implemented as an OSGi bundle that is built using Declarative Services (DS) and Maven. DS is used to inject a SlingRepository instance into the service. The OSGi bundle is a managed component, which means that the OSGi service container creates the SlingRepository instance.

Note:

To simplify the way claim data submitted from mobile devices is persisted, the data is stored as nt:unstructured nodes under /content/claims.

Create an application folder structure

Create an application folder structure that contains templates, components, and pages by using CRXDE Lite.

CQAppSetup

The following describes each application folder:

  • application name: contains all of the resources that an application uses. The resources can be templates, pages, components, and so on.
  • components: contains components that your application uses. 
  • page: contains page components. A page component is a script such as a JSP file. 
  • global: contains global components that your application uses.
  • template: contains templates on which you base page components. 
  • src: contains source code that comprises an OSGi component (this development article does not create an OSGi bundle using this folder). 
  • install: contains a compiled OSGi bundles container.

To create an application folder structure:

  1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.
  2. Select CRXDE Lite.
  3. Right-click the apps folder (or the parent folder), select Create, Create Folder.
  4. Enter the folder name into the Create Folder dialog box. Enter mobile
  5. Repeat steps 1-4 for each folder specified in the previous illustration. 
  6. Click the Save All button.

Note:

You have to click the Save All button when working in CRXDE Lite for the changes to be made.

Create a template

You can create a template by using CRXDE Lite. A template enables you to define a consistent style for the pages in your application. A template comprises of nodes that specify the page structure. For more information about templates, see Templates.

To create a template, perform these tasks:

1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click the template folder (within your application), select Create, Create Template.

4. Enter the following information into the Create Template dialog box:

  • Label: The name of the template to create. Enter templateMobile
  • Title: The title that is assigned to the template.
  • Description: The description that is assigned to the template.
  • Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter mobile/components/page/templateMobile.
  • Ranking: The order (ascending) in which this template will appear in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.

5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.

6. Click Next for Allowed Parents.

7. Select OK on Allowed Children.

Create a render component that uses the template

Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as an AEM developer to create scripts that perform specific functionality. For more information about components, see Components.

By default, a component has at least one default script, identical to the name of the component. To create a render component, perform these tasks:

1. To view the welcome page, enter the URL http://[host name]:[port] into a web browser. For example, http://localhost:4502.

2. Select CRXDE Lite.

3. Right-click /apps/mobile/components/page, then select Create, Create Component.

4. Enter the following information into the Create Component dialog box:

  • Label: The name of the component to create. Enter templateMobile
  • Title: The title that is assigned to the component.
  • Description: The description that is assigned to the template.

5. Select Next for Advanced Component Settings and Allowed Parents.

6. Select OK on Allowed Children.

7. Open the templateJCR.jsp located at: /apps/mobile/components/page/templateMobile/templateMobile.jsp.

8. Enter the following HTML code.

<html>
<head>
<title>Adobe Experience Manager Mobile Form</title>
</head>
<body>
<h1>Hello AEM Mobile!!!</h1>
<h2>This page will become a mobile form that lets users submit data</h2>
</body>
</html>

Setup Maven in your development environment

You can use Maven to build an OSGi bundle that uses the JCR API and is deployed to Experience Manager. Maven manages required JAR files that a Java project needs in its class path. Instead of searching the Internet trying to find and download third-party JAR files to include in your project’s class path, Maven manages these dependencies for you.

You can download Maven 3 from the following URL:

http://maven.apache.org/download.html

After you download and extract Maven, create an environment variable named M3_HOME. Assign the Maven install location to this environment variable. For example:

C:\Programs\Apache\apache-maven-3.0.4

Set up a system environment variable to reference Maven. To test whether you properly setup Maven, enter the following Maven command into a command prompt:

%M3_HOME%\bin\mvn -version

This command provides Maven and Java install details and resembles the following message:

Default locale: en_US, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

Note:

For more information about setting up Maven and the Home variable, see: Maven in 5 Minutes.

Next, copy the Maven configuration file named settings.xml from [install location]\apache-maven-3.0.4\conf\ to your user profile. For example, C:\Users\scottm\.m2\.

You have to configure your settings.xml file to use Adobe’s public repository. For information, see Adobe Public Maven Repository at http://repo.adobe.com/.

Create an Adobe Experience Manager archetype project

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

Maven

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 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=com.adobe.cq.mobile -DartifactId=mobile -Dversion=1.0-SNAPSHOT -Dpackage=com.adobe.cq.mobile -DappsFolderName=myproject -DartifactName="My Project" -DcqVersion="5.6.1" -DpackageGroup="My Company"

3. When prompted for additional information, specify Y.

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

[[INFO] Total time: 14:46.131s
[INFO] Finished at: Wed Mar 27 13:38:58 EDT 2013
[INFO] Final Memory: 10M/184M

5. Change the command prompt to the generated project. For example: C:\AdobeCQ\mobile. Run the following Maven 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.

JavaProject

The next step is to add Java files to the com.adobe.cq.mobile package. The Java files that you create in this section use the Java JCR API. For information, see http://www.day.com/maven/jsr170/javadocs/jcr-2.0/overview-summary.html.

Add the following Java files to the com.adobe.cq.mobile package:

  1. A Java interface named ClaimService.
  2. A Java class named ClaimServiceImpl that implements the ClaimService interface.

ClaimService interface

The following code represents the ClaimService interface. This interface contains a method signature named createClaim. The implementation logic for this method is located in the ClaimServiceImp class. This method uses the JCR API to store data submitted from the mobile device into the Experience Manager JCR.

package com.adobe.cq.mobile;

public interface ClaimService {
		
	//Creates a new claim (passed from a mobile device) and returns a 
	//claim identifier value
	public String createClaim(
                    String last, 
                    String first, 
                    String date, 
                    String address, 
                    String city, 
                    String state, 
                    String cat,
                    String details );
}

The createClaim method creates a new claim in Experience Manager. This method accepts the following values:

  • A String value that represents the user's last name.
  • A String value that represents the user's first name.
  • A String value that represents the date.
  • A String value that represents the user's address.
  • A String value that represents the user's city.
  • A String value that represents the user's state.
  • A String value that represents the cliam category. In this example, a category value is one of these values: auto, home, boat, and life.
  • A String value that provides additional details about the claim.

The createClaim method is invoked from the mobile form.

ClaimServiceImpl class

The ClaimServiceImp class uses the following Apache Felix SCR annotations to create the OSGi component:

  • @Component – defines the class as a component
  • @Service - defines the service interface that is provided by the component
  • @Reference – injects a service into the component.

In this development article, a SlingRepository instance is injected into the createClaim method. This instance is required to perform JCR operations from within an OSGi bundle. To inject a SlingRepository instance, you use the @Reference annotation to define a class member, as shown in the following example.

@Reference
private SlingRepository repository;

To successfully use service injection, define another method in the ClaimServiceImpl class named bindRepository. This method binds a SlingRepository instance to the class member that uses the @Reference annotation.

public void bindRepository(SlingRepository repository) {
        this.repository = repository;
        }

Within the createClaim method, use the SlingRepository to create a Session object, as shown here.

//Creates a new claim (submitted from a mobile device) and returns a 
//claim identifier value
public String CreateClaim(String last, String first, String date,
String address, String city, String state, String cat,
String details) {
    try { 
	    Session session = this.repository.loginAdministrative(null);

This is the main difference between using the JCR API from within an OSGi bundle as opposed to using the JCR API from an external Java application. If you are using the JCR API from an external Java application, you can create a Session object by using the following code.

//Create a connection to the CQ repository running on local host
 Repository repository = JcrUtils.getRepository("http://localhost:4503/crx/server");
    
//Create a Session
javax.jcr.Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()));

However, this code throws an exception if you use it from within a deployed OSGi bundle. To successfully use the JCR API from within a deployed OSGi bundle, you inject the SlingRepository as discussed in this article. For information about using the JCR API from an external Java application, see http://scottsdigitalcommunity.blogspot.ca/2012/03/programmatically-accessing-day-cq.html.

The following Java code represents the ClaimServiceImp class. For each submitted claim (from a mobile device), a new node is created at /content/claim. In this example, each claim identifier value is created by invoking the UUID.randomUUID().toString() method. The createClaim method returns this value (this value is displayed in the mobile form).

package com.adobe.cq.mobile;

import java.util.Iterator;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.commons.JcrUtils;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.sling.jcr.api.SlingRepository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Node; 
import org.apache.jackrabbit.commons.JcrUtils;
import java.util.Iterator;
import java.util.UUID;
 
//This is a component so it can provide or consume services
@Component
// This component provides the service defined through the interface
@Service

public class ClaimServiceImpl implements ClaimService {
	
	
	/** Default log. */
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	     
	@Reference
	private SlingRepository repository;
	     
	public void bindRepository(SlingRepository repository) {
	    this.repository = repository; 
	    }

	//Creates a new claim (submitted from a mobile device) and returns a 
	//claim identifier value
	public String CreateClaim(String last, String first, String date,
			String address, String city, String state, String cat,
			String details) {
		try { 
		    Session session = this.repository.loginAdministrative(null);
		              
		    //Generate claim Id - this method returns this value
		    String uuid = UUID.randomUUID().toString();
		    
		    //Create a node that represents the root node
		    Node root = session.getRootNode(); 
		               
		    //Get the content node in the JCR
		    Node content = root.getNode("content");
		                
		    //Determine if the content/claim node exists
		    Node claimRoot = null;
		    int claimRec = doesClaimExist(content);
		                                      
		    //-1 means that content/claim does not exist
		    if (claimRec == -1)
		     {
		       //content/claim does not exist -- create it
		    	claimRoot = content.addNode("claim");
		       }
		       else
		       {
		       //content/claim does exist -- retrieve it
		    	claimRoot = content.getNode("claim");
		       }
		                
		     String claimId = uuid; //assign claim id
		                
		     //Store claim data submitted from the CQ mobile form
		    Node claimNode = claimRoot.addNode("claim_"+uuid); 
		         
		    //make sure name of node is unique
		    //String last, String first, String date, String address, String city, String state, String cat,String details );
		    claimNode.setProperty("id", claimId); 
		    claimNode.setProperty("firstName", first); 
		    claimNode.setProperty("lastName", last); 
		    claimNode.setProperty("date", date);  
		    claimNode.setProperty("address", address);
		    claimNode.setProperty("city", city);
		    claimNode.setProperty("state", state);
		    claimNode.setProperty("cat", cat);
		    claimNode.setProperty("details", details);
		                              
		    // Save the session changes and log out
		    session.save(); 
		    session.logout();
		    return claimId; 
		    }
		 
		 catch(RepositoryException  e){
		     log.error("RepositoryException: " + e);
		      }
		 return "no claim id" ; 
		 } 

	/*
	 * Determines if the content/claim node exists 
	 * This method returns these values:
	 * -1 - if content/claim does not exist
	 * 0 - if content/claim node exists; however, contains no children
	 * number - the number of children that the content/claim node contains
	*/
	private int doesClaimExist(Node content)
	{
	    try
	    {
	        int index = 0 ; 
	        int childRecs = 0 ; 
	         
	    java.lang.Iterable<Node> claimNode = JcrUtils.getChildNodes(content, "claim");
	    Iterator it = claimNode.iterator();
	              
	    //only going to be 1 content/claim node if it exists
	    if (it.hasNext())
	        {
	        //Count the number of child nodes in content/claim
	        Node claimRoot = content.getNode("claim");
	        Iterable itCust = JcrUtils.getChildNodes(claimRoot); 
	        Iterator childNodeIt = itCust.iterator();
	             
	        //Count the number of claim child nodes 
	        while (childNodeIt.hasNext())
	        {
	            childRecs++;
	            childNodeIt.next();
	        }
	         return childRecs; 
	       }
	    else
	        return -1; //content/claim does not exist
	    }
	    catch(Exception e)
	    {
	    	e.printStackTrace();
	    }
	    return 0;
	 }
	}

Modify the Maven POM file

Modify a Maven POM file to successfully build the OSGi bundle. In the POM file located at C:\AdobeCQ\mobile\bundle, add the following dependencies:

  • org.apache.felix.scr
  • org.apache.felix.scr.annotations
  • org.apache.jackrabbit
  • org.apache.sling

The following XML represents this POM file.

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd ">
    <modelVersion>4.0.0</modelVersion>
    <!-- ====================================================================== -->
    <!-- P A R E N T P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->
    <parent>
        <groupId>com.adobe.cq.mobile</groupId>
        <artifactId>mobile</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- ====================================================================== -->
    <!-- P R O J E C T D E S C R I P T I O N -->
    <!-- ====================================================================== -->

    <artifactId>mobile-bundle</artifactId>
    <packaging>bundle</packaging>
    <name>My Project Bundle</name>

   <dependencies>
       <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.scr.annotations</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
           
        <dependency>
         <groupId>org.apache.felix</groupId>
    
         <artifactId>org.osgi.core</artifactId>
    
         <version>1.4.0</version>
      </dependency>
          
         
           
    <dependency>
    <groupId>org.apache.jackrabbit</groupId>
    <artifactId>jackrabbit-core</artifactId>
    <version>2.4.3</version>
    </dependency>
        
    <dependency>
    <groupId>org.apache.jackrabbit</groupId>
    <artifactId>jackrabbit-jcr-commons</artifactId>
    <version>2.4.3</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.sling</groupId>
        <artifactId>org.apache.sling.jcr.api</artifactId>
        <version>2.0.4</version>
      </dependency>
          
      <dependency>
         <groupId>javax.jcr</groupId>
         <artifactId>jcr</artifactId>
         <version>2.0</version>
      </dependency>
    </dependencies>
    <!-- ====================================================================== -->
    <!-- B U I L D D E F I N I T I O N -->
    <!-- ====================================================================== -->
    <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.adobe.cq.mobile.mobile-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/myproject/install</slingUrl>
                    <usePut>true</usePut>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                 <configuration>
                    <excludePackageNames>
                        *.impl
                    </excludePackageNames>
                 </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Build the OSGi bundle using Maven

Build the OSGi bundle by using Maven. When you build the OSGi bundle, Maven creates the required serviceComponents.xml file based on the annotations that are included in the ClaimServiceImp class. The following XML represents this file.

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
    <scr:component enabled="true" name="com.adobe.cq.mobile.ClaimServiceImpl">
        <implementation class="com.adobe.cq.mobile.ClaimServiceImpl"/>
        <service servicefactory="false">
            <provide interface="com.adobe.cq.mobile.ClaimService"/>
        </service>
        <property name="service.pid" value="com.adobe.cq.mobile.ClaimServiceImpl"/>
        <reference name="repository" interface="org.apache.sling.jcr.api.SlingRepository" cardinality="1..1" policy="static" bind="bindRepository" unbind="unbindRepository"/>
    </scr:component>
</components>

There are a couple of points to note about this XML file. First, notice that the implementation class element specifies com.adobe.cq.mobile.ClaimServiceImp. The service element contains an interface attribute that specifies com.adobe.cq.mobile.ClaimService. This lines up with the Java interface that was created in an earlier step.

In order for the service injection to work, the reference element must be configured correctly. In this example, notice that name of the reference is repository. Also notice that it’s based on org.apache.sling.jcr.api.SlingRepository. Finally the bind element specifies the Java method (in this example, bindRepository) located in the ClaimServiceImp class that binds the reference.

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

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

Deploy the bundle to Experience Manager

Once you deploy the OSGi bundle, you can invoke the createClaim method defined in the ClaimServiceImpl class (this is shown later in this development article). After you deploy the OSGi bundle, you can view it in the Apache Felix Web Console.

OSGiMobile

You will also be able to view the service defined in the OSGi bundle by using the Service tab in the Apache Felix Web Console.

OSGIServices

Note:

To view the services, simply click the Services tab.

Deploy the new OSGi bundle to Experience Manager  by performing these steps:

  1. Login to the Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).
  2. Click the Bundles tab, sort the bundle list by Id, and note the Id of the last bundle.
  3. Click the Install/Update button.
  4. Browse to the bundle JAR file you just built using Maven. (C:\AdobeCQ\mobile\bundle\target).
  5. Click Install.
  6. Click the Refresh Packages button.
  7. Check the bundle with the highest Id.
  8. Click Active.
  9. Your new bundle should now be listed with the status Active.
  10. If the status is not Active, check the error.log for exceptions.

 

Note:

The name of the service defined within the OSGi bundle is com.adobe.cq.mobile.ClaimService.

Modify the templateMobile to invoke the createClaim method

To create the JQuery mobile form that lets mobile users submit data, create these files:

  • mobile.json.jsp: contains application logic that invokes the OSGI bundle’s createClaim method. 
  • templateMobile.jsp: contains application logic that uses the JQuery Mobile API to create a mobile form. This form lets a mobile user create a claim. The claim number is generated on the server and displayed within this form. 

Create the mobile.json.jsp

Add a new JSP file named mobile.json.jsp to the following path:

/apps/mobile/components/page/templateMobile

In mobile.json.jsp, you create a ClaimService instance by using the sling.getService method, as shown in the following example:

com.adobe.cq.mobile.ClaimService cs = sling.getService(com.adobe.cq.mobile.ClaimService.class);

You pass the fully qualified name of the service to sling.getService method. Because the OSGi bundle is a managed component that injects a SlingRepository into the service, you must use the sling.getService method to create a ClaimService object. If you attempt to create a ClaimService using the new operation, the OSGi bundle is not considered a managed component and will not successfully inject a SlingRepository instance. A Java null pointer exception is thrown.

After you create a ClaimService object by using sling.getService, you can invoke the createClaim method exposed by the service. You pass the following values to this method:

  • A String value that represents the user's last name.
  • A String value that represents the user's first name.
  • A String value that represents the date.
  • A String value that represents the user's address.
  • A String value that represents the user's city.
  • A String value that represents the user's state.
  • A String value that represents the cliam category. In this example, a category value is one of these values: auto, home, boat, and life.
  • A String value that provides additional details about the claim.

The following code represents the mobile.json.jsp file.

<%@include file="/libs/foundation/global.jsp"%>
<%@ page import="org.apache.sling.commons.json.io.*,com.adobe.cq.mobile.*" %><%
String first = request.getParameter("first");
String last = request.getParameter("last");
String address = request.getParameter("address");
String city = request.getParameter("city");
String details = request.getParameter("details");
String state = request.getParameter("state");
String date = request.getParameter("date");
String cat =  request.getParameter("cat");

//Create a ClaimService instance
com.adobe.cq.mobile.ClaimService cs = sling.getService(com.adobe.cq.mobile.ClaimService.class);
 
String claimId = cs.CreateClaim(last,first, date,address, city, state, cat, details) ; 
  
//Send the data back to the client 
JSONWriter writer = new JSONWriter(response.getWriter());
writer.object();
writer.key("claimId");
writer.value(claimId);
 
writer.endObject();
%>

In this code example, notice that a JSONWriter instance is created. This object is used to return data to the main JSP client after the call to the OSGi bundle is made.

Modify the templateMobile.jsp

Modify the templateMobile.jsp file to call the mobile.json.jsp when the submit button is clicked. In this example, a JQuery Ajax HTTP request is used and the required values are passed to the mobile.json.jsp. This code shows the submit method that is called when the user fills in the data and clicks the submit button.

$('#submit').click(function() {
    var failure = function(err) {
             alert("Unable to retrive data "+err);
   };

    //Get the values from the mobile JQuery form
    var myFirst= $('#FirstName').val() ; 
    var myLast= $('#LastName').val() ; 
    var date= $('#DateId').val() ; 
    var cat= $('#Cat_Id').val() ; 
     var state= $('#State_Id').val() ; 
     var details= $('#Explain').val() ; 
     var city= $('#City').val() ; 
     var address= $('#Address').val() ; 

     var url = location.pathname.replace(".html", "/_jcr_content.mobile.json") + "?first="+ myFirst + "&last="+ myLast + "&address="+ address + "&city="+ city + "&details="+ details + "&state="+ state + "&date="+ date + "&cat="+ cat;

    $.ajax(url, {
        dataType: "text",
        success: function(rawData, status, xhr) {
            var data;
            try {
                data = $.parseJSON(rawData);
                                 
                //Set the fields in the forum
                $('#ClaimNum').val(data.claimId); 
             } catch(err) {
                failure(err);
            }
        },
        error: function(xhr, status, err) {
            failure(err);
        } 
    });
  });

The following code represents the entire templateMobile JSP file. Notice that the JQuery Mobile API and CSS files are referenced using an URL.

<%@include file="/libs/foundation/global.jsp"%>
<html>
  
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
<div>
      
<link href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css" rel="stylesheet">
      
<link href="css/colors.css" rel="stylesheet">
      
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
      <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.3/jquery-ui.min.js" type="text/javascript"></script>
      <script src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
    

  <script>
$(document).ready(function() {

    $('body').hide().fadeIn(5000);
       
$('#submit').click(function() {
    var failure = function(err) {
             alert("Unable to retrive data "+err);
   };

    //Get the user-defined values to persist in the database
    var myFirst= $('#FirstName').val() ; 
    var myLast= $('#LastName').val() ; 
    var date= $('#DateId').val() ; 
    var cat= $('#Cat_Id').val() ; 
     var state= $('#State_Id').val() ; 
     var details= $('#Explain').val() ; 
     var city= $('#City').val() ; 
     var address= $('#Address').val() ; 

    var url = location.pathname.replace(".html", "/_jcr_content.mobile.json") + "?first="+ myFirst + "&last="+ myLast + "&address="+ address + "&city="+ city + "&details="+ details + "&state="+ state + "&date="+ date + "&cat="+ cat;

    $.ajax(url, {
        dataType: "text",
        success: function(rawData, status, xhr) {
            var data;
            try {
                data = $.parseJSON(rawData);
                                 
                //Set the fields in the forum
                $('#ClaimNum').val(data.claimId); 
             } catch(err) {
                failure(err);
            }
        },
        error: function(xhr, status, err) {
            failure(err);
        } 
    });
  });
   
}); // end ready
</script>
</head>
  
<title>formTitle</title>
  
<body>
    
<div data-role="page" data-theme="a">
      
<div data-role="content" id="contentMain" name="contentMain">
        
<div data-nobackbtn="true" data-role="header" id="hdrMain" name="hdrMain">
          
<h1>Adobe CQ Mobile Claim Form</h1>
        
</div>
        
<form method="#">
  
      
<div data-role="fieldcontain" id="RequestNumDiv">
            
<label for="ClaimNum" id="ClaimNumLabel" name="ClaimNumLabel">A. Claim Number      </label>
            <input id="ClaimNum" name="A1. Claim Number" readonly=true type="text" value="">
          
</div>

<div data-role="fieldcontain" id="ProjectTitleDiv">
            
<label for="DateId" id="DateIncident" name="DateIncident">A.2. Date of Incident     </label>
            <input id="DateId" name="A.2 Date of Incident     " type="text" value="">
          
</div>    
          
<div data-role="fieldcontain" id="RequestTitleDiv">
            
<label for="FirstName" id="FirstNameLabel" name="FirstNameLabel">B2. First Name     </label>
            <input id="FirstName" name="B1. First Name    " type="text" value="">
          
</div>
          
<div data-role="fieldcontain" id="LastNameDiv">
            
<label for="LastName" id="LastNameLabel" name="LastNameeLabel">C1. Last Name     </label>
            <input id="LastName" name="C1. Last Name     " type="text" value="">
          
</div>
          
<div data-role="fieldcontain" id="Cat_IdDiv">

<label for="Cat_Id">D1. Category </label>
            <select id="Cat_Id" name="Category ">
              <option value="Home">Home Claim</option>
              <option value="Auto">Auto Claim</option>
              <option value="Boat">Boat Claim</option>
              <option value="Personal">Personnal Claim</option>
            </select>
          
</div>

<div data-role="fieldcontain" id="AddressDiv">
            
<label for="Address" id="AddressLabel" name="AddressLabel">E1. Address   </label>
            <input id="Address" name="Address   " type="text" value="">
          
</div>
          
<div data-role="fieldcontain" id="CityDiv">

<label for="City" id="CityLabel" name="CityLabel">F1. City   </label>
            <input id="City" name="City   " type="text" value="">
          
</div>

<div data-role="fieldcontain" id="ExplanDiv">

<label for="Explain" id="ExplainLabel" name="ExplainLabel">G1. Additional Details  </label>
    <input id="Explain" name="Explain   " type="text" value="">
          
</div>    
          
<div data-role="fieldcontain" id="State_IdDiv">

<label for="State_Id">H1. State </label>
            <select id="State_Id" name="State ">
              <option value="Alabama">Alabama</option>
              <option value="Alaska">Alaska</option>
              <option value="Arizona">Arizona</option>
              <option value="Arkansas">Arkansas</option>
              <option value="California">California</option>
              <option value="Colorado">Colorado</option>
              <option value="Connecticut">Connecticut</option>
              <option value="Delaware">Delaware</option>
              <option value="District of Columbia">District of Columbia</option>
              <option value="Florida">Florida</option>
              <option value="Georgia">Georgia</option>
              <option value="Hawaii">Hawaii</option>
              <option value="Idaho">Idaho</option>
              <option value="Illinois">Illinois</option>
              <option value="Indiana">Indiana</option>
              <option value="Iowa">Iowa</option>
              <option value="Kansas">Kansas</option>
              <option value="Kentucky">Kentucky</option>
              <option value="Louisiana">Louisiana</option>
              <option value="Maine">Maine</option>
              <option value="Maryland">Maryland</option>
              <option value="Massachusetts">Massachusetts</option>
              <option value="Michigan">Michigan</option>
              <option value="Minnesota">Minnesota</option>
              <option value="Mississippi">Mississippi</option>
              <option value="Missouri">Missouri</option>
              <option value="Montana">Montana</option>
              <option value="Nebraska">Nebraska</option>
              <option value="Nevada">Nevada</option>
              <option value="New Hampshire">New Hampshire</option>
              <option value="New Jersey">New Jersey</option>
              <option value="New Mexico">New Mexico</option>
              <option value="New York">New York</option>
              <option value="North Carolina">North Carolina</option>
              <option value="North Dakota">North Dakota</option>
              <option value="Ohio">Ohio</option>
              <option value="Oklahoma">Oklahoma</option>
              <option value="Oregon">Oregon</option>
              <option value="Pennsylvania">Pennsylvania</option>
              <option value="Rhode Island">Rhode Island</option>
              <option value="South Carolina">South Carolina</option>
              <option value="South Dakota">South Dakota</option>
              <option value="Tennessee">Tennessee</option>
              <option value="Texas">Texas</option>
              <option value="Utah">Utah</option>
              <option value="Vermont">Vermont</option>
              <option value="Virginia">Virginia</option>
              <option value="Washington">Washington</option>
              <option value="West Virginia">West Virginia</option>
              <option value="Wisconsin">Wisconsin</option>
              <option value="Wyoming">Wyoming</option>
            </select>

</div>

<div>
        <input type="button" value="Submit"  name="submit" id="submit" value="Submit">
 </div>

</form>

</div>
    
</div>

</body>

</html>

Note:

In this example AEM application, the required JQuery Mobile JS and CSS files are referenced by using a <script> tag that resolves the resource using an URL. Instread, you can use a clientlibs node. For information on creating a CQ application that uses a clientlibs node, see Querying Adobe Experience Manager Data using the JCR API.

Note:

For information about the JQuery Mobile API, see JQuery Mobile.

Modify the templateMobile JSP file

  1. To view the CQ welcome page, enter the URL: http://[host name]:[port] into a web browser. For example, http://localhost:4502.
  2. Select CRXDE Lite.
  3. Double-click apps/mobile/components/page/templateMobile/templateMobile.jsp.
  4. Replace the JSP code with the new code shown in this section.
  5. Click Save All.

Create a CQ web page based on the mobile form

The final task is to create a site that contains a page that is based on the templateMobile (the template created earlier in this development article). When the user enters claim data and submits it, the claim data is persisted in the CQ JCR.

claimdata

Create a CQ web page that displays the Mobile CQ form:

  1. Go to the CQ welcome page at http://[host name]:[port]; for example, http://localhost:4502.
    Select Websites.
  2. From the left hand pane, select Websites.
  3. Select New Page.
  4. Specify the title of the page in the Title field.
  5. Specify the name of the page in the Name field.
  6. Select templateMobile from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information, the template will not show up in the New Page dialog box.
  7. Open the new page that you created by double-clicking it in the right pane. The new page opens in a web browser. You should see a page similar to form shown at the beginning of this article.

 

Testing the CQ mobile form within a mobile emulator

You can test the CQ mobile form (including submitting form data) by using a mobile emulator. At the time this article was written, the mobile form was tested using the Chrome Ripple emulator. For information, see https://chrome.google.com/webstore/detail/ripple-emulator-beta/geelfhphabnejjhdalkjhgipohgpdnoc?hl=en.

After you install the Ripple Emulator, you can test the CQ mobile form using different device emulators. You can fill in the form and submit data. Once submitted, notice that the claim identifier value is returned as shown in the following illustration.

ClaimNumber

Note:

When you submit data, you will be able to view the customer data in the following JCR path: content/claims. You can view the data by using CRXDE Lite.

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