May 20, 2020
Estimated Post Reading Time ~

Programmatically find the Sling Resource from a Given a URL

In CQ, ResourceResolver class can be used for resolving a Request into a Sling Resource. However, given a random URL served by a CQ instance, how do you figure out the corresponding Sling Resource of the given URL as a result of Resource Mapping definition?

Let's assume we have some Resource Mapping rules (mapping definition) set up on our Author node via /etc/map so that a sample request to,

URL: http://dictionary.mycompany.com/definition/visa-validity.html

will be served by the resource at,

Sling Resource: /content/public/dictionary/legal-terms/v/visa-validity.html

You can have as many Resource Mapping rules (mapping definition) as you want. The above mapping is just an example. I want to use this example to demonstrate how did I programmatically figure out the corresponding resource from a given URL.

ResourceResolver

ResourceResolver class was implemented to return Resource. Specifically, the resolve() functions exist for this type of resolution. However, even there are three overloaded resolve() functions, none of them takes in a URL String.

Resource resolve(HttpServletRequest request)
Deprecated. as of 2.0.4, use resolve(HttpServletRequest, String) instead.

Resource resolve(HttpServletRequest request, String absPath)
Resolves the resource from the given absPath optionally taking HttpServletRequest into account, such as the value of the Host request header.

Resource resolve(String absPath)
Resolves the resource from the given absolute path.

The thought process
Given ResourceResolver takes in HttpServletRequest as input, if I can transform (adapt) a given URL into a HttpServletRequest using HttpServletRequestWrapper, the problem will be solved. Therefore, I implemented a ResolverRequest class which extends HttpServletRequestWrapper.

Code Sample:
package com.company.util.http;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;

public class ResolverRequest extends HttpServletRequestWrapper {

private final URI uri;

public ResolverRequest(HttpServletRequest request, String uriString)
throws URIException {
super(request);
uri = new URI(uriString, false);
}

@Override
public String getScheme() {
return uri.getScheme();
}
@Override
public String getServerName() {
try {
return uri.getHost();
} catch (URIException ue) {
return null;
}
}

@Override
public int getServerPort() {
return uri.getPort();
}

@Override
public String getPathInfo() {
try {
return uri.getPath();
} catch (URIException ue) {
return "";
}
}
}

Once you have ResolverRequest class implemented and available to you, you can construct a ResolverRequest from an URL string, and pass the ResolverRequest into resolve() function of ResourceResolver to find the Resource. Problem solved:

<?xml version="1.0" encoding="UTF-8"?>
<%@page session="false"
content
pageEncoding="utf-8"
import="org.apache.sling.api.request.*,
com.company.util.http.ResolverRequest" %>
<%@include file="/libs/foundation/global.jsp" %>
<cq:defineObjects/>

<%
RequestParameter url_request_param = slingRequest.getRequestParameter("url"); // 1
pageContext.setAttribute("url_request_param", url_request_param);
%>

<result>
<c:choose>
<c:when test="${url_request_param == null}">
<error>
url parameter needed!
</error>
</c:when>

<c:otherwise>
<%
HttpServletRequest wrappedRequest = new ResolverRequest(request, url_request_param.getString());
Resource r = resourceResolver.resolve(wrappedRequest, wrappedRequest.getPathInfo());
%>

<%=r.getPath() %>

</c:otherwise>
</c:choose>
</result>

Get the value of url parameter from the request (e.g., "http://localhost:4502/apps/company/tools/dispatcher/invalidate?url=http://dictionary.mycompany.com/definition/visa-validity.html")



By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.