DELTASPIKE-414 Added a ServletRequestListener to bind the request to the current thread
Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/6f37b12f Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/6f37b12f Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/6f37b12f Branch: refs/heads/master Commit: 6f37b12f0e4dc52cd6e4a57ff249c48a0ed59c59 Parents: 360a694 Author: Christian Kaltepoth <[email protected]> Authored: Mon Mar 10 17:26:28 2014 +0100 Committer: Christian Kaltepoth <[email protected]> Committed: Mon Mar 10 17:26:28 2014 +0100 ---------------------------------------------------------------------- .../produce/RequestResponseHolderFilter.java | 30 +++++-- .../produce/RequestResponseHolderListener.java | 42 ++++++++++ .../main/resources/META-INF/web-fragment.xml | 5 ++ .../producer/EarlyRequestInjectionFilter.java | 69 ++++++++++++++++ .../producer/EarlyRequestInjectionTest.java | 87 ++++++++++++++++++++ 5 files changed, 228 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/6f37b12f/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderFilter.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderFilter.java b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderFilter.java index f63e67d..9f55cb0 100644 --- a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderFilter.java +++ b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderFilter.java @@ -44,16 +44,36 @@ public class RequestResponseHolderFilter implements Filter ServletException { - RequestResponseHolder.REQUEST.bind(request); - RequestResponseHolder.RESPONSE.bind(response); + /* + * Typically the request is bound to the thread in RequestResponseHolderListener. But as this listener was added + * after the initial release of the Servlet module, the filter will also do it if necessary. + */ + final boolean alreadyBound = RequestResponseHolder.REQUEST.isBound(); + if (!alreadyBound) + { + RequestResponseHolder.REQUEST.bind(request); + } + try { - chain.doFilter(request, response); + + RequestResponseHolder.RESPONSE.bind(response); + try + { + chain.doFilter(request, response); + } + finally + { + RequestResponseHolder.RESPONSE.release(); + } + } finally { - RequestResponseHolder.REQUEST.release(); - RequestResponseHolder.RESPONSE.release(); + if (!alreadyBound) + { + RequestResponseHolder.REQUEST.release(); + } } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/6f37b12f/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderListener.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderListener.java b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderListener.java new file mode 100644 index 0000000..a913436 --- /dev/null +++ b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/produce/RequestResponseHolderListener.java @@ -0,0 +1,42 @@ +/* + * 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.deltaspike.servlet.impl.produce; + +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; + +/** + * This class stores the ServletRequest in the {@link RequestResponseHolder}. + */ +public class RequestResponseHolderListener implements ServletRequestListener +{ + + @Override + public void requestInitialized(ServletRequestEvent sre) + { + RequestResponseHolder.REQUEST.bind(sre.getServletRequest()); + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) + { + RequestResponseHolder.REQUEST.release(); + } + +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/6f37b12f/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml ---------------------------------------------------------------------- diff --git a/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml b/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml index 4eff1d1..bffa282 100644 --- a/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml +++ b/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml @@ -45,6 +45,11 @@ <listener-class>org.apache.deltaspike.servlet.impl.produce.ServletContextHolderListener</listener-class> </listener> + <listener> + <display-name>RequestResponseHolderListener</display-name> + <listener-class>org.apache.deltaspike.servlet.impl.produce.RequestResponseHolderListener</listener-class> + </listener> + <filter> <display-name>RequestResponseHolderFilter</display-name> <filter-name>RequestResponseHolderFilter</filter-name> http://git-wip-us.apache.org/repos/asf/deltaspike/blob/6f37b12f/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionFilter.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionFilter.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionFilter.java new file mode 100644 index 0000000..f60eecd --- /dev/null +++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionFilter.java @@ -0,0 +1,69 @@ +/* + * 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.deltaspike.test.servlet.impl.producer; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.deltaspike.core.api.common.DeltaSpike; + +public class EarlyRequestInjectionFilter implements Filter +{ + + @Inject + @DeltaSpike + private HttpServletRequest injectedRequest; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, + ServletException + { + + // check if the request has been injected + if (injectedRequest != null && injectedRequest.getContextPath() != null) + { + ((HttpServletResponse) response).setHeader("X-DS-Request-Injected", "true"); + } + + chain.doFilter(request, response); + + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + // nothing to do + } + + @Override + public void destroy() + { + // nothing to do + } + +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/6f37b12f/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionTest.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionTest.java new file mode 100644 index 0000000..274a8e0 --- /dev/null +++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/producer/EarlyRequestInjectionTest.java @@ -0,0 +1,87 @@ +/* + * 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.deltaspike.test.servlet.impl.producer; + +import static org.junit.Assert.assertEquals; + +import java.net.URL; + +import org.apache.deltaspike.test.category.WebProfileCategory; +import org.apache.deltaspike.test.servlet.impl.util.ArchiveUtils; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.descriptor.api.Descriptors; +import org.jboss.shrinkwrap.descriptor.api.spec.servlet.web.WebAppDescriptor; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +/** + * Verifies that request injection into filters work as expected. + * + * @see https://issues.apache.org/jira/browse/DELTASPIKE-414 + */ +@RunWith(Arquillian.class) +@Category(WebProfileCategory.class) +public class EarlyRequestInjectionTest +{ + + @Deployment(testable = false) + public static WebArchive getDeployment() + { + return ShrinkWrap.create(WebArchive.class, EarlyRequestInjectionTest.class.getSimpleName() + ".war") + .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreAndServletModuleArchive()) + .addAsResource("META-INF/web-fragment.xml", "META-INF/web-fragment.xml") + .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml") + .addClass(EarlyRequestInjectionFilter.class) + .addAsWebResource(new StringAsset("foobar"), "foobar.txt") + .setWebXML(new StringAsset( + Descriptors.create(WebAppDescriptor.class) + .filter(EarlyRequestInjectionFilter.class, "/*") + .exportAsString())); + + } + + @ArquillianResource + private URL contextPath; + + @Test + public void shouldInjectRequestIntoFilters() throws Exception + { + + String url = new URL(contextPath, "foobar.txt").toString(); + HttpResponse response = new DefaultHttpClient().execute(new HttpGet(url)); + + assertEquals(200, response.getStatusLine().getStatusCode()); + + Header[] verificationHeader = response.getHeaders("X-DS-Request-Injected"); + assertEquals(1, verificationHeader.length); + assertEquals("true", verificationHeader[0].getValue()); + + } + +}
