This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch issue/SLING-13103 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-starter-integration-tests.git
commit 68465aad23843a8061170ffd45644801595ad296 Author: Robert Munteanu <[email protected]> AuthorDate: Tue Feb 10 11:36:03 2026 +0100 SLING-13103 - Wrong ResourceResolver set in script bindings after request dispatch in a Jakarta Context Add an integration test validating resource resolver bindings after dispatching with custom wrappers. --- .../JspDefineObjectsResolverWrapperTest.java | 146 +++++++++++++++++++++ .../integration-test/resolver-wrapper-test.jsp | 33 +++++ 2 files changed, 179 insertions(+) diff --git a/src/main/java/org/apache/sling/starter/webapp/integrationtest/JspDefineObjectsResolverWrapperTest.java b/src/main/java/org/apache/sling/starter/webapp/integrationtest/JspDefineObjectsResolverWrapperTest.java new file mode 100644 index 0000000..bb2653c --- /dev/null +++ b/src/main/java/org/apache/sling/starter/webapp/integrationtest/JspDefineObjectsResolverWrapperTest.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.starter.webapp.integrationtest; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.sling.commons.testing.integration.HttpTest; +import org.apache.sling.commons.testing.junit.Retry; +import org.apache.sling.commons.testing.junit.RetryRule; +import org.apache.sling.servlets.post.SlingPostConstants; +import org.apache.sling.starter.webapp.integrationtest.util.UniqueResourceType; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Test that a javax.servlet.Filter wrapping the SlingHttpServletRequest + * with a custom ResourceResolver has that ResourceResolver properly + * propagated to JSP scripts via <sling:defineObjects />. + * + * <p>This test verifies backward compatibility with the Jakarta migration: + * when a javax Filter wraps the request with a custom + * SlingHttpServletRequestWrapper that overrides getResourceResolver(), + * the resourceResolver variable set by DefineObjectsTag in JSPs should + * reflect the custom wrapper, not the original request's resolver.</p> + */ +public class JspDefineObjectsResolverWrapperTest { + + private String nodeUrl; + private String scriptPath; + private Set<String> toDelete = new HashSet<>(); + + /** HTTP tests helper */ + private final HttpTest H = new HttpTest(); + + @Rule + public RetryRule retryRule = new RetryRule(); + + @Before + public void setUp() throws Exception { + H.setUp(); + + // Create a test node with a unique resource type + UniqueResourceType urt = new UniqueResourceType(); + final String url = HttpTest.HTTP_BASE_URL + "/" + getClass().getSimpleName() + "/" + System.currentTimeMillis() + + SlingPostConstants.DEFAULT_CREATE_SUFFIX; + final Map<String, String> props = new HashMap<>(); + props.put("sling:resourceType", urt.getResourceType()); + props.put("text", "test-content"); + nodeUrl = H.getTestClient().createNode(url, props); + + // Upload the test JSP that outputs resourceResolver class names + scriptPath = urt.getScriptPath(); + H.getTestClient().mkdirs(HttpTest.WEBDAV_BASE_URL, scriptPath); + toDelete.add(H.uploadTestScript(scriptPath, "resolver-wrapper-test.jsp", "html.jsp")); + } + + @After + public void tearDown() throws Exception { + H.tearDown(); + for (String script : toDelete) { + H.getTestClient().delete(script); + } + } + + /** + * Test that without the wrapping filter, the resourceResolver from + * defineObjects is the normal resolver (baseline test). + */ + @Test + @Retry + public void testWithoutWrapper() throws IOException { + final String content = H.getContent(nodeUrl + ".html", HttpTest.CONTENT_TYPE_HTML); + // Without the filter, resolversMatch should be true (defineObjects and bindings should agree) + assertTrue( + "resolversMatch should be true without wrapper: " + content, content.contains("resolversMatch=true")); + } + + /** + * Test that when a javax Filter wraps the request with a custom ResourceResolver, + * the script bindings resolver reflects the custom wrapper. This verifies the fix + * in DefaultSlingScript.verifySlingBindings(). + */ + @Test + @Retry + @Ignore("SLING-13103") + public void testBindingsResolverIsCustomWrapper() throws IOException { + // Trigger the ResourceResolverWrappingFilter by adding the wrapResourceResolver param + final String content = H.getContent(nodeUrl + ".html?wrapResourceResolver=true", HttpTest.CONTENT_TYPE_HTML); + + // The bindings resolver should be the custom wrapper + assertTrue( + "Bindings resolver should be custom wrapper: " + content, + content.contains( + "bindingsResolverClass=org.apache.sling.starter.testservices.filters.ResourceResolverWrappingFilter$CustomResourceResolverWrapper")); + } + + /** + * Test that when a javax Filter wraps the request with a custom ResourceResolver, + * the resourceResolver variable set by DefineObjectsTag also reflects the custom + * wrapper and matches the bindings resolver. This verifies the fix in + * DefineObjectsTag.doEndTag() (org.apache.sling.scripting.jsp.taglib). + */ + @Test + @Retry + @Ignore("SLING-13103 or follow-up") + public void testDefineObjectsResolverMatchesBindings() throws IOException { + // Trigger the ResourceResolverWrappingFilter by adding the wrapResourceResolver param + final String content = H.getContent(nodeUrl + ".html?wrapResourceResolver=true", HttpTest.CONTENT_TYPE_HTML); + + // The defineObjects resolver SHOULD also be the custom wrapper + assertTrue( + "DefineObjects resolver should be custom wrapper: " + content, + content.contains( + "defineObjectsResolverClass=org.apache.sling.starter.testservices.filters.ResourceResolverWrappingFilter$CustomResourceResolverWrapper")); + + // They should match + assertTrue( + "DefineObjects resolver should match bindings resolver: " + content, + content.contains("resolversMatch=true")); + } +} diff --git a/src/main/resources/integration-test/resolver-wrapper-test.jsp b/src/main/resources/integration-test/resolver-wrapper-test.jsp new file mode 100644 index 0000000..c97bc5b --- /dev/null +++ b/src/main/resources/integration-test/resolver-wrapper-test.jsp @@ -0,0 +1,33 @@ +<%-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--%> +<%@page session="false"%> +<%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%> +<sling:defineObjects/> +<% + // Output the class names of the resource resolver from defineObjects and from the bindings + org.apache.sling.api.scripting.SlingBindings b = + (org.apache.sling.api.scripting.SlingBindings) + request.getAttribute(org.apache.sling.api.scripting.SlingBindings.class.getName()); + Object bindingsResolver = b.get("resolver"); +%> +defineObjectsResolverClass=<%= resourceResolver.getClass().getName() %> +bindingsResolverClass=<%= bindingsResolver != null ? bindingsResolver.getClass().getName() : "null" %> +resourceResolverFromResource=<%= resource.getResourceResolver().getClass().getName() %> +resolversMatch=<%= resourceResolver == bindingsResolver %>
