Apache Sling for Dummies: What goes where?

For a while it seemed every time I got a web UI working with Apache Sling (HTML, JSP, Flash, whatever) I would always be told that some part of it was “in the wrong place”. Now that I think I know how to do this stuff, I thought I would offer a simple example with “all the bits in the right places” to help anyone who is new to Sling. By the way, I don’t discount the possibility that someone will reply and point out something still in the wrong place. But here goes!

Let’s take one of the most common approaches for a simple web UI and see how it’s done. That would be a JSP used to display some simple HTML with a very simple style sheet.

Let’s say this is the web UI we we want to arrive at looks like this:

Two things to notice right away:

  1. Spot that the URL is /content/samples/testdrive/dynamichtml.html. That URL structure (especially the /content part) is pretty important. It is literally the same as a node path in your CRX content repository
  2. The web page is showing a title and some body text that it claims to be “dynamic”. What does that mean? Well, as we shall see, these values are not literally coded in the HTML but come from “JCR Properties” of the node in the CRX content repository sitting at the end of the node path. We’ll get to that in a minute.

And something else to point out right away: Most web developers would just think, “Fine. I have all this stuff in a WAR file where I just dump my assets (JSPs, scripts, whatever) under this folder within the ZIP structure of the WAR”. Yes you can do the equivalent of that in the CRX content repository, but you’d be wrong and you’d probably get reported to the Sling Police. So don’t do that.

OK. So how do we build this web UI using Sling. Let’s start by looking at the JSP that renders this page:

(Click to Enlarge)

Nothing too special there. But notice the HTML in the JSP is using two variables “currentNodeTilte” and “currentNodeBody“. These variables in turn come from the currentNode binding which gives you access to the JCR node where the .html request was made. But now the interesting part. Where does the JSP go? Maybe not where you think..

First we start by defining a content node (under /content) where requests will be made for a “.html” rendition:

(Click to Enlarge)

There is not much going on here. Just a content node under /content/samples/testdrive/dynamichtml with a few basic text properties (including our title and body). But look at the value for the  property called “sling:resourceType“. That’s where the magic happens and it’s where the JSP lives:

(Click to Enlarge)

So you place your JSP under the /apps folder and reference its location from the the resourceType in your content node. That might seem like a lot of annoying indirection but it actually achieves something pretty cool.

  • Your anonymous end users don’t literally need read access to the JSP, They just talk to the content node and ask it for “.html“. It is then the Sling framework on the server that executes the JSP and returns the requested “.html” rendition of the content node. That’s why, in this case, we have called it “html.jsp“.
  • You can re-use this JSP as the base web application for requests to other URLs. All you need is another content node that uses the same sling:resourceType and sets its own properties for the dynamic text.

Although the JSP is under /apps that reference to “currentNode” still binds to the node under /content where the HTML request was made. Therefore the JSP gets to substitute text in the HTML based on the “title” and “body” properties of the actual content node.

But we’re not done yet. If you look carefully in the JSP you will see that it its HTML references a style sheet. But style sheets are not really part of the base web application. They belong somewhere else:

(Click to Enlarge)



The style sheet belongs under /etc/clientlibs. Then the JSP simply references it under it literal path in this case, /etc/clientlibs/aep/samples/testdrive/dynamichtml/style.css.

So in summary to build our little web UI correctly in Sling we needed to:

  1. Write a JSP called “html.jsp” and place it under a location in the /apps folder.
  2. Create a node for the web UI whose folder hierarchy matches the intended URL. Then set the sling:resourceType property of the node to point to the location of your html.jsp in the /apps folder. Therefore when anyone requests a “.html” rendition for that node (called dynamichtml) , Sling will know how to do it.
  3. Within your JSP implementation refer to the style sheet .css file from a folder location under /etc/clientlibs.

This example is quite rudimentary. I haven’t even mentioned what to do with SWFs or how to deploy composite web applications (formerly called “mosaic”) . It is the first sample in a new “Developer Test Drive” that ships with our pre-release for the Adobe Digital Enterprise Platform. There I provide a  few such “getting started for developers” examples that run immediately after launching the ADEP Quick Start.

Happy Hacking,


4 Responses to Apache Sling for Dummies: What goes where?

  1. Raul says:

    I notice that the CQ apps tend to use /etc/designs rather than /etc/clientlibs for storing CSS files. Is that more of a CQ convention than a Sling practice?

    • Gary Gilchrist says:

      Ah, ha. I knew there would be something 🙂 Funny I was just discussing this with the Day guys today. I think what you say sounds right. I’ll check and get back to you.

    • Gabriel Walt says:

      The response is both:
      – put generic clientlibs that can be used across sites into /etc/clientlibs/…
      – put site-specific clientlibs into /etc/designs/sitename/clientlibs/…

  2. Gabriel Walt says:

    The response is both:
    – put generic clientlibs that can be used across sites into /etc/clientlibs/…
    – put site-specific clientlibs into /etc/designs/sitename/clientlibs/…