AEM/CQ Reverse Engineering Demystified

Have you ever struggled to find out how to implement a particular feature for Adobe AEM/CQ? Did your attempt to find what you needed on Google or discussion groups fail? In your gut, do you know it's possible to implement the feature since AEM performs a very similar operation? If you answered yes to any of these questions, some degree of reverse engineering may do the trick.

Before we get started, let's use a real world example. The other day I had to solve a relatively simple problem in AEM: for a given asset in the DAM find its references through out the site—namely, references to pages. Sounds simple, right? Well, my Google search failed and I didn't even bother with the discussion group (not my style). So, here was my approach:

Finding an Example in AEM

If AEM performs the feature that you're looking for, chances are good that you can implement the same feature as well. In my case, I know that you can get the references for an asset from the "References" tab in AEM's asset editor.

AEM's Asset Editor with "References" tab.

Now that we know that this is possible, let's see how they implemented this feature.

Find the AJAX Request

Now, we need to find the AJAX request tied to this behavior. Launch Google Developer Tools (or any tool that allows you to capture HTTP requests) and click the "Network" tab. Then, click the refresh icon in the pane that contains the "References" tab. Success! We found that this UI is tied to http://localhost:4502/bin/wcm/references.json?path=%2Fcontent%2Fdam%2Fgeometrixx-outdoors%2Fbanners%2Fadventure.jpg&predicate=wcmcontent.

Google Developer Tools > Network

I issued this request in a new browser window and it returned exactly what I needed. However, I do not want to issue an HTTP request from within my application using HttpCilent, however, this would work. Instead, I want to do this with native Java code.

/bin/wcm/references.json

Find the Servlet

Next, we need to find the Servlet that implements /bin/wcm/references.json. Easy, there is a tool in the Felix Console that provides this mapping called the "Sling Servlet Resolver." Navigate to http://localhost:4502/system/console/servletresolver and enter /bin/wcm/references.json as the URL and click the "resolve" button. Immediately, we see that com.day.cq.wcm.core.impl.servlets.ReferenceSearchServlet is the implementing class.

Sling Servlet Resolver

Find the Bundle

The next step is a little trickier as we need to find the bundle that includes com.day.cq.wcm.core.impl.servlets.ReferenceSearchServlet. Fortunately, we are dealing with a Servlet, so it will be registered as an OSGi component. If we visit the Components section in Felix, http://localhost:4502/system/console/components, and search for, ReferenceSearchServlet, we quickly notice that this component is part of the com.day.cq.wcm.cq-wcm-core bundle.

Felix Components

Now, it's off to the Bundles section in Felix, http://localhost:4502/system/console/bundles. Search for com.day.cq.wcm.cq-wcm-core and take a look at the bundle properties. Notice that the jar for this bundle is located under /libs/wcm/core/install/cq-wcm-core-5.6.14.jar. Use either vault or create a package to obtain this JAR.

Felix Bundles

Decompile the JAR

Decompile the JAR and inspect the decompiled code for com.day.cq.wcm.core.impl.servlets.ReferenceSearchServlet. I will not go into this, but anyone working in the Java space should now how to do this.

Conclusion

Well, after all these steps, it turns out that the solution to my problem was quite simple. I found that there is a public API called com.day.cq.wcm.commons.ReferenceSearch that makes finding references trivial. Just use ReferenceSearch.search(ResourceResolver resolver, String path).

Phew...time for a coffee break, writing 3-4 lines of reference code took an hour.