We were working on a project that involved integrating an existing complex ecommerce system with Adobe Experience Manager (AEM formerly Adobe CQ). As can be expected, we ran into a lot of complications. One interesting piece we worked on was related to Apache Sling script resolution, a common stumbling block for developers moving from a script-based Web environment (such as PHP or ASP.NET) to AEM.
If you’ve worked on AEM much, you should have at least been exposed to this diagram:
There’s a lot going on here, but I’m just going to focus on query parameters, selectors, and suffixes.
In my past professional experience, I’ve worked with many ecommerce solutions. Some were large and complex, others were custom built to be simple and easy to customize. They all generally have some products that you can view and put in your shopping cart before checking out. The products are usually viewable on a page with a URL like /products.php?pid=123 or /products/details/123. The point is that the product id is in the URL, either directly as a query parameter, or in a URL rewrite that is fed to the script as a query parameter.
In our AEM deployments, we generally set up the dispatcher to cache pages unless they have a query string in the URL. For the project I was working on, we really wanted all our pages to be cached in the dispatcher so they’d load as fast as possible under high load. We had already set up the product detail view as individual pages in AEM, so that wasn’t an issue. However, for this project, after adding certain products to their shopping cart, the user was to be directed to a configure page.
We didn’t need the configure page to be authorable by a business user for each different product. In fact, we wanted it to only have a few global pieces that were authorable and have the rest of the page pull in information from the product that had been selected. Given this parameter, we knew we’d be building something similar to the scripts I was familiar with where the product ID is sent in the URL, but using a query string would cause the dispatcher to bypass the cache.
Selectors and Suffixes
Fortunately, Sling has an easy way to handle this. And in fact, AEM provides a selector called “form” that will take care of this for you. Let me briefly cover both ways this could be done.
If you use the Sling way as shown in the Sling Cheatsheet, your URL should look something like this: /products/123.configure.html
This tells Sling that you want the configure page to load using the data located at /products/123.
The built-in AEM “form” method looks a little less elegant in the URL: /products/123.form.html/cart/configure.html
This doesn’t quite do the same thing. Basically, what happens is that AEM finds the “form” selector and then looks for a suffix (/cart/configure.html). AEM assumes the suffix is a path and redirects the user to this path. The script at that location can then parse the URL for /products/123 to look for which product is being configured.
No query string is used, but each product gets a unique, cacheable URL. It is as simple as that.