Closed marto closed 7 months ago
I haven't tested it, but this can happen because some of the injected variables come from the sling script bindings (which haven't been initialized before the request gets to your servlet).
Try adding this
/**
* Bundle context.
*/
private BundleContext bundleContext;
/**
* Activate the service.
*
* @param bundleContext The bundle context.
*/
@Activate
protected void activate(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) throws ServletException, IOException {
SlingBindings bindings = new SlingBindings();
bindings.setSling(new ScriptHelper(bundleContext, null, req, resp));
req.setAttribute(SlingBindings.class.getName(), bindings);
// ....
}
You can see an example of this being done in the SearchResultServlet
Thanks @ky940819, that was the issue.
It seems that allot of the models now rely on the SlingBindings to be setup which are always setup when you use those models inside a HTL template but have to be manually setup if accessed directly from a filter/servlet. For reference here is the working code.
package com.adobe.aem.guides.wknd.core.servlets;
import com.adobe.cq.wcm.core.components.models.Teaser;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.models.factory.ModelFactory;
import org.apache.sling.scripting.core.ScriptHelper;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
@Component(service = { Servlet.class })
@SlingServletResourceTypes(
resourceTypes= { "wknd/components/teaser"},
methods=HttpConstants.METHOD_GET,
selectors="custom",
extensions = "html"
)
public class SSRComponentServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(getClass());
@Reference
private ModelFactory modelFactory;
private BundleContext bundleContext;
@Activate
protected void activate(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) throws ServletException, IOException {
Object model = null;
String response = null;
logger.error("SSRComponentServlet is being executed");
final SlingBindings binding = new SlingBindings();
binding.setSling(new ScriptHelper(bundleContext, null, req, resp));
binding.setResponse(resp);
binding.setRequest(req);
binding.setResource(req.getResource());
req.setAttribute(SlingBindings.class.getName(), binding);
logger.error("Added " + SlingBindings.class.getName());
try {
model = modelFactory.getModelFromWrappedRequest(req, req.getResource(), Teaser.class);
} catch (Exception e) {
logger.error("An error occurred while resolving the model from req.adaptTo.", e);
response = "<html><body><h1>Error: An error occurred while resolving the model from modelFactory.getModelFromWrappedRequest.</h1><p>Model: " + e.getLocalizedMessage() + "</p></body></html>";
}
if (model != null) {
String modelAsString = objectMapper.writeValueAsString(model);
response = "<html><body><h1>OK</h1><p>Model: " + modelAsString + "</p></body></html>";
}
// Write the response body to the servlet response writer
resp.setContentType("text/html");
resp.setStatus(model == null ? 500 : 200);
resp.getWriter().write(response);
}
}
For testing this is usefull: https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/junit-test-cases-for-sling-models-based-on-delegation-pattern/m-p/396541
Bug Report
Current Behavior Majority of WCM Core components can not be adapted from a SlingHttpServletRequest to a model in code. We can no longer use and extend WCM Core components using the proxy pattern as per the recommended way of using and extending core components. For example a Teaser or Button component can no longer be adapted. The example below shows how proxy components can't be adapted.
Expected behavior/code
modelFactory.getModelFromRequest
method should return a valid model and not nullslingHttpServletRequest.adaptTo(Teaser.class)
method should return a valid model not nullEnvironment
Possible Solution Not sure if this is an AEM issue or a Core Components issue.
Additional context / Screenshots
Expected Behaviour:
Impact
Errors: