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