AEM Cloud Service - Assets Metadata Schema Json Data Servlet for Dropdown Options


In Assets Metadata Schema Editor an author can provide jsonPath for values in a Drop Down widget. Json Path should be a resource, so this post creates a Synthetic Resource which in turn gets the Options JSON from a Servlet...

Demo | Package Install | Github




Solution

1) Create a maven project...

set JAVA_HOME=C:/Progra~1/Java/jdk-11

mvn -B org.apache.maven.plugins:maven-archetype-plugin:3.2.1:generate -D archetypeGroupId=com.adobe.aem
    -D archetypeArtifactId=aem-project-archetype -D archetypeVersion=51 -D aemVersion="cloud"
    -D appTitle="AEM Metadata Schema Json Synthetic Res" -D appId="eaem-meta-schema-json-synt-res"
    -D groupId="apps.experienceaem.assets" -D frontendModule=none -D includeExamples=n -D includeErrorHandler=n
    -D includeDispatcherConfig=n


2) Create a Resource Provider  MetadataOptionsResourceProvider to call the servlet /bin/eaem/metadata/options prepare a Synthetic Resource MetadataOptionsSyntheticResource  when root path is /content/api/eaem

package apps.experienceaem.assets.core.servlets;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.engine.SlingRequestProcessor;
import org.apache.sling.spi.resource.provider.ResolveContext;
import org.apache.sling.spi.resource.provider.ResourceContext;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.contentsync.handler.util.RequestResponseFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component(
    service = ResourceProvider.class,
    property = {
        ResourceProvider.PROPERTY_ROOT + "=/content/api/eaem",
        ResourceProvider.PROPERTY_MODIFIABLE + "=false"
    }
)
public class MetadataOptionsResourceProvider extends ResourceProvider<Object> {
   
    private static final Logger LOG = LoggerFactory.getLogger(MetadataOptionsResourceProvider.class);
   
    private static final String RESOURCE_PATH = "/content/api/eaem/metadata-options.json";
    private static final String JSON_FEED_SERVLET_PATH = "/bin/eaem/metadata/options";

    @Reference
    private RequestResponseFactory requestResponseFactory;

    @Reference
    private SlingRequestProcessor slingRequestProcessor;

    @Override
    public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext resourceContext, Resource parent) {
        if (RESOURCE_PATH.equals(path)) {
            return createMetadataOptionsResource(ctx.getResourceResolver());
        }
        return null;
    }
   
    @Override
    public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
        return Collections.emptyIterator();
    }
   
    private Resource createMetadataOptionsResource(ResourceResolver resolver) {
        String jsonData = "{}";

        try {
            Map<String, Object> requestParams = new HashMap<String, Object>();
            HttpServletRequest request = (HttpServletRequest) requestResponseFactory.createRequest("GET", JSON_FEED_SERVLET_PATH,requestParams);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            HttpServletResponse response = (HttpServletResponse) this.requestResponseFactory.createResponse(bos);

            slingRequestProcessor.processRequest(request, response, resolver);

            response.getWriter().flush();

            jsonData = bos.toString();
        } catch (Exception e) {
            LOG.error("Error fetching data from servlet: {}", JSON_FEED_SERVLET_PATH, e);
        }
       
        return new MetadataOptionsSyntheticResource(resolver, RESOURCE_PATH, jsonData);
    }
}


3) Create the Synthetic Resource MetadataOptionsSyntheticResource

package apps.experienceaem.sites.core.servlets;

import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.SyntheticResource;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class MetadataOptionsSyntheticResource extends SyntheticResource {
   
    private static final String NT_FILE = "nt:file";
   
    private final String path;
    private final String data;

    public MetadataOptionsSyntheticResource(ResourceResolver resourceResolver, String path, String data) {
        super(resourceResolver, path, NT_FILE);
        this.path = path;
        this.data = data;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
        if (type == InputStream.class) {
            return (AdapterType) new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
        }
        return super.adaptTo(type);
    }
}


4) Add the servlet MetadataOptionsServlet for returning data to feed the Synthetic Resource...

package apps.experienceaem.assets.core.servlets;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.service.component.annotations.Component;

import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.Servlet;

@Component(
    service = Servlet.class,
    property = {
        "sling.servlet.paths=/bin/eaem/metadata/options",
        "sling.servlet.methods=GET"
    }
)
public class MetadataOptionsServlet extends SlingSafeMethodsServlet {
    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
        throws ServletException, IOException {
        response.setContentType("text/plain");
        String json = "{\n" +
                      "  \"options\":[\n" +
                      "    {\n" +
                      "      \"text\":\"One\",\n" +
                      "      \"value\":\"OPTION_ONE\"\n" +
                      "    },\n" +
                      "    {\n" +
                      "      \"text\":\"Two\",\n" +
                      "      \"value\":\"OPTION_TWO\"\n" +
                      "    },\n" +
                      "    {\n" +
                      "      \"text\":\"Three\",\n" +
                      "      \"value\":\"OPTION_THREE\"\n" +
                      "    }\n" +
                      "  ]\n" +
                      "}";
        response.getWriter().write(json);
    }
}





No comments:

Post a Comment