How to invoke Sling Servlet that uses "resourceType" instead of "paths" in @SlingServlet annotation

mitchj picture mitchj · Mar 17, 2015 · Viewed 17.2k times · Source

How do I invoke a Sling Servlet that uses the "resourceType" property inside @SlingServlet? When I use"paths" I just call it with an ajax call but I am not sure what to do if I change my servlet to use "resourceType" instead of "paths". (I am making the change for learning purposes)

I am still learning CQ5, Sling, etc.

My servlet follows.

package com.mypackage.weather;

import org.apache.sling.api.resource.*;
import org.apache.sling.commons.osgi.PropertiesUtil;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import javax.servlet.ServletException;
import java.io.BufferedReader;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SlingServlet(
        name="Weatherservlet",
        //paths="/bin/Weather",
        resourceType="OpenWeather/components/page/contentPage",
        methods="GET",
        metatype=true)
@Properties({
        @org.apache.felix.scr.annotations.Property(name="WeatherServlet", description="Get JSON String weather info", value="mitch weather"),
        @org.apache.felix.scr.annotations.Property(name = "apikey", label = "The api key", value = "d8e39388b0bc54a62ffc6b385639b3dc") // register the api key in the OSGi console
})

/**
 * Handles requests for getting weather information from OpenWeatherMap.org.  returns the information as a JSon string.
 */
public class WeatherServlet extends SlingSafeMethodsServlet {

    private static final String SERVER = "localhost:4502";
    private static final String RESOURCE_PATH = "/content/OpenWeather";
    private String apikey = "";
    private String location = "";
    private ResourceResolver resourceResolver;

    private Logger logger = LoggerFactory.getLogger(WeatherServlet.class);

    @Override
    public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        logger.info("Reconfigured Weather Servlet");
        getWeather(request, response);

    }

    /**
     * Gets current weather information from OpenWeatherMap.org API
     * @param request
     * @param response
     * @throws IOException
     */
    public void getWeather(SlingHttpServletRequest request, SlingHttpServletResponse response)   {
        logger.info("api key: " + apikey);
        location = request.getParameter("city");
        logger.info("city sent: " + location);
        String urlString = "http://api.openweathermap.org/data/2.5/weather?q=" + location + "&units=imperial&APPID=" + apikey;
        logger.info("urlString: " + urlString);
        URL url = null;
        HttpURLConnection connection = null;
        int responseCode = -9;
        String result = "";
        logger.info("Before call to Open Weather");
        long startTime = System.currentTimeMillis();
        try {
            url = new URL(urlString);
            logger.info("url: " + url);
            connection = (HttpURLConnection) url.openConnection();
            logger.info("Connection: " + connection);
            connection.setRequestMethod("GET");
            responseCode = connection.getResponseCode();
            logger.info("After calling Open Weather");
            BufferedReader reader;
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            logger.info("reader: " + reader);
            result = reader.readLine();
            long stopTime = System.currentTimeMillis();
            long elapsedTime = stopTime - startTime;
            logger.info("Elapsed Time is... " + elapsedTime);
            logger.info("result: " + result);
            PrintWriter writer = response.getWriter();
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            writer.write(result);
        } catch (MalformedURLException e) {
            logger.info("MalformedURL");
            e.printStackTrace();
        } catch (IOException e) {
            logger.info("IOException!!!!!!!!");
            e.printStackTrace();
            logger.info("Cause: " + e.getCause());
        }
    }


    protected void activate(ComponentContext context)
    {
        apikey = PropertiesUtil.toString(context.getProperties().get("apikey"), "d8e39388b0bc54a62ffc6b385639b3dc"); // Get the api key from the OSGi console
        System.out.println("weather servlet activated");
    }
}

Answer

Sharath Madappa picture Sharath Madappa · Mar 17, 2015

Instead of making ajax call to the path in the servlet, you make an ajax call to the component. In case you want the servlet to work with resourceType the servlet should have an additional configuration for extensions property (sling.servlet.extensions).This configuration let's you run a servlet in context of a resource(of a particular resourceType) instead of a global one.

Let me explain with an example. Consider a page content/home.html with a foo component (resourceType="/apps/someproject/components/foo) at path /par/foo . Normally on a page the component will be requested with .html selector and the resource will be rendered by the default script (foo.jsp). Let's add a servlet with the following annotation

@SlingServlet( name="Weatherservlet", extensions = "pdf", resourceType="someproject/components/foo", methods="GET", metatype=true) which will give pdf representation of the resource.

A GET request to /content/home/jcr:content/par/foo.pdf will be handled by the servlet instead of foo.jsp.

request.getResource() inside the servlet's doGet will return the component resource.

path configuration will override the resourceType configuration.