Using sling:Mapping to expose repository values

Besides conventional client access to Web sites using a browser, client applications can be built within applications such as Flex and still access data in our repositories. A quick way of doing this is by having Flex access that data as JSON. There is one thing that makes this problematic for production. When a publish instance is accessed through Dispatcher it is suggested that any access to URLs ending with the .json suffix should be forbidden. For security reasons many directories in the repository should not be accessible through outward facing connections. Like I mentioned, this can be problematic if JSON is being accessed by Flex.

Sling, and by extension CQ, has a redirect mechanism that can selectively expose values.

Pre-requisites

Knowledge of the use of CRXDE or CRXDE Lite to edit nodes and properties is required for the example.

What are sling:Mapping nodes?

Sling uses sling:Mapping nodes much the same way that Apache’s mod redirect uses its configurations in httpd to define redirect behavior. The Apache Sling Web site has documentation for mappings. Existing mappings can be seen in the Sling Resource Resolver Console at http://[host]:[port]/system/console/jcrresolver.

A brief explanation is that redirect behavior can be configured by setting properties on sling:Mapping nodes. There should be one sling:Mapping node per redirect rule. The sling:Mapping nodes can have nested sling:Mapping nodes, but that is not needed for my simple example and I won’t go there at this time. Add the sling:Mapping nodes to the repository within the /etc/map/ directory. Sub-folders can be created in this directory and that has an effect on how URLs are matched for redirecting. Once again, this article does not need this and I won’t get into that. This framework can be very powerful and has many ways of being configured. The use case for the sling:Mapping node will be basic and simple in this example.

Using redirection to access JSON data behind a securely configured Dispatcher

For this example I will show how to create a redirect that allows access to the possible values of a dialog used to configure a component. The component is the Flash component. The values are for the menu property of the Flash component. That value is contained within the dialog configuration of the Flash component:

|- libs
   |- foundation
      |- components
         |- flash
            |- dialog
               |- items
                  |- menu
                     |- options
 

The url I used to get the JSON version of this on my local, sample server is [1]. Calling this JSON as admin returns:

{
     "jcr:primaryType":"cq:WidgetCollection",
     "show":{
          "value":"show",
          "jcr:primaryType":"nt:unstructured",
          "text":"Show"
     },
     "hide":{
          "value":"hide",
          "jcr:primaryType":"nt:unstructured",
          "text":"Hide"
     }
}
 

The direct URL to this value is not available behind Dispatcher. Dispatcher should not allow calls either to the /libs directory nor any resource with a .json suffix.

To make it so the Flex client can query this value we need to set up a mapping for it.

  1. Create a node called, menudata, of type sling:Mapping within the /etc/maps/ directory
  2. Create a property called, sling:internalRedirect, of type String to the menudata node. Set it to:/libs/foundation/components/flash/dialog/items/advanced/items/menu/options.1.json
  3.  Create a property called, sling:match, of type String to the menudata node. Set it to:^[^/]+/[^/]+/menu-options$

Once saved, the redirect takes effect. You should see the values of this mapping if you go to Sling Resource Resolver Console.

The sling:internalRedirect property is the relative URL to a resource within the repository. There are, of course, exceptions. But for this example the value of the internalRedirect property is returned without sending a redirect message back to the browser.

The sling:match property is a regular expression pattern used to match the URL. If this property were not present in the sling:Mapping node it would use the node’s name to match with.

Now, when I go to the URL that calls menu-option ([2] on my local server), the value of the options node is returned.

Standard cautions apply. Be very conservative about what you expose to the outside world. But the redirect mechanism in Sling is very powerful and it is worth exploring.

[1] http://localhost:4502/libs/foundation/components/flash/dialog/items/advanced/items/menu/options.1.json

[2] http://localhost:4502/menu-options

Creating images from PDFs that are proportionally the same size in LiveCycle ES2 and ES3

Problem:

What if images produced from PDFs within the timeline of LiveCycle need to all be the same size? PDFs that are the same size, dimension-wise, can turn out as images of different sizes after processing with the toImage activity. For example, two PDFs could be 8.5 x 11 inches in size. But one would convert to an image that is 1700 x 2200 pixels in size and the other would convert to an image that is 2550 x 3300 pixels in size.

Resolution:

Use the same DPI argument for each of the PDFs. The resulting images will not be an exact match with one another, however. In my test a variation of ten pixels or so could be seen as the result of differences in the areas of the PDF page that are converted to image. But PDFs that are the same dimensions before conversions result in images that are the same pixel height and width (or very close to it).

See Also:

The documentation for the toImage operation of the Convert PDF service

Editing the content directory in CRXDE

CRXDE is the eclipsed-based tool used to to develop within the CQ and CRX repository. By default, only a few directories within the repository are visible. The content directory is not one of them. A setting in the repository must be change before it can be seen.

Go to /etc/crxde/profiles/default. There is a property, crxde:paths. This property is a list of String. Add /content to that list and restart CRXDE.

Output Exceptions in CQ Blog Feeds

Symptom

The Atom blog feed from CQ that is obtained by using the .feed suffix on a URL has exceptions within it. The output is an error witinh the feed.jsp or feedentry.jsp file and it contains the following:

Caused by: java.lang.IllegalStateException: output stream already obtained
 

What Can Be Done?

There is a structural supposition within CQ that the output of JSP pages will be HMTL. Because of that, <div> tags are generated for sections of content automatically. Writing these <div> tags causes writes to the output buffer that should not happen. Even if writing to the output buffer did not cause the exception, it would create bad Atom files with <div> tags sprinkled throughout in places they should not be. Changes need to be made to the JSP pages that handle the *.feed suffix. Those files can be found here:

/libs/foundation/components/page/feed.jsp /libs/foundation/components/page/feedentry.jsp /libs/collab/blog/components/page/feed.jsp /libs/collab/blog/components/page/feedentry.jsp

Within ALL feed oriented JSP files (*.feed.jsp, *.feedentry.jsp, etc) the following must be added:

// This bypasses the normal component handling with its automatic output of content
request.setAttribute(ComponentContext.BYPASS_COMPONENT_HANDLING_ON_INCLUDE_ATTRIBUTE, "true");

// This changes the tag used for blocking areas of content from "div" to "". 
// When empty, a tag will not be written to create blocks of content.
IncludeOptions.getOptions(request,true).setDecorationTagName("");

These nodes are part of the foundation components for CQ. Make backups. And be aware that these components can be overwritten without warning in future updates. You will need to document well the changes that have been made in case problems arise later.

Watched File System Folders in CQ/CRX

Greg Klebus suggested using WebDAV to mount repository directories on the file system. Doing this, he said, the end user has access to file system directories on which CQ can automatically run workflows.

A quick example of this is mounting the DAM directory as WebDAV. When content is added or changed within the DAM directory of CQ, a workflow process will run automatically.

These are the steps I go through for using WebDAV with Windows 7 to do that very thing.

I mount the CRX repository as a mapped drive within Windows 7 by right-clicking on the computer and selecting the Map Network Drive menu item. I pick the drive letter and, for my local installation, use the CRX WebDAV URL for my server [1].

Windows 7, out of the box, may not support WebDAV. To use WebDAV on a computer with Windows 7 you may need to install an update from Microsoft: Software Update for Web Folders [2]. You may want to see if it works without this update. It is an old software update and only lists Windows 2003 and Vista specifically. For instructions on how to get Windows 7 64bit, specifically, to work with WebDAV go to [3].

Within CQ 5.4, you can set the permissions of a directory under /var/dam to allow read/write or write privileges for the end user. When they drop an image into this folder there is a workflow that explodes the image, generates thumbnails, and creates the dam:asset for that image. The result of the process can be seen in the /content/dam directory. For CQ 5.5, images placed into /content/dam and its sub-directories will trigger the workflow.

[1] http://localhost:4502/crx/repository/crx.default

[2] http://www.microsoft.com/en-us/download/details.aspx?id=15123

[3] http://shon.org/blog/2010/03/04/howto-fix-windows-7-64bit-webdav/

Appliness Digital Magazine

A new digital magazine has been released that is aimed towards HTML developers. It is called Appliness. It is downloadable for both Android and iOS from each platforms respective market. Links to the more information about this magazine and a description of how it is put together can be found at  Michaël Chaize’s blog.

Register a Custom Namespace within CQ

It is possible to add your own namespaces within CQ. Just as there are predefined namespaces such as cq, jcr and sling, you can have a namespace for your repository metadata and xml processing.

Go to the node type administration page, http://<host>:<port>/crx/explorer/nodetypes/index.jsp. The right-most button at the top of this pages is Namespaces. Clicking that button will open a pop-up window containing the namespace administration page. At the bottom of the page is the New button use to add a namespace.

The namespace follows the XML namespace convention. There is the id in the form of a URI and the prefix associated with that id.

What is the gray circle with an exclamation mark (or bang)?

[Note: edited 7 Jun 2012, 13 Aug 2012 to make changes based on comments that have been received]

The generic memory error icon was added in Flash Player version 10.1 and will appear within a browser when the Flash Player has been particularly abused or is running in a very low memory environment. The icon, affectionately known as the Gray Circle of Death (GCOD), is a gray circle with a white exclamation mark within it.

It is not just an icon, however. It is a sign that Flash is protecting your computer from an application that is asking for more memory than your browser has available. The browser will crash if it runs out of memory and that is a Very Bad Thing. If that happens your browser may crash or your computer may crash and need a restart. Flash now has the feature in which it shuts down an application if that application causes a memory problem.

Note: One recurring comment to this post is that one application or another created in Flash often triggers this icon to appear. “Why don’t you fix Flash?” The answer to that question is that Flash is doing exactly what it is supposed to do. It is protecting your computer.

It is possible in Flash, as with most programming languages, to create create an application that doesn’t play nice.

The Flash Player tries to shield the user from either intentional or unintentional mischief that an application can create. The GCOD is shown when Flash has stepped in and kept an application running in the Flash Player from using more memory than is available. The Flash Player stops execution of an application and displays the GCOD when an application requires more memory to continue running than is available.

It is important to point out that the Flash Player has not overrun its available memory. If it had Very Bad Things would have occurred. What did happen is that Flash Player yanked the leash of an application and shut it down when it needed more memory than the browser had available.

For that reason, the GCOD is a very good feature of the Flash Player.

Getting Rid of the GCOD

Most important to most people is not what the GCOD is, but how to make it go away. In all cases, an application does not have enough memory to run. The application could be needing a reasonable amount of memory but the browser does not have that much memory available. On the other hand, the application could also go into a death spiral because of a programming error and suck up every bit of memory available in even the heftiest computers. There are many ways for an application to overrun its memory.

When the GCOD is seen, the first course of action is to contact the developer of the Flash application. I have a decent computer and I have only seen the GCOD appear because of the coding of the application. The GCOD is not a problem Flash Player causes. You see it when the safety valve has blown.

For more:
Flash Player 11 Technical Specifications
Garbage collection internals for Flash Player and Adobe AIR
Optimizing Performance for the Adobe Flash Platform

True literacy in the 21st Century

“The illiterate of the 21st century will not be those who cannot read and write, but those who cannot learn, unlearn, and relearn.”

Alvin Toffler

Place simple HTML and image files online with CRX and CQ

The Sling underpinnings of CRX and CQ allow for complex, conditional, rendering of content. That is fine and good, but what if you are just wanting to render a simple HTML page? CRX/CQ can serve static content as well. This includes any HTML files, images, SWFs and PDFs. This is a quick description of three ways to add this sort of content to your repository.

Using cURL

The most basic way to get static content into the CRX/CQ repository is to place it there using HTTP. Here is a simple example showing how to upload a page, sample.html, to a CRX server using curl:

curl -u admin:admin -T sample.html http://localhost:8080/content/sample.html

The resulting page is accessed at the same URL it was placed to.

Using WebDAV

By default, CRX/CQ allow WebDAV connections. With any WebDAV client, point to the CRX/CQ WebDAV endpoint at http://<host>:<port>/crx/repository/crx.default. I have a laptop with Windows 7 64 bit. WebDAV does not work with that operating system so I had to download a WebDAV client. My personal preference for a WebDAV client is CyberDuck (http://cyberduck.ch).

Once you connect to your CRX/CQ instance you can place your static content within the repository.

Using Package Manager

The third way to add content to your repository is to create a package and import the package. The advantage of this method is that your content becomes a single file that is portable and able to archived. Packages can be created using tools such as Maven. The method I describe here uses no build tools.

First, create a folder node to contain your content within your repository using CRXDE Lite. Right click on the node you want to contain your new node and select the Create->Create folder… from the context menu.

This will bring up a dialog to name your new folder.

Once you have created and named your new folder, be sure to press the Save All… button within CRXDE Lite. Any changes are lost if you leave the page before saving.

At this stage go back to the main screen by pressing the CRXDE Lite logo at the top and the screen. On the main screen, select the Packages link to go to the Package Manager.

In the Package Manager you can create a new, empty, package for the folder you just created in your repository. Select the Create Package button.

This will open a dialog. Enter the name and version of your package. The group of the package should be the default, my_packages. Press OK.

The package is listed within the Package Manager. Right now this package is completely empty. Within the listing for the new package select the Edit… button.

Within the dialog that is opened, select the Filters tab and press the Add Filter button. Specify the root path of the package. Press the search button next to the root path field and select the folder within the repository for the Web pages. Press OK to select the folder and press the Save button in the Edit Package dialog.

In the listing for the new package press the Build button to the right of the Edit button. The Activity Log at the bottom of the page will show you the progress of the build. Once built, press the Download button in the package’s listing to save a copy to your computer.

This package file will be a zip file with content directories and manifest files. At this stage we finally get to your content. Place the content you want to include in your repository inside the package file. Place the content inside the directory of the zip file that matches the folder in the repository you wish to place it. Once the package file contains all of your content you can upload it to any CRX/CQ repository.

To upload the package, go once again to the Package Manager. Within the Package Manager is the Upload Package button.

A dialog to select a package file appears after the Upload Package button is pressed. Select your package file. Pressing OK adds the Package you selected to CRX/CQ. The package will be listed in the Package Manager. It very important to know that the package itself has not been applied to the repository. To apply the content changes found in the package file, press the Install button within that package’s listing.

Once the package is installed the content can be access through your CRX/CQ instance.

See Also

Apache Sling –  Discover Sling in 15 minutes has instructions on how to use the curl command to add and edit content within the Sling instance. This works the same way in CRX/CQ.

The documentation site for CRX/CQ, dev.day.com, contains documentation on WebDAV access to CRX/CQ and how to work with packages.