Enhancing JSON Response Dynamically in AEM with Sling Filters
In the realm of web development, customizing JSON responses dynamically based on specific criteria is a common requirement. Recently, our team encountered such a scenario in Adobe Experience Manager (AEM) where we needed to modify the JSON response based on a URL value within the response itself. In this blog post, I’ll walk you through our solution using Sling Filters in AEM, along with code snippets to illustrate the implementation.
Understanding the Requirement
Our requirement was to augment the main JSON response with additional data fetched from a URL provided within the response. Essentially, we needed to append the response from this URL to the main JSON structure before sending it back to the client.
Solution Overview
To achieve this dynamic modification of the JSON response, we leveraged Sling Filters in AEM. Sling Filters allow us to intercept requests and responses in AEM, making them a perfect fit for our use case. Here’s an overview of the solution:
- Identify the URL within the JSON response: We first needed to parse the incoming JSON response to locate the URL that contains the additional data we want to append.
- Implement a Sling Filter: We created a custom Sling Filter that intercepts the request and response. Within this filter, we extracted the URL from the JSON response and made an HTTP request to fetch the additional data.
- Append data to the main JSON response: Once we retrieved the additional data from the URL, we appended it to the main JSON response.
- Return the modified JSON response: Finally, we returned the modified JSON response to the client.
Implementation Steps
Let’s dive into the implementation details with code snippets:
- Create the Sling Filter
@Component(service = Filter.class, immediate = true, name = "TTN Custom JSON Filter", property = { EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST, EngineConstants.SLING_FILTER_METHODS + "=" + METHOD_GET, EngineConstants.SLING_FILTER_PATTERN + "=" + "/content/ttn/api/v1/offers", EngineConstants.SLING_FILTER_SELECTORS + "=" + model, EngineConstants.SLING_FILTER_EXTENSIONS + "=" + "json" }) public class CustomJsonFilter implements Filter { @Reference private HttpClient httpClient; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { apiUrlResponseMap = new HashMap<>(); SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request; SlingHttpServletResponse modelResponse = new offerSlingModelResponseWrapper((SlingHttpServletResponse) response); chain.doFilter(slingRequest, modelResponse); PrintWriter responseWriter = response.getWriter(); updateJson(modelResponse.toString(), responseWriter); } catch (ServletException | IOException e) { logger.error("doFilter: Exception Occurred: {}", e.getMessage()); } } /** * Iterates the json response of cms api * * @param modelResponse the response object * @param responseWriter the printWriter object */ protected void updateJson(String modelResponse, PrintWriter responseWriter) { // write down the logic to update the json response } @Override public void init(FilterConfig filterConfig) throws ServletException { // Do nothing } @Override public void destroy() { // Cleanup logic } }
- Implement HTTP Client Service
/** * Http Request Data Service component that returns the API response in String * */ @Component(service = HttpRequestDataService.class, immediate = true) public class HttpRequestDataServiceImpl implements HttpRequestDataService { @Override public String invokeHttpRequest(URL endpointUrl) { // Make HTTP request to fetch additional data // Return response body as String } }
Conclusion
By utilizing Sling Filters in AEM, we successfully achieved dynamic modification of JSON responses based on specific criteria. This approach not only met our requirement but also demonstrated the flexibility and extensibility of AEM in handling diverse use cases.