CQ & Sling servlets: resourceType

Last time we see how to use Sling servlets with old legacy URL. Today we’ll see how to create Sling Servlets in the Sling-way: using resourceType.

Scenario

We want a component that can be dragged into a parsys. With a form that submit data to a sling servlet. Then the servlet will do the operations required.

Process

Let’s create the component following the CQ guidelines for making it drag-droppable into a parsys (allowedParents): geometrixx/components/test003. The test003.jsp will look like the following:

<%@include file="/libs/foundation/global.jsp"%>
<form name="frm" method="post" action="<c:out value="${resource.path}" />.c">
    <input type="submit" />
</form>

This JSP will answer at a GET http call showing the form. In order to use, create a content page and drag the component into a parsys.

Now it’s time to create the servlet. As usual you’ll have to register it using some felix annotations. The following servlet will be used when posting (HTTP POST) to a resource of type geometrixx/components/test003 with an extension of “c”.

package com.samples.sling;

import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @scr.component immediate="true" metatype="false"
 * @scr.service interface="javax.servlet.Servlet"
 * @scr.property name="sling.servlet.methods" values.0="POST"
 * @scr.property name="sling.servlet.resourceTypes" values.0="geometrixx/components/test003"
 * @scr.property name="sling.servlet.extensions" values.0="c"
 */

public class ResourceTypePostServlet extends SlingAllMethodsServlet {
   private static final long serialVersionUID = 8795673847499208743L;
   private final static Logger logger = LoggerFactory.getLogger(ResourceTypePostServlet.class);

   @Override
   protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
      logger.debug("ResourceTypePostServlet::doPost()");
      response.setContentType("text/plain");
      response.getOutputStream().print("Hello ResourceTypePostServlet World!");
   }
}

We used the sling.servlet.methods to specify which HTTP method the servlet listen to, the sling.servlet.resourceTypes to specify all the resource types is should listen to and the .extensions if you wish to specify an extension.

Remember that if you specify a sling.servlet.paths, resourceTypes, extensions and selectors will be ignored.

Now build the bundle and refresh the previously created content page (should not necessary actually). If you click on the “submit” button you’ll see the Hello World.

References:

CQ & Sling servlets: old legacy URL

SlingIn this short article (first of a serie I hope) I’ll show you how to create a Sling Servlet in CQ.

Scenario

You are migrating your existing application in CQ a piece at time and it’s time for the Servlets (controllers) part, so for the first stage you’d like to keep the old URLs. Maybe because some other external services are calling you at these coordinates or because you don’t want to enter each jsp and change the forms action.

Ingredients

  • CQ instance running in Author (localhost:4502)
  • CRXDE (let’s ease the game for starting)

Process

Create a new OSGi bundle under geometrixx (or your app). In this create a new class that extends the SlingSafeMethodsServlet.
Then you have to register as a service in the OSGi container. This is done using the Felix annotations as following:

/**
 * @scr.component immediate="true" metatype="false"
 * @scr.service interface="javax.servlet.Servlet"
 * @scr.property name="sling.servlet.methods" values.0="GET"
 * @scr.property name="sling.servlet.paths" values.0="/path/to/my/servlet"
 *                                          values.1="/apps/path/to/my/servlet"
 */

I’ll leave you to the references section of this post for getting deeper into the meaning of each.

At the end your code will look something like the following:

package com.samples.sling;

import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @scr.component immediate="true" metatype="false"
 * @scr.service interface="javax.servlet.Servlet"
 * @scr.property name="sling.servlet.methods" values.0="GET"
 * @scr.property name="sling.servlet.paths" values.0="/path/to/my/servlet"
 *                values.1="/apps/path/to/my/servlet"
 */
public class AbsoluteUrlServlet extends SlingSafeMethodsServlet {
   private static final long serialVersionUID = -1920460619265757059L;
   private static final Logger logger = LoggerFactory.getLogger(AbsoluteUrlServlet.class);

   @Override
   protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
      logger.debug("AbsoluteUrlServlet::doGet()");
      response.setContentType("text/plain");
      response.getOutputStream().print("Hello AbsoluteUrlServlet World!");
   }
}

Looking at the sling.servlet.paths annotation we se on which url we are actually mapping the servlet: /path/to/my/servlet and /apps/path/to/my/servlet.

Building the bundle and CRXDE+felix will do the magic of the deployment.

Now if you try to run localhost:4502/apps/path/to/my/servlet you’ll see our beautiful Helloworld, but if you’ll try to access localhost:4502/path/to/my/servlet you’ll get a 404 or a content listing.
This is due to a settings in felix+Sling. Open the felix console at the configuration tab (/system/console/configMgr) and search for Apache Sling Servlet/Script Resolver and Error Handler. Here you’ll have to add “/path/” to the Execution Paths section.

Done done!

References