getServletPath() output JSP name instead of action name when a request is forwarded inside Servlet application in EAP 7
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 7.x
Issue
We are trying to migrate our application from JBoss EAP 6.x to JBoss EAP 7.x. We found that EAP 6.x and EAP 7.x return different results of Content from docs.oracle.com is not included.HttpServletRequest.getServletPath() (and also Content from docs.oracle.com is not included.getRequestURI() and getRequestURL()](https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html#getRequestURL--)) after invoking Content from docs.oracle.com is not included.RequestDispatcher.forward(). This behavior change causes an issue with our application using Struts and Siteminder framework.
-
In JBoss EAP 6.4:
getServletPath() = /example.action getRequestURI() = /myapp/example.action -
In JBoss EAP 7.x:
getServletPath() = /jsp/forward/example.jsp getRequestURI() = /myapp/jsp/forward/example.jsp
Also, you can observe the different behavior with the following code in the servlet application without using Struts framework:
System.out.println("getServletPath() before forward = " + request.getServletPath());
System.out.println("getRequestURI() before forward = " + request.getRequestURI());
System.out.println("getRequestURL() before forward = " + request.getRequestURL());
request.getRequestDispatcher("/jsp/forward/example.jsp").forward(request, response);
System.out.println("getServletPath() after forward = " + request.getServletPath());
System.out.println("getRequestURI() after forward = " + request.getRequestURI());
System.out.println("getRequestURL() after forward = " + request.getRequestURL());
-
In JBoss EAP 6.4:
getServletPath() before forward = /example getRequestURI() before forward = /myapp/example getRequestURL() before forward = http://<hostname>:<port>/myapp/example getServletPath() after forward = /example getRequestURI() after forward = /myapp/example getRequestURL() after forward = http://<hostname>:<port>/myapp/example -
In JBoss EAP 7.x:
getServletPath() before forward = /example getRequestURI() before forward = /myapp/example getRequestURL() before forward = http://<hostname>:<port>/myapp/example getServletPath() after forward = /jsp/forward/example.jsp getRequestURI() after forward = /myapp/jsp/forward/example.jsp getRequestURL() after forward = http://<hostname>:<port>/myapp/jsp/forward/example.jsp
Is it possible to make JBoss EAP 7 behave the same as JBoss EAP 6?
Resolution
The current EAP 7's behavior does not violate Servlet specification. However, we've added a compatible switch to restore the previous EAP 6's behavior since EAP 7.2.1 or later.
Update to JBoss EAP 7.2 CP1 and set the system property io.undertow.servlet.dispatch.preserve_path_of_forward to true in your standalone.conf (or add the system property in your configuration as described in this knowledge article):
JAVA_OPTS="$JAVA_OPTS -Dio.undertow.servlet.dispatch.preserve_path_of_forward=true"
In EAP 7.3.0 or later, set preserve-path-on-forward="true" to <servlet-container> in the undertow subsystem instead of the above system property. You can configure this by the following JBoss-CLI command:
/subsystem=undertow/servlet-container=default:write-attribute(name=preserve-path-on-forward,value=true)
then this will configure like the following in the undertow subsystem:
<servlet-container name="default" ...(snip)... preserve-path-on-forward="true">
...(snip)...
</servlet-container>
If you would like to change the behavior for the specific application only, update to EAP 7.2 CP2 or later, then implement and package your own Content from undertow.io is not included.ServletExtension which invokes DeploymentInfo.setPreservePathOnForward(true).
For example: create the following PreservePathOnForwardServletExtension class:
package org.jboss.support.example.
import javax.servlet.ServletContext;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.ServletExtension;
public class PreservePathOnForwardServletExtension implements ServletExtension {
@Override
public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
deploymentInfo.setPreservePathOnForward(true);
}
}
and package the above class and META-INF/services/io.undertow.servlet.ServletExtension which contains the following:
org.jboss.support.example.PreservePathOnForwardServletExtension
in your application.
Root Cause
- Undertow JIRAs:
- This content is not included.UNDERTOW-1159 - Getting JSP name instead action name for getServletPath() in EAP 7.0.0 undertow
- This content is not included.UNDERTOW-1499 - Make getServletPath return action name or jsp name configurable
- This content is not included.UNDERTOW-1504 - Move UNDERTOW-1159 configuration property of DeploymentInfo
- JBEAP JIRAs:
- This content is not included.JBEAP-16448 - (7.2.z) [EAP] Make getServletPath return action name or jsp name configurable
- This content is not included.JBEAP-16644 - (7.2.z) (EAP part) UNDERTOW-1504 - Move UNDERTOW-1159 configuration property of DeploymentInfo
- This content is not included.JBEAP-17141 - (7.3.0) Make getServletPath return action name or jsp name configurable
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.