Article summary

Summary
Discusses how to create a mobile application that uses a Sling Post Servlet to modify the Adobe Experience Manager JCR.  
Digital Marketing Solution(s) Adobe Experience Manager (Adobe CQ)
Audience
Developer (intermediate)
Required Skills
JQuery, AJAX. CSS, HTML
Tested On Experience Manager 5.5, 5.6

Note:

You can download an AEM package that contains code that is used in this article. Download the package and deploy using package manager. The purpose of this code is to show the community these concepts in action. That is, it's to illustrate how to use the default SlingPostServlet using an AEM mobile form (built using JQuery mobile). This community code is for teaching purposes only and not meant to go into production as is.

You can view the application by using the following URL: http://localhost:4502/cf#/content/MobileSlingServlet.html (assuming you deploy on author).

Download

Introduction

You can create an Adobe Experience Manager (AEM) mobile form using JQuery Mobile API and submit the data to the AEM JCR by using a Sling Post Servlet. When a mobile user fills in the form and clicks the submit button, form data is submitted to the AEM JCR. However, instead of using an OSGi bundle to store the data in the Experience Manager JCR, you can use the Sling Post Servlet. 

MobileForm

The Sling Post Servlet provides a RESTful interface that lets you manipulate data content stored in the AEM JCR. This servlet maps nodes in the JCR repository to URIs and allows applications to modify JCR content.  This development article guides you through how to build this AEM mobile form and then submit form data to the AEM JCR by using the Sling Post Servlet. See Sling Cheat Sheet

A difference between using a Sling Post Servlet as opposed to an OSGi bundle is you do not have to create and deploy a server-side component using Java application logic. A Sling Post Servet is performed on the client using JavaScript. In this example, a JQuery AJAX call is used. In contrast, you can submit mobile data to the Experience Manager JCR using an OSGi bundle that contains Java application logic. For information, see Submitting Mobile Form Data to Adobe Experience Manager.

Create an application folder structure 

Create an Experience Manager 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 mobileSling
  5. Repeat steps 1-4 for each folder specified in the previous illustration.

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 CQ 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 templateSling
  • 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 mobileSling/components/page/templateSling.
  • 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/mobileSling/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 templateSling. 
  • 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/mobileSling/components/page/templateSling/templateSling.jsp.

8. Enter the following HTML code.
 

<html>
<head>
<title>Adobe CQ Mobile Form</title>
</head>
<body>
<h1>Hello CQ Mobile!!!</h1>
<h2>This page will become a CQ mobile form that lets users submit data to Adobe CQ using the Sling Post Servlet</h2>
</body>
</html>

Note:

Because this use case does not involve creating a server-side component or a client library, the next step is to modify the JavaScript code associated with this component. If you were to build an Experience Manager application that uses an OSGi bundle to modify the Adobe JCR, you would create it next. To see an example workflow that involves building an OSGi bundle to update the Adobe JCR with mobile data, see http://helpx.adobe.com/adobe-cq/using/submitting-mobile-form-data-cq.html.

Modify the templateSling JSP to use a Sling Post Servlet 

To create an AEM mobile form that uses a Sling Post Servlet to modify the AEM JCR, you can use JQuery mobile API to build the mobile form. In this development article, AJAX  is used to make the Sling Post Servlet call. In this example, assume that claim data is submitted from the mobile device. To simplify the way claim data submitted from a mobile device,  claim data is stored as a nt:unstructured node under /content/claims.

Each claim has a unque identifier value that is generated by using JavaScript. The following JavaScript represents the AJAX call that uses a Sling Post Servlet.

 

 //Get the user-defined values that represent claim data to persist in the AEM JCR
    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 claimId = createUUID(); 


    //Use a Sling Servlet Post to persist the claim data into the Adobe JCR under content/claim
    $.ajax({
  		 type: 'POST',    
		 url:'/content/claim/newClaim_'+claimId,
		 data:'id='+ claimId+'&firstName='+ myFirst+'&lastName='+ myLast+'&address='+ address+'&cat='+ cat+'&state='+ state+'&details='+ details+'&date='+ date+'&city='+ city,
         success: function(msg){

          $('#ClaimNum').val(claimId);
         }
     });

Note:

To see other types of operations that you can perform using a Sling Post Servlet, see Sling Cheat Sheet.

Notice that a JQuery AJAX Post is used and the URL is /content/claim_claimId. The claimId is the unique identifier value used for the claim and is concatenated to the name of the claim. The following illustration shows claim nodes within the Adobe JCR.

 

Claim

When you click on a claim node, you can see the properties that store claim data, as shown in the following illustration.

 

data

The following code represents the entire TemplateSling JSP.

<%@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>


 //Creates a GUID value using JavaScript - used for the unique value for the generated claim     
 function createUUID() {

    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}

$(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 that represent claim data to persist in the Adobe CQ JCR
    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 claimId = createUUID(); 


    //Use a Sling Servlet Post to persist the claim data into the Adobe JCR under content/claim
    $.ajax({
  		 type: 'POST',    
		 url:'/content/claim/newClaim_'+claimId,
		 data:'id='+ claimId+'&firstName='+ myFirst+'&lastName='+ myLast+'&address='+ address+'&cat='+ cat+'&state='+ state+'&details='+ details+'&date='+ date+'&city='+ city,
         success: function(msg){

          $('#ClaimNum').val(claimId);
         }
     });
  });
   
}); // end ready
</script>
</head>
  
<title>Adobe CQ Sling Mobile Page</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 Sling 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 CQ application, the required JQuery Mobile JS and CSS files are referenced by using a tag that resolves the resource using an URL. Instead, 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 templateSling 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/mobileSling/components/page/templateSling/templateSling.jsp.
  4. Replace the JSP code with the new code shown in this section.
  5. Click Save All.

Create an Experience Manager web page based on the mobile form

The final task is to create a site that contains a page that is based on the templateSling (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.

Create a web page that displays the Mobile CQ form:

  1. Go to the 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 templateSling 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.
    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 mobile form within a mobile emulator

You can test the 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 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