Monday, 19 April 2010

Creating QR Codes for Apache Sling URLs

Matt Cutts mentioned recently that the goo.gl URL shortening service had a trick where if a ".qr" extension is added to the shortened URL then a QR Code image is generated for that URL.

After a quick look at the Apache Sling documentation it seemed that adding such a feature to Sling/ Day CQ would be pretty easy, especially as goo.gl uses the Google Chart API to create the images.

To deal with requests within Sling based on the url extension, a Servlet Service must be added via an OSGi bundle and use service reference properties to detail which extensions/paths/selectors/methods/prefix are handled by this servlet.  Thanks to the maven-bundle-plugin and maven-scr-plugins, packaging this bundle for deployment using Maven is a piece of cake.

The Servlet is quite simple. Here are the SCR annotations from the Servlet class javadoc that tell the Sling what type of requests this Servlet will service:
/**
 * @scr.service interface="javax.servlet.Servlet"
 * @scr.property name="sling.servlet.resourceTypes"
 *               value="sling/servlet/default"
 *
 * @scr.property name="sling.servlet.extensions" value = "qr"
 */

and here are the couple of lines that create the redirect URL for the QR Code image and send that in the response.

private static final String baseUrl = "http://chart.apis.google.com/chart?cht=qr&chs=150x150&choe=UTF-8&chld=H&chl=";
 
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ... { 
 resp.sendRedirect(baseUrl + removeQRExtension(req));
} 

protected String removeQRExtension(HttpServletRequest req) {
 StringBuffer url = req.getRequestURL();
 return url.substring(0, url.length() -3);  
} 

Once the OSGi bundle is installed, you can add the .qr extension to any url on your Sling/CQ5 server and get back a QR code for that URL. For example the CQ5 URL
http://localhost:4502/libs/cq/core/content/welcome.html.qr
will give you this QR Code.

Although QR codes not yet made it mainstream, they provide a great way for mobile users to grab information quickly and there seem to be plenty of QR code readers out there.  I have been using QuickMark on the iPhone and that works great for me.


The full code can be found here
and the compiled OSGi bundle can be found here