Skip to content

Commit

Permalink
Thread-safe removal of destruction callbacks in web scopes
Browse files Browse the repository at this point in the history
Closes gh-23117
  • Loading branch information
jhoeller committed Jun 12, 2019
1 parent 160cde2 commit d032bed
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -54,22 +54,26 @@ public void contextDestroyed(ServletContextEvent event) {


/**
* Find all ServletContext attributes which implement {@link DisposableBean}
* and destroy them, removing all affected ServletContext attributes eventually.
* @param sc the ServletContext to check
* Find all Spring-internal ServletContext attributes which implement
* {@link DisposableBean} and invoke the destroy method on them.
* @param servletContext the ServletContext to check
* @see DisposableBean#destroy()
*/
static void cleanupAttributes(ServletContext sc) {
Enumeration<String> attrNames = sc.getAttributeNames();
static void cleanupAttributes(ServletContext servletContext) {
Enumeration<String> attrNames = servletContext.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = attrNames.nextElement();
if (attrName.startsWith("org.springframework.")) {
Object attrValue = sc.getAttribute(attrName);
Object attrValue = servletContext.getAttribute(attrName);
if (attrValue instanceof DisposableBean) {
try {
((DisposableBean) attrValue).destroy();
}
catch (Throwable ex) {
logger.error("Couldn't invoke destroy method of attribute with name '" + attrName + "'", ex);
if (logger.isWarnEnabled()) {
logger.warn("Invocation of destroy method failed on ServletContext " +
"attribute with name '" + attrName + "'", ex);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -188,18 +188,17 @@ public void setAttribute(String name, Object value, int scope) {
public void removeAttribute(String name, int scope) {
if (scope == SCOPE_REQUEST) {
if (isRequestActive()) {
this.request.removeAttribute(name);
removeRequestDestructionCallback(name);
this.request.removeAttribute(name);
}
}
else {
HttpSession session = getSession(false);
if (session != null) {
this.sessionAttributesToUpdate.remove(name);
try {
session.removeAttribute(name);
// Remove any registered destruction callback as well.
session.removeAttribute(DESTRUCTION_CALLBACK_NAME_PREFIX + name);
session.removeAttribute(name);
}
catch (IllegalStateException ex) {
// Session invalidated - shouldn't usually happen.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -78,8 +78,10 @@ public Object get(String name, ObjectFactory<?> objectFactory) {
public Object remove(String name) {
Object scopedObject = this.servletContext.getAttribute(name);
if (scopedObject != null) {
synchronized (this.destructionCallbacks) {
this.destructionCallbacks.remove(name);
}
this.servletContext.removeAttribute(name);
this.destructionCallbacks.remove(name);
return scopedObject;
}
else {
Expand All @@ -89,7 +91,9 @@ public Object remove(String name) {

@Override
public void registerDestructionCallback(String name, Runnable callback) {
this.destructionCallbacks.put(name, callback);
synchronized (this.destructionCallbacks) {
this.destructionCallbacks.put(name, callback);
}
}

@Override
Expand All @@ -112,10 +116,12 @@ public String getConversationId() {
*/
@Override
public void destroy() {
for (Runnable runnable : this.destructionCallbacks.values()) {
runnable.run();
synchronized (this.destructionCallbacks) {
for (Runnable runnable : this.destructionCallbacks.values()) {
runnable.run();
}
this.destructionCallbacks.clear();
}
this.destructionCallbacks.clear();
}

}

0 comments on commit d032bed

Please sign in to comment.