From 7bce8ef6a84a2ddf5d79f89337e08bec223c3730 Mon Sep 17 00:00:00 2001 From: zhouyanming Date: Thu, 13 Nov 2014 16:06:00 +0800 Subject: [PATCH 1/2] Defend for NPE when performing async request when I combined spring async mvc with struts2 sitemesh plugin, It will throw NPE java.lang.NullPointerException at org.apache.struts2.ServletActionContext.getRequest(ServletActionContext.java:112) at org.apache.struts2.sitemesh.StrutsSiteMeshFactory.isInsideActionTag(StrutsSiteMeshFactory.java:25) at org.apache.struts2.sitemesh.StrutsSiteMeshFactory.shouldParsePage(StrutsSiteMeshFactory.java:21) at com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor.handles(PageParser2ContentProcessor.java:45) at com.opensymphony.sitemesh.webapp.ContentBufferingResponse$1.shouldParsePage(ContentBufferingResponse.java:29) at com.opensymphony.module.sitemesh.filter.PageResponseWrapper.setContentType(PageResponseWrapper.java:63) at com.opensymphony.sitemesh.webapp.ContentBufferingResponse$2.setContentType(ContentBufferingResponse.java:39) at com.opensymphony.module.sitemesh.filter.PageResponseWrapper.addHeader(PageResponseWrapper.java:135) at javax.servlet.http.HttpServletResponseWrapper.addHeader(HttpServletResponseWrapper.java:173) at org.springframework.http.server.ServletServerHttpResponse.writeHeaders(ServletServerHttpResponse.java:103) at org.springframework.http.server.ServletServerHttpResponse.getBody(ServletServerHttpResponse.java:83) at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:217) at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:199) at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:128) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748) at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:659) at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:625) at org.apache.catalina.core.AsyncContextImpl$1.run(AsyncContextImpl.java:239) at org.apache.catalina.core.AsyncContextImpl.doInternalDispatch(AsyncContextImpl.java:382) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:215) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:299) at org.apache.coyote.http11.AbstractHttp11Processor.asyncDispatch(AbstractHttp11Processor.java:1652) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) --- .../org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java index 458cbf7d4..29eb052f6 100644 --- a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java +++ b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java @@ -2,6 +2,7 @@ package org.apache.struts2.sitemesh; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.factory.DefaultFactory; +import com.opensymphony.xwork2.ActionContext; import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsStatics; @@ -22,6 +23,8 @@ public class StrutsSiteMeshFactory extends DefaultFactory { } private boolean isInsideActionTag() { + if(ActionContext.getContext() == null) + return false; Object attribute = ServletActionContext.getRequest().getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION); return (Boolean) ObjectUtils.defaultIfNull(attribute, Boolean.FALSE); } From 2b150d87759d08cde08aa90ab78d28946836c7f8 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 23 Dec 2014 21:48:43 +0100 Subject: [PATCH 2/2] Adds logging and proper header with licence --- .../sitemesh/StrutsSiteMeshFactory.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java index 29eb052f6..96405fb37 100644 --- a/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java +++ b/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/StrutsSiteMeshFactory.java @@ -1,15 +1,36 @@ +/* + * 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.struts2.sitemesh; import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.factory.DefaultFactory; import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsStatics; - public class StrutsSiteMeshFactory extends DefaultFactory { + private static final Logger LOG = LoggerFactory.getLogger(StrutsSiteMeshFactory.class); + public StrutsSiteMeshFactory(Config config) { super(config); } @@ -23,9 +44,14 @@ public class StrutsSiteMeshFactory extends DefaultFactory { } private boolean isInsideActionTag() { - if(ActionContext.getContext() == null) - return false; + if(ActionContext.getContext() == null) { + if (LOG.isTraceEnabled()) { + LOG.trace("ActionContext is null! Not a user request?"); + } + return false; + } Object attribute = ServletActionContext.getRequest().getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION); return (Boolean) ObjectUtils.defaultIfNull(attribute, Boolean.FALSE); } + }