Skip to content

Commit a53182f

Browse files
authored
cleanup servlet request attribute (#3527)
1 parent 9d21f36 commit a53182f

File tree

6 files changed

+40
-12
lines changed

6 files changed

+40
-12
lines changed

CHANGELOG.asciidoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ Use subheadings with the "=====" level for adding notes for unreleased changes:
3131
3232
=== Unreleased
3333
34+
[float]
35+
===== Bug fixes
36+
* Cleanup extra servlet request attribute used for Spring exception handler - {pull}3527[#3527]
37+
3438
[[release-notes-1.x]]
3539
=== Java Agent version 1.x
3640

apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/ServletApiAdvice.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,15 @@ public abstract class ServletApiAdvice {
5555
private static final DetachedThreadLocal<Object> servletPathTL = GlobalVariables.get(ServletApiAdvice.class, "servletPath", WeakConcurrent.buildThreadLocal());
5656
private static final DetachedThreadLocal<Object> pathInfoTL = GlobalVariables.get(ServletApiAdvice.class, "pathInfo", WeakConcurrent.buildThreadLocal());
5757

58-
private static final List<String> requestExceptionAttributes = Arrays.asList("javax.servlet.error.exception", "jakarta.servlet.error.exception", "exception", "org.springframework.web.servlet.DispatcherServlet.EXCEPTION", "co.elastic.apm.exception");
58+
private static final String ELASTIC_EXCEPTION = "co.elastic.apm.exception";
59+
private static final String JAVAX_ERROR_EXCEPTION = "javax.servlet.error.exception";
60+
private static final String JAKARTA_ERROR_EXCEPTION = "jakarta.servlet.error.exception";
61+
private static final List<String> requestExceptionAttributes = Arrays.asList(
62+
JAVAX_ERROR_EXCEPTION,
63+
JAKARTA_ERROR_EXCEPTION,
64+
"exception",
65+
"org.springframework.web.servlet.DispatcherServlet.EXCEPTION",
66+
ELASTIC_EXCEPTION);
5967

6068
@Nullable
6169
public static <HttpServletRequest, HttpServletResponse, ServletContext, ServletContextEvent, FilterConfig, ServletConfig> Object onServletEnter(
@@ -202,7 +210,7 @@ public static <HttpServletRequest, HttpServletResponse, ServletContext, ServletC
202210
httpServletRequest != null &&
203211
httpServletResponse != null) {
204212

205-
if (adapter.getHttpAttribute(httpServletRequest, ServletTransactionHelper.ASYNC_ATTRIBUTE) != null) {
213+
if (adapter.getAttribute(httpServletRequest, ServletTransactionHelper.ASYNC_ATTRIBUTE) != null) {
206214
// HttpServletRequest.startAsync was invoked on this httpServletRequest.
207215
// The transaction should be handled from now on by the other thread committing the response
208216
transaction.deactivate();
@@ -230,10 +238,16 @@ public static <HttpServletRequest, HttpServletResponse, ServletContext, ServletC
230238
final int size = requestExceptionAttributes.size();
231239
for (int i = 0; i < size; i++) {
232240
String attributeName = requestExceptionAttributes.get(i);
233-
Object throwable = adapter.getHttpAttribute(httpServletRequest, attributeName);
241+
Object throwable = adapter.getAttribute(httpServletRequest, attributeName);
234242
if (throwable instanceof Throwable) {
235243
t2 = (Throwable) throwable;
236-
if (!attributeName.equals("javax.servlet.error.exception") && !attributeName.equals("jakarta.servlet.error.exception")) {
244+
245+
// elastic exception can be removed as it's not needed after transaction end
246+
if (attributeName.equals(ELASTIC_EXCEPTION)) {
247+
adapter.removeAttribute(httpServletRequest, attributeName);
248+
}
249+
250+
if (!attributeName.equals(JAVAX_ERROR_EXCEPTION) && !attributeName.equals(JAKARTA_ERROR_EXCEPTION)) {
237251
overrideStatusCodeOnThrowable = false;
238252
}
239253
break;

apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/adapter/JakartaServletApiAdapter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,9 @@ public void setAttribute(HttpServletRequest servletRequest, String attributeName
242242
servletRequest.setAttribute(attributeName, value);
243243
}
244244

245-
@Nullable
246245
@Override
247-
public Object getHttpAttribute(HttpServletRequest httpServletRequest, String attributeName) {
248-
return httpServletRequest.getAttribute(attributeName);
246+
public void removeAttribute(HttpServletRequest httpServletRequest, String attributeName) {
247+
httpServletRequest.removeAttribute(attributeName);
249248
}
250249

251250
@Override

apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/adapter/JavaxServletApiAdapter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,9 @@ public void setAttribute(HttpServletRequest servletRequest, String attributeName
256256
servletRequest.setAttribute(attributeName, value);
257257
}
258258

259-
@Nullable
260259
@Override
261-
public Object getHttpAttribute(HttpServletRequest httpServletRequest, String attributeName) {
262-
return httpServletRequest.getAttribute(attributeName);
260+
public void removeAttribute(HttpServletRequest servletRequest, String attributeName) {
261+
servletRequest.removeAttribute(attributeName);
263262
}
264263

265264
@Override

apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/adapter/ServletRequestAdapter.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ public interface ServletRequestAdapter<HttpServletRequest, ServletContext> {
9090

9191
void setAttribute(HttpServletRequest request, String attributeName, Object value);
9292

93-
@Nullable
94-
Object getHttpAttribute(HttpServletRequest request, String attributeName);
93+
void removeAttribute(HttpServletRequest request, String attributeName);
9594

9695
Map<String, String[]> getParameterMap(HttpServletRequest httpServletRequest);
9796

apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/src/test/java/co/elastic/apm/agent/springwebmvc/exception/AbstractExceptionHandlerInstrumentationWithExceptionResolverTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import org.springframework.test.web.servlet.MvcResult;
2727
import org.springframework.test.web.servlet.ResultActions;
2828

29+
import java.util.Enumeration;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
2932
import static org.junit.Assert.assertEquals;
3033
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
3134

@@ -45,6 +48,16 @@ public void testCallApiWithExceptionThrown() throws Exception {
4548
MvcResult result = resultActions.andReturn();
4649
MockHttpServletResponse response = result.getResponse();
4750

51+
52+
Enumeration<String> attributeNames = result.getRequest().getAttributeNames();
53+
while (attributeNames.hasMoreElements()) {
54+
String attributeName = attributeNames.nextElement();
55+
assertThat(attributeName)
56+
.describedAs("elastic attributes should be removed after usage")
57+
.doesNotStartWith("co.elastic.");
58+
}
59+
60+
4861
assertExceptionCapture(ExceptionResolverRuntimeException.class, response, 200, "", "runtime exception occurred", "View#render error-page");
4962
assertEquals("error-page", response.getForwardedUrl());
5063
assertEquals("runtime exception occurred", result.getModelAndView().getModel().get("message"));

0 commit comments

Comments
 (0)