by Oliver Choy

Created

August 19, 2012

A lot of enterprise grade systems require some sort of integration with other services these days, to extend and bring in more features into the systems. In this blog post I would like to show a quick and easy way to integrate CQ5 with other web services. Examples below will be showing a RESTful webservice but other webservices like SOAP will take similar approach.

Webservices integration usually involves building a integration layer. A Java Servlet would definitely be a good candidate. But to avoid building / compiling / packaging / deploying such code into an OSGi container, one can easily write a JSP (on the fly) in CQ to handle the integration.

Create an integration layer page:

This integration page is basically to create an instance of a CQ Page so that the rest of the content pages can communicate to it (Things under /app are not exposed or cannot be called directly). And extra benefit about this CQ Page -> You can control who has access to it!

Note the above page is using “Demo – API Page Template”, and here is the mapping:

 

And apipage.jsp is nothing more than what you want to surface in a typical Servlet.  Here is snippet of the code:

if (request.getParameter("action") != null) {
    if (request.getParameter("action").equals("getSomething")) {
        Node demoNode = resourceResolver.getResource(INTEGRATION_DESIGN_NODEPATH).adaptTo(Node.class);
        response.setContentType("application/json");
        out.write(getSomething(demoNode));
 
    } else if (request.getParameter("action").equals("getCategories")) {
        Node demoNode = resourceResolver.getResource(INTEGRATION_DESIGN_NODEPATH).adaptTo(Node.class);
        response.setContentType("application/json");
        out.write(getCategories(demoNode));
 
    } else if (request.getParameter("action").equals("getFields") &&
            request.getParameter("param1") != null &&
            request.getParameter("param2") != null) {
        response.setContentType("application/json");
        out.write(getFields(
            request.getParameter("param1"),
            request.getParameter("param2"));
 
    } else {
        response.setContentType("application/json");
        out.write("{\"error\":\"error\"}");
    }
}

 

And derived from the above, we now have the following links to retrieve data:

http://_server_:_port_/content/integrationdemo/en/integration/integrationapi?action=getSomething

http://_server_:_port_/content/integrationdemo/en/integration/integrationapi?action=getCategories

http://_server_:_port_/content/integrationdemo/en/integration/integrationapi?action=getFields&param1=test&param2=data

 

The integration implementation will be per your requirements, but at a high level you can pretty much do everything-in-a-servlet inside a JSP. JSPs are Servlets after all. Here is a snippet of a http call (to a webservice) inside the same JSP:

 

static String getFields(String apiKey, String accessToken, String someJson) {
    HttpClient httpClient = new HttpClient();
    HttpClientParams httpClientParams = new HttpClientParams();
    DefaultHttpMethodRetryHandler defaultHttpMethodRetryHandler = new DefaultHttpMethodRetryHandler(0, false);
    httpClientParams.setParameter(HttpClientParams.RETRY_HANDLER, defaultHttpMethodRetryHandler);
    httpClient.setParams(httpClientParams);
 
    PostMethod post = new PostMethod(EXTERNAL_WEBSERVICE_API_URL+apiKey.trim()+"/URL_EXAMPLE/test?oauth_token="+accessToken.trim());
    post.addRequestHeader("Accept", "application/json");
    post.addRequestHeader("Content-Type", "application/json");
    post.setRequestBody(someJson);
 
    try {
        httpClient.executeMethod(post);
        String result = post.getResponseBodyAsString();
 
        if (result != null && !result.equals("")) {
            JSONObject returnObj = new JSONObject(result);
            return returnObj.toString();
        } else {
            return "";
        }
    } catch (Exception ex) {
        return ex.getMessage();
    }   
}

 

And finally, as an option (if you want to integration the CQ authoring experience with an external webservice), you can expose the data retrieved inside a CQ Component dialog field, you will need to configure the widget to retrieve webservice data. Details are documented in:

http://dev.day.com/docs/en/cq/current/widgets-api/index.html?class=CQ.form.Selection

Here’s a quick example:

And the result:

 

Enjoy~