NullPointerException occurred at HttpServletRequestImpl.getLocalAddr() in JBoss EAP 7.1.2

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP) 7.1.2

Issue

The following NullPointerException occurred when calling javax.servlet .ServletRequest#getLocalAddr() or javax.servlet .http.HttpServletRequest#getLocalAddr() in an application:

UT005023: Exception handling request to /example.jsp: org.apache.jasper.JasperException: java.lang.NullPointerException
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:473)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:403)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:347)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.jsp.JspFileHandler.handleRequest(JspFileHandler.java:32)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:64)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:330)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:812)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at io.undertow.servlet.spec.HttpServletRequestImpl.getLocalAddr(HttpServletRequestImpl.java:937)
	at org.apache.jsp.example_jsp._jspService(example_jsp.java:151)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
	... 43 more

Resolution

This is a bug reported as Content from issues.jboss.org is not included.JBEAP-14689 and this has been fixed in JBoss EAP 7.1 CP3 (EAP 7.1.3).

This issue happens when your application calls Content from docs.oracle.com is not included.ServletRequest#getLocalAddr() or HttpServletRequest.getLocalAddr() in the following conditions:

  • The request contains "X-Forwarded-Host" header and you configure proxy-address-forwarding="true" on http-listener/https-listener
  • The request come through ajp-listener (regardless of having "X-Forwarded-Host" header in the request)

Until the above JIRA is fixed, this issue can be workaround by either of the followings:

  • Using io.undertow.server.handlers.LocalNameResolvingHandler ('resolve-local-name' in expression-filter):

    This can avoid this NPE issue unless the destination address (Host header in AJP request or the X-Forwarded-Host header in HTTP request) is really unresolved. However, using this handler can impact performance. If a DNS server is unresponsive this could potentially add seconds to the request processing time.
    You can enable this by the following CLI:

    /subsystem=undertow/configuration=filter/expression-filter=resolve-local-name-filter:add(expression=resolve-local-name)
    /subsystem=undertow/server=default-server/host=default-host/filter-ref=resolve-local-name-filter:add()
    

    then standalone.xml configuration will be changed like the following:

        <subsystem xmlns="urn:jboss:domain:undertow:4.0">
            ...
            <server name="default-server">
                ...
                <host name="default-host" alias="localhost">
                    ...
                    <filter-ref name="resolve-local-name-filter"/> <!-- add this -->
                </host>
            </server>
            ...
            <filters>
                ...(snip)...
                <expression-filter name="resolve-local-name-filter" expression="resolve-local-name"/> <!-- add this -->
            </filters>
        </subsystem>
    
  • Using a custom servlet filter with HttpServletRequestWrapper to override getLocalAddr().

    For example:

@WebFilter("/*")
public class ExampleFilter implements Filter {
 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {
 
        if (!(req instanceof HttpServletRequest)) {
            chain.doFilter(req, res);
            return;
        }
 
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
 
        HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) {
            @Override
            public String getLocalAddr() {
                try {
                    return request.getLocalAddr();
                } catch(NullPointerException npe) {
                    // When NPE happnes, just return request.getLocalName() instread
                    return request.getLocalName();
                    // If you want to resolve address, you can use the followin code. But this can impact performance.
                    // If a DNS server is unresponsive this could potentially add seconds to the request processing time.
                    // try {
                    //     return InetAddress.getByName(request.getLocalName()).getHostAddress();
                    // } catch(Exception e){
                    //     // Can not be resolved. Just return request.getLocalName() instread
                    //     return request.getLocalName();
                    // }
                }
            }
        };
 
        chain.doFilter(wrappedRequest, res);
    }
 
    ...
}
Components
Category

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.