You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2021/04/30 14:37:10 UTC
[tomee] 02/03: TOMEE-3213 TOMEE-3214 TOMEE-3215 Refine our wrapping
mechanism for CDI such as it does not break TCK
This is an automated email from the ASF dual-hosted git repository.
jlmonteiro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 057ed7adade08d8c2132ab1c8bc6fa367c93e946
Author: Jean-Louis Monteiro <jl...@tomitribe.com>
AuthorDate: Fri Apr 30 14:07:30 2021 +0200
TOMEE-3213 TOMEE-3214 TOMEE-3215 Refine our wrapping mechanism for CDI such as it does not break TCK
---
.../org/apache/openejb/server/httpd/EEFilter.java | 63 ++++++++++++++++------
.../openejb/server/httpd/HttpRequestImpl.java | 2 +-
2 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java
index 38ed02f..26f3507 100644
--- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java
+++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/EEFilter.java
@@ -36,6 +36,7 @@ import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
@@ -59,13 +60,13 @@ public class EEFilter implements Filter {
final boolean shouldWrap = active && HttpServletRequest.class.isInstance(servletRequest);
if (!HttpServletRequest.class.isInstance(servletRequest)) {
filterChain.doFilter(shouldWrap ?
- new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), this) : servletRequest, servletResponse);
+ new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, this) : servletRequest, servletResponse);
return;
}
WebBeansContext ctx;
filterChain.doFilter(servletRequest.isAsyncSupported() && (ctx = WebBeansContext.currentInstance()) != null ?
- new CdiRequest(HttpServletRequest.class.cast(servletRequest), ctx, this) :
- (shouldWrap ? new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), this) : servletRequest),
+ new CdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, ctx, this) :
+ (shouldWrap ? new NoCdiRequest(HttpServletRequest.class.cast(servletRequest), servletResponse, this) : servletRequest),
servletResponse);
}
@@ -79,10 +80,12 @@ public class EEFilter implements Filter {
}
public static class NoCdiRequest extends HttpServletRequestWrapper {
+ private final ServletResponse response;
private final EEFilter filter;
- public NoCdiRequest(final HttpServletRequest cast, final EEFilter filter) {
+ public NoCdiRequest(final HttpServletRequest cast, final ServletResponse response, final EEFilter filter) {
super(cast);
+ this.response = response;
this.filter = filter;
}
@@ -104,8 +107,15 @@ public class EEFilter implements Filter {
@Override
public boolean equals(final Object obj) {
// unwrap and delegate
+ if (obj instanceof NoCdiRequest /* and CDI Request */) {
+ return getRequest().equals(((NoCdiRequest) obj).getRequest());
+ }
return getRequest().equals(obj);
}
+
+ protected ServletResponse getResponse() {
+ return response;
+ }
}
public static class CdiRequest extends NoCdiRequest {
@@ -114,22 +124,22 @@ public class EEFilter implements Filter {
// it's a request so not multi-threaded
private final AtomicReference<AsynContextWrapper> asyncContextWrapperReference = new AtomicReference<>();
- public CdiRequest(final HttpServletRequest cast, final WebBeansContext webBeansContext, final EEFilter filter) {
- super(cast, filter);
+ public CdiRequest(final HttpServletRequest cast, final ServletResponse response, final WebBeansContext webBeansContext, final EEFilter filter) {
+ super(cast, response, filter);
this.webBeansContext = webBeansContext;
}
@Override
public AsyncContext startAsync() throws IllegalStateException {
asyncContextWrapperReference.compareAndSet(null,
- new AsynContextWrapper(super.startAsync(), this, webBeansContext));
+ new AsynContextWrapper(super.startAsync(), this, getResponse(), webBeansContext));
return asyncContextWrapperReference.get();
}
@Override
public AsyncContext startAsync(final ServletRequest servletRequest, final ServletResponse servletResponse) throws IllegalStateException {
asyncContextWrapperReference.compareAndSet(null,
- new AsynContextWrapper(super.startAsync(servletRequest, servletResponse), servletRequest, webBeansContext));
+ new AsynContextWrapper(super.startAsync(servletRequest, servletResponse), servletRequest, servletResponse, webBeansContext));
return asyncContextWrapperReference.get();
}
@@ -143,14 +153,17 @@ public class EEFilter implements Filter {
public static class AsynContextWrapper implements AsyncContext {
private final AsyncContext delegate;
private final CdiAppContextsService service;
- private final ServletRequest request;
+ private final ServletResponse response;
+ private volatile ServletRequest request;
private volatile ServletRequestEvent event;
- public AsynContextWrapper(final AsyncContext asyncContext, final ServletRequest request, final WebBeansContext webBeansContext) {
+ public AsynContextWrapper(final AsyncContext asyncContext, final ServletRequest request,
+ final ServletResponse response, final WebBeansContext webBeansContext) {
this.delegate = asyncContext;
this.service = CdiAppContextsService.class.cast(webBeansContext.getService(ContextsService.class));
this.event = null;
this.request = request;
+ this.response = response;
}
private boolean startRequestScope() {
@@ -179,7 +192,10 @@ public class EEFilter implements Filter {
@Override
public ServletRequest getRequest() {
- return request;
+ if (request != null) {
+ return request;
+ }
+ return delegate.getRequest();
}
@Override
@@ -195,7 +211,12 @@ public class EEFilter implements Filter {
// Unfortunately we pass in the wrapped request so the flag is false
// we need to override the value returned by Tomcat in case we are wrapping the request
if (request instanceof NoCdiRequest) { // and CdiRequest
- return request == delegate.getRequest(); // Tomcat should have this as the request and not the RequestFacade
+ final NoCdiRequest noCdiRequest = (NoCdiRequest) this.request;
+ // Tomcat should have this as the request and not the RequestFacade because of the wrapping
+ // compare with the response we captured during wrapping
+ // they might have been wrapped bu the user during the start
+ return noCdiRequest == delegate.getRequest()
+ && noCdiRequest.getResponse() == delegate.getResponse();
}
}
return tomcatHasOriginalRequestAndResponse;
@@ -203,17 +224,29 @@ public class EEFilter implements Filter {
@Override
public void dispatch() {
- delegate.dispatch();
+ try {
+ delegate.dispatch();
+ } finally {
+ request = null;
+ }
}
@Override
public void dispatch(final String s) {
- delegate.dispatch(s);
+ try {
+ delegate.dispatch(s);
+ } finally {
+ request = null;
+ }
}
@Override
public void dispatch(final ServletContext servletContext, final String s) {
- delegate.dispatch(servletContext, s);
+ try {
+ delegate.dispatch(servletContext, s);
+ } finally {
+ request = null;
+ }
}
@Override
diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java
index 79b5654..0ba3e7c 100644
--- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java
+++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java
@@ -1040,7 +1040,7 @@ public class HttpRequestImpl implements HttpRequest {
final WebBeansContext webBeansContext = AppFinder.findAppContextOrWeb(
Thread.currentThread().getContextClassLoader(), AppFinder.WebBeansContextTransformer.INSTANCE);
return webBeansContext != null ?
- new EEFilter.AsynContextWrapper(asyncContext, servletRequest, webBeansContext) : asyncContext;
+ new EEFilter.AsynContextWrapper(asyncContext, servletRequest, servletResponse, webBeansContext) : asyncContext;
}
public void addInternalParameter(final String key, final String val) {