Posts tagged "Forms in AEM"

Enable JS and CSS minification

Mobile Form runtime includes couple of js and a CSS file. These files, by default, are not minified. But there is no need to worry as there is a configuration to use the minified versions of these. This blog post will take you through the steps on how to enable minification.
You need to go to http://:/lc/system/console/configMgr page. This is a configuration page listing all the services that has configurations. Just look for ‘HTML Library Manager’ and click it. You will see the configurations like following:



Now check the ‘Minify’ checkbox. That’s it. Now you would get all the js and css in minified form.

This is very important from performance perspective. Less size will take less time over the network resulting in better load time when you render the form.

Hide parameters from Mobile Form URL

In ES4, Mobile Form had a limitation that it could only hide the template references from the form URL exposed to the user. In ES4 SP1, one can overcome it using the new ways of passing parameters to Mobile Form render service.

Based on your preference and requirement, you can choose to specify the render parameters like template reference, data reference, submit url etc either as node properties or as setAttribute API of server request object. In this post, I will go through both the options in detail and discuss pros and cons. Ideally, in production system, one should use any of these two methods of passing parameters over the request parameter method wherein all parameters are visible to the user accessing the url. Besides hiding the parameters, these two methods also make maintenance easy. For example, let’s say you want to change the data reference, then you wont need to update the URL everywhere because it is anyway not part of the URL.

Let’s say, you already have a servlet or JSP running on the same server and you want to forward the user request to the Mobile Form profile renderer using servlet forwarding. In this case, you can expose the URL of your servlet or jsp as Form URL. That user facing JSP may, in turn, set the template and data references in the request object before forwarding, using setAttribute API of servlet. Now this approach would mean you create one user facing JSP/servlet for each form or pass some parameter based on which it can select a form. The jsp would like the following:

//similarly for other parameters and then get the request dispatcher of the profile URL and forward it.
RequestDispatcher rd = request.getRequestDispatcher("/content/xfaforms/profiles/default.html");
rd.forward(request, response);

If you create the user facing URLs in sling subsystem then it better to go for the other approach. Because, you have to create a content node anyway, to create a new REST URL. But if you are creating node, then you can specify the parameters as node properties as mention in post. In the following screenshot, you would notice, how I have specified Mobile Form render parameters as node properties of “leave” node created under /content section. Also, I specified resourceSuperType for this node to default profile renderer of Mobile Form.



As is evident from the above, you need to create one node for each combination of render api parameter.

It is good practice to do mix and match of both approaches. It is good to specify the static or less dynamic properties like template reference as node properties and pass other dynamic or frequently changing parameters like data reference as setAttribute method.


Smart submission – part II : LiveCycle Process

In my last post on Mobile Form data submission, I discussed how to submit data directly to a LiveCycle process. In ES4 LiveCycle Mobile Form, one needed to deploy the custom package shared in this blog. In ES4 SP1, submission to any LC process is even more easier to do. Now you don’t need custom package any more.

You can download the FormSubmission LiveCycle process and import it following the instructions. You can create your own process as well. The important part is to get the REST url of the process. The rest url of the process turns out to be http://localhost:8080/rest/services/<ApplicationName>/<ProcessName>:1.0 as shown in the screenshot of workbench.



If you hit the REST url in the browser, it will ask for credentials of a user that can run this service or process. You can also disable the authentication required for running this process, for details look for adobe help.

http://localhost:8080/lc/content/xfaforms/profiles/default.html with the following parameters:

  • contentRoot=repository:///Applications/FormSubmission/1.0
  • template=SimpleForm.xdp
  • submitUrl=http://localhost:8080/rest/services/FormSubmission/archiveForm:1.0

The difference between ES4 and ES4 SP1 is, you dont need to preprocess the submission payload of Mobile Form before routing it to a LiveCycle process. You can also implement a custom submission proxy as mentioned in service proxy post. This will not only  do away the need for exposing LiveCycle server from internet but also give you a hook to pass any authentication information to LiveCycle process.

Mobile Form smart submission

The workflows around Mobile Form generally involve rendering a form in the browser and then capture data and submit it back to the server. You cannot render the form if you are not connected to the server. In general, data capture step doesn’t need any connectivity from server except in case of running any script on server side or executing a web service. But connectivity is very critical in case of form submission. If you are not connected to the server and you submit the form, you would get just 404 error page and  you data would be lost.

Generally, the solution is to check connectivity before one submits the form. Mobile Form with ES4 Sp1, brings out this check out of the box. It will  first issue a HEAD request to LiveCycle Server to check if it is still accessible. If this check fails, it will show the following dialog. Once it gets assurance then Mobile Form submits the data to the server.


Mobile Form Service Proxy

In the pre-release forum of ES4 and other customer forums of Mobile Form, one of the most sought after feature was to run all the Mobile Form workflows without directly exposing the LiveCycle server to the user accessing the forms in the browser. In ES4, the LC admin is required to open submission service “/lc/content/xfaforms/submission/default” to the whole internet as the Mobile Form needs to talk to it. The service url was embedded in the runtime model of the form. One way was to do URL mapping in webserver and proxy it but the restriction was one cannot change the URL path as it was in the runtime model.

There was another issue with the submission was, it was a two step submission that is you need two trips to server at the minimum to submit form data. This is again unnecessary load on server handling the submission. The data was being send as request parameter in the POST request on contrary to the pdf where data is sent in the body payload. This means for any workflow involving both pdf and mobile form, one has to field two different ways of processing the submission payload.

In ES4 SP1, Mobile exposed a configuration wherein you can register a proxy to submission service by specify its url through request parameter submitServiceProxy. Mobile Form talks to this service over ajax so you need to make sure your submission service proxy is hosted at the same server which is delivering the form.

We can broadly categorize two different types of deployment topology as shown in the following two diagrams. Topology (1) is where LC Server/Mobile Form POSTs data to the server and another Topology (2) where data is POST’d by the proxy server on behalf of Mobile Form.

Topology 1
Topology 2

Mobile Form rendered in the browser needs to contact LC Server for running server side scripts, web services and submission. The XFA runtime of the form in the browser talks to LC Server using AJAX calls on “/lc/bin/xfaforms/submitaction” end point with various parameters. But as I mentioned earlier one can configure the REST service endpoint using submitServiceProxy. The XFA runtime calls LC Server in the following conditions:

Executing Server Side Scripts (scripts in the form that are marked runAt=server) and webservices.

Here is the detail of the parameters:

Parameters Description
activity events e.g. click, exit or change to execute.
contextSom SOM expression of the object where events to be executed.
template template reference that was passed while rendering the form.
contentRoot template root directory that was passed while rendering the form.
data data bytes that was passed while rendering the form.
formDom form dom in JSON format.
packet This is specified as “form”.
debugDir The debug directory passed while rendering the form.

On submission of data by clicking submit button

And here is the detail:

Parameters Description
template template reference that was passed while rendering the form.
contentRoot template root directory that was passed while rendering the form.
data data bytes that was passed while rendering the form.
formDom form dom in JSON format.
packet This is specified as “data”.
debugDir The debug directory passed while rendering the form.
submitUrl The submit url where data xml is to be posted.

The submit service proxy should act as just pass through if submitUrl is not present in the request parameter that is if it is request type 1. That means whatever is posted to the proxy it should send that to “/lc/bin/xfaforms/submitaction” end point and send the response to he XFA runtime. If submitUrl parameter is specified, the service proxy has one of the two options based on the deployment topology. If data is posted by the LC server as shown in topology (1) then the proxy can act as pass through even in this case whereas if data is posted by the proxy as shown in topology (2) then the proxy server can pass all the parameters except submitUrl to “/lc/bin/xfaforms/submitaction” end point and get data xml bytes in response stream. Then the proxy service can post the data xml bytes to the submitUrl where it is to be processed.

The other proxy is for getting the XFA runtime client logs. This is useful if one wants to debug the forms’ client side runtime. For details refer to (reference to logger page). By using the same argument as of submission service, we need a proxy for logging service also. This should act just as a pass through to “/bin/xfaforms/logger.

You can take a look at Mobile Form Submission Proxy sample on how to create one.

Backward compatibility configuration

Ensuring upgrade compatibility across LiveCycle versions is of prime importance for Adobe and our customers relish that. This means if a feature works in a certain way in a release it will continue to do so.
One can configure Mobile Form to get the behavior of a feature in older versions. You can browse through http://localhost:8080/lc/system/console/configMgr and search for “LC Forms Configuration”. On clicking, it should expand like the following:


If anyone is upgrading the Mobile Form specifically from ES4 to ES4 SP1, then to make sure the upgrade compatibility one should select “LiveCycle ES4” from the browser. In ES4 SP1, we changed the way we submit the form for details refer to Mobile Form Service Proxy post. If you want to use the older way of submission, you can select “LiveCycle ES4” version behavior.

Mobile Form goes Right To Left

With ES4 SP1, we added support for Right To Left languages like Hebrew in Mobile Form. Now you can see html for your hebrew forms. Not only that but you can also fill the fields in Hebrew. We also support mix and match of English or any Left to Right script for that matter with Hebrew in form fields. Based on form locale we even show the date and days info in localized form.


Here comes the limitations. It works perfectly fine in all other supported browsers except IE. IE lacks basic support for Right To Left scripts so Mobile Form doesn’t support RTL in IE.

Passing parameters to Mobile Form

In LC ES4, we get this feedback from customers that they want to hide the parameters passed to Mobile Form profile to render a form. If you could see the There was only one way to pass parameters that is through request parameters (refer to Mobile Profile page). In ES4 SP1, we introduced couple more ways to pass parameters to Mobile Form.
You can pass parameters by using setAttribute(parameter_name, parameter_value) on the request object if you are forwarding a request from any other jsp/servlet to Mobile Form profile jsp/servlet. This will have highest precedence.
Another way to pass parameters is through profile node i.e. the node where request is made. For example, http://localhost:8080/lc/content/xfaforms/profiles/test.html /content/xfaforms/profiles/test is the profile node. You can specify parameters as node properties on this node using crxde.

Mobile Form gives highest precedence to parameter values set using setAttribute then it falls back to profile node properties and in the last it reads values through request parameters.

Create custom Mobile Form profile

Mobile Form renders the form based on profile. If you want to change the look and feel or do other customization, you are required to make modifications in the default profile. In ES4, Mobile Form profile script was one single monolithic jsp file. So if you want to modify the profile script you have to copy the whole script and then make the changes as suggested in ES4 Adobe documentation. This way, you loose the updates provided in the script over different patches.

With ES4 SP1, we have modularized the various constituents of profile renderer instead of one monolithic profile. The profile script is still html.jsp and html.POST.jsp for GET and POST requests. One can choose to override or add his customization by copying and modifying one or more files. It is not recommended to modify any of the files in place or you will loose the changes after a patch.

You should create an application directory in /apps space and copy html.jsp and other files you want to modify. Before delving into the steps of customization, I will discuss the changed structure of html.jsp.


<%@ page session="false"
               contentType="text/html; charset=utf-8"%><%
%><%@ taglib prefix="cq" uri="" %><%


As you can see html.jsp is just serves as composition jsp. Now customization means, you need to create new components and add them into the appropriate section of html.jsp.

In subsequent sections, I will explore all the components of html.jsp in detail.


<%@ page import="java.util.ArrayList" %><%
%><%@taglib prefix="cq" uri="" %><%
    String acceptLang = request.getHeader("accept-language");
    if(acceptLang == null || "".equals(acceptLang.trim()))
        acceptLang = "en-US";
    acceptLang = acceptLang.trim();

    String[] locales = acceptLang.split(",");
    ArrayList localeChainList = new ArrayList();
    for(int i=0; i<%

LC Forms

As you can see it contains the references to the client libraries to include. It also depicts how one can extract locale information from the request and include the localized messages related to Mobile Forms runtime. You can create a JSP like this to include your own scripts and styles and add it to the head section of html.jsp.


<%@ page session="false"
               " %>
<%@ page import="" %>
%><%@taglib prefix="sling" uri=""%><%
    LCFormsOptionService lcFormsOptionService = sling.getService(LCFormsOptionService.class);
    //read debugDir to pass it along with server API endpoint -- use it for debugging.
    String debugDir = lcFormsOptionService.get(slingRequest, "debugDir");

    if(debugDir != null && !debugDir.isEmpty()) {
        debugDir = "?debugDir="+debugDir;
    else {
        debugDir = "";

    SlingSettingsService slingSettingsService = sling.getService(SlingSettingsService.class);
    boolean  isLCEmbedded = slingSettingsService.getRunModes().contains("livecycle");

    //lcServerProxy that will handle forms server api requests and also submission...
    String submitServiceProxy = lcFormsOptionService.get(slingRequest, "submitServiceProxy");
    if(submitServiceProxy == null) //if running into lc embedded mode then append /lc
        submitServiceProxy = (isLCEmbedded ? "/lc" : "") + "/bin/xfaforms/submitaction"+debugDir;
    String logServiceProxy = lcFormsOptionService.get(slingRequest, "logServiceProxy");

    if(logServiceProxy == null)
        logServiceProxy = (isLCEmbedded ? "/lc" : "") + "/bin/xfaforms/logger";

    String submitUrl = lcFormsOptionService.get(slingRequest, "submitUrl");
    if(submitUrl == null)
        submitUrl = "";
    //to enable logging options...
    LCFormsAdminService formsAdminService = sling.getService(LCFormsAdminService.class);
    formsAdminService.setupLogging (slingRequest);
    String originalVersion = formsAdminService.getOriginalVersion();

As you can see this component of profile contains the various configurations like logging, proxy services, behaviour version etc. If you want to add you own config then this is the place. You can add various configurations like custom widget registration etc just like this in a JSP of your own.


<%@taglib prefix="cq" uri="" %><%

This component is responsible for the red coloured toolbar you notice at the top. In case you want to get rid of the toolbar, you can remove this from the html.jsp.


<%@taglib prefix="sling" uri=""%>

This component is for the html presentation of the XFA form. As shown in html.jsp, you can include this component in the body section of the html.


Mobile Form only renders the first page of the form at first and then subsequently load the pages on scroll to give faster loading experience. This component contains all the styles and required elements to facilitate this.


This is empty for now. But in case you want to add any scripts that is used in user interaction only then you should include that in this section.

Creating Custom profile

Now that we understand what all components does then one can choose to modify a component. Here are the steps on how to create a custom profile.

Creating profile node:

Note: The name of the newly created folders (hrform and demo) can be anything as per your preference.

  1. Navigate to the CRX DE interface at the URL: http://<server>:<port>/lc/crx/de and log in to the interface with administrator credentials.
  2. In the left pane, navigate to the location: /content/xfaforms/profiles.
  3. Copy the node default, and paste the node in different folder e.g. (/content/yourapp/profiles) with the name: hrform.
  4. Select the new node, hrform, and add a string property: sling:resourceType with value: hrform/demo.
  5. Click Save All in toolbar menu to save the changes.

Creating the profile renderer script:

After creating a custom profile, add render information to this profile. On receiving a request for the new profile, CRX verifies the existence of the /apps folder for the JSP page to be rendered. Create the JSP page in the /apps folder.

  1. In the left pane, navigate to the /apps folder.
  2. Right-click on the /apps folder and choose to create a folder with name: hrform.
  3. Insider the hrform folder create a folder: demo.
  4. Click the Save All button.
  5. Navigate to /libs/xfaforms/profile/html.jsp and copy the node html.jsp.
  6. Paste html.jsp node into the /apps/hrform/demo folder created above with same name html.jsp and click Save.
  7. You copy any of the other components of profile script as described above and paste it in the same folder.

Verifying the updates

Render a form using Mobile Forms IVS with the custom profile:

  1. Navigate to http://localhost:8080/mobileformsivs.
  2. Choose and update the form demo.xdp.
  3. Select the demo.xdp form. Choose Custom in profile, and specify hrform as the profile name.

Debugging Mobile Form

Logging in Mobile Form or any application for that matter is of utmost importance. It helps our customers in debugging the various issues in forms including performance. Mobile Form is a distributed application. It has a server component that generates data for the XFA runtime. XFA runtime is a javascript implementation of XFA reference that runs inside the browser and interprets the data generated by the Mobile Form server to render an XFA template and data in html5. In distributes scenario, logging helps a lot in keeping tab at what is going on at various sites.

Mobile Form has two distinct sites or two different components the Mobile Form server and XFA runtime.  One can configure Logger, individually (server and client), based on the requirements and set the levels for any specific request.

I will first describe on how to enable fine level logging in Mobile Form server and how to make sense out of it.

The steps are outlined as following:

  1. Go to http://<server>:<port>/lc/system/console/configMgr and look for “Apace Sling logging logger configuration” and click on it. You see a dialog like following:
  2. Select the Log Level to Debug.
  3. Specify a log file name. If you want to generate logs in the same directory i.e. <lc-install-dir>/crx-repository/logs, where other log files are kept then specify ../logs/<logfilename>.
  4. Specify Logger to HTMLFormsPerfLogger and save the configuration.



That’s it. Now you can find the logs with performance for each render request. The log entries should look like the following:

04.07.2012 17:58:14.054 *DEBUG* [ [1341404888673] GET /content/xfaforms/profiles/test.html HTTP/1.1] HTMLFormsPerfLogger !PERFORMANCE! <RenderOsgiServiceImpl.render>

04.07.2012 17:58:14.142 *DEBUG* [ [1341404888673] GET /content/xfaforms/profiles/test.html HTTP/1.1] HTMLFormsPerfLogger !PERFORMANCE! <time>4004644004ns</time></RenderOsgiServiceImpl.render>

We are interested only in the last word of these log line. That will give you a valid xml file containing all the timings. Each label of the node represents the name of the API and <time> node contains the time taken by that API. You can use awk to generate that xml file. The following command would do: awk ‘{ print $11 }’ <logfilepath>

It is called perf logger because it generates performance information along with the trace. That is it about Mobile Form server logging. Now let’s move to client side logging.

There are two ways to enable XFA runtime client side logging. Like Mobile Form server logging, one way is to enable logs via configuration another via request parameter log. If you just want to generate logs for one particular request, you should use the 2nd approach i.e. pass the request parameter. The log parameter takes log configuration that is defined as follows:

{destination}-{a level}-{b level}-{c level}

For example:

Log Configuration Description
2-a4-b5-c6 Destination: Server
xfa level: INFO
xfaView level: DEBUG
xfaPerf level: TRACE


Let’s explore various constituents of log configuration. destination  is where log is redirected:

Log Destination

Log Destination Description
1 Logs are directed to the browser Console
2 Logs are collected in a JavaScript object on client side and can be posted to the Server
3 Both of the above options


Log Levels and Logger Categories are other constituents.

Log Levels

Log Level Description

Logger Categories

Log Category Description
a xfa (Scripting engine related logs)
b xfaView (Layout engine related logs)
c xfaPerf (Performance related logs)

The default log level for each log category a (xfa), b (xfaView), and c (xfaPerf) is 2 (ERROR). Accordingly, for log configuration: 2-b6, the log levels for different categories are:

a (xfa): 2 (default level ERROR)
b (xfaView): 6 (user specified TRACE)
a (xfaPerf): 2 (default level ERROR)


You specify the log configuration using LC Forms Configuration:

  1. Search for and click LC Forms Configurations on http://<server>:<port>/lc/system/console/configMgr page.
  2. In the Debug Options text box, enter the log configurations as described in the previous section e.g. 2-a4-b5-c6.




If the destination is set as 1, all client script log messages are directed to the console. But at times Admin might need these logs along with server logs to co relate the two and for such cases destination level can be set to 2. At this level, all logs would be collected in a JS object on client side and if form is rendered with default Profile then a Send Logs button would appear to the left of Highlight Existing Fields button in toolbar. On click of this link all collected logs would be posted to the server and will be logged in the configured error log file on the server.

With ES4 SP1, you can also redirect client logs to a separate log file like Mobile Form server logs using the same steps mentioned to configure “Apace Sling logging logger configuration”  above in server logging section.