Skip to content

Commit 65fe83c

Browse files
authored
feat: Support Servlet API 3.1+ (#228)
* refact: Factory for mock implementations of Servlet API objects * feat: Produce HttpServletResponse only in request scope * chore: Minimize implementation of the LifecycleAwareRequest by relying on HttpServletRequestWrapper * feat: Extract module for Servlet API 3.0 support * refact: Replace usages of Weld exceptions * refact: Remove NestedApplicationException and usages * feat: Implements mocks for Servlet API 3.1 * ci: Define CI matrix for Servlet API tests * build: Add cdi-unit-servlet30 when performing a release * build: Add cdi-unit-servlet30 to published JavaDoc
1 parent 3144057 commit 65fe83c

37 files changed

+696
-490
lines changed

.github/workflows/build-test-temurin.yml

+41
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,44 @@ jobs:
132132

133133
- name: Test DeltaSpike
134134
run: ./ci-support/test-deltaspike.sh deltaspike-v1.x.sh
135+
136+
test-servlet-api:
137+
needs: build
138+
runs-on: ubuntu-latest
139+
140+
strategy:
141+
matrix:
142+
java: [8, 11]
143+
144+
steps:
145+
- uses: actions/checkout@v4
146+
147+
- name: Set up JDK ${{ matrix.java }}
148+
uses: actions/setup-java@v4
149+
with:
150+
java-version: ${{ matrix.java }}
151+
distribution: 'temurin'
152+
cache: 'maven'
153+
154+
- name: Restore build artifacts
155+
uses: actions/cache@v2
156+
env:
157+
cache-name: build-maven-repository
158+
with:
159+
path: ~/.m2/repository
160+
key: ${{ env.cache-name }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
161+
restore-keys: |
162+
${{ env.cache-name }}-${{ github.sha }}-${{ github.run_id }}-
163+
${{ env.cache-name }}-${{ github.sha }}-
164+
165+
- uses: s4u/[email protected]
166+
with:
167+
mirrors: '[{
168+
"id": "google-maven-central",
169+
"name": "GCS Maven Central mirror EU",
170+
"mirrorOf": "central",
171+
"url": "https://maven-central-eu.storage-download.googleapis.com/maven2/"
172+
}]'
173+
174+
- name: Test Servlet API
175+
run: ./ci-support/test-servlet-api.sh servlet-api.sh

.github/workflows/build-test-zulujdk.yml

+41
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,44 @@ jobs:
132132

133133
- name: Test DeltaSpike
134134
run: ./ci-support/test-deltaspike.sh deltaspike-v1.x.sh
135+
136+
test-servlet-api:
137+
needs: build
138+
runs-on: ubuntu-latest
139+
140+
strategy:
141+
matrix:
142+
java: [8, 11]
143+
144+
steps:
145+
- uses: actions/checkout@v4
146+
147+
- name: Set up JDK ${{ matrix.java }}
148+
uses: actions/setup-java@v4
149+
with:
150+
java-version: ${{ matrix.java }}
151+
distribution: 'zulu'
152+
cache: 'maven'
153+
154+
- name: Restore build artifacts
155+
uses: actions/cache@v2
156+
env:
157+
cache-name: build-maven-repository
158+
with:
159+
path: ~/.m2/repository
160+
key: ${{ env.cache-name }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
161+
restore-keys: |
162+
${{ env.cache-name }}-${{ github.sha }}-${{ github.run_id }}-
163+
${{ env.cache-name }}-${{ github.sha }}-
164+
165+
- uses: s4u/[email protected]
166+
with:
167+
mirrors: '[{
168+
"id": "google-maven-central",
169+
"name": "GCS Maven Central mirror EU",
170+
"mirrorOf": "central",
171+
"url": "https://maven-central-eu.storage-download.googleapis.com/maven2/"
172+
}]'
173+
174+
- name: Test Servlet API
175+
run: ./ci-support/test-servlet-api.sh servlet-api.sh

cdi-unit-servlet30/pom.xml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>io.github.cdi-unit</groupId>
8+
<artifactId>cdi-unit-parent</artifactId>
9+
<version>4.4.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>cdi-unit-servlet30</artifactId>
13+
14+
<name>CDI-Unit-Servlet-3.0</name>
15+
<description>CDI-Unit support for Servlet API 3.0</description>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>javax.servlet</groupId>
20+
<artifactId>javax.servlet-api</artifactId>
21+
<version>3.0.1</version>
22+
<scope>provided</scope>
23+
<optional>true</optional>
24+
</dependency>
25+
<dependency>
26+
<groupId>javax.enterprise</groupId>
27+
<artifactId>cdi-api</artifactId>
28+
<version>2.0.SP1</version>
29+
<scope>provided</scope>
30+
</dependency>
31+
</dependencies>
32+
33+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.github.cdiunit.internal.servlet;
2+
3+
public final class ExceptionUtils {
4+
5+
private ExceptionUtils() {
6+
}
7+
8+
@SuppressWarnings("unchecked")
9+
public static <T extends RuntimeException> T asRuntimeException(final Throwable t) throws T {
10+
return (T) t;
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.github.cdiunit.internal.servlet;
2+
3+
import javax.servlet.http.HttpSession;
4+
5+
public interface HttpSessionAware {
6+
7+
/**
8+
* Use HTTP session.
9+
*
10+
* @param session session to use
11+
*/
12+
void setSession(HttpSession session);
13+
14+
}

cdi-unit/src/main/java/io/github/cdiunit/internal/servlet/MockHttpServletResponseImpl.java cdi-unit-servlet30/src/main/java/io/github/cdiunit/internal/servlet/MockHttpServletResponseImpl.java

+29-33
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,24 @@
1515
*/
1616
package io.github.cdiunit.internal.servlet;
1717

18-
import java.io.IOException;
19-
import java.io.OutputStreamWriter;
20-
import java.io.PrintWriter;
21-
import java.io.UnsupportedEncodingException;
22-
import java.text.SimpleDateFormat;
23-
import java.util.ArrayList;
24-
import java.util.Collection;
25-
import java.util.Date;
26-
import java.util.List;
27-
import java.util.Locale;
28-
import java.util.Map;
29-
import java.util.TimeZone;
30-
import java.util.TreeMap;
31-
3218
import javax.servlet.ServletOutputStream;
3319
import javax.servlet.http.Cookie;
3420
import javax.servlet.http.HttpServletResponse;
3521

22+
import java.io.*;
23+
import java.text.SimpleDateFormat;
24+
import java.util.*;
25+
import java.util.function.Supplier;
26+
3627
/**
3728
* Shamlessly ripped from mockrunner. If mockrunner supports servlet 3.1 https://github.com/mockrunner/mockrunner/issues/4 then this class can extend mockrunner instead.
3829
*
3930
* @author Various
4031
*/
41-
@CdiUnitServlet
4232
public class MockHttpServletResponseImpl implements HttpServletResponse {
33+
private final Supplier<ServletOutputStream> outputStreamSupplier;
4334
private PrintWriter writer;
44-
private MockServletOutputStream outputStream;
35+
private ServletOutputStream outputStream;
4536
private Map headers;
4637
private Locale locale;
4738
private String characterEncoding;
@@ -53,7 +44,8 @@ public class MockHttpServletResponseImpl implements HttpServletResponse {
5344
private List cookies;
5445
private long contentLength;
5546

56-
public MockHttpServletResponseImpl() {
47+
public MockHttpServletResponseImpl(Supplier<ServletOutputStream> outputStreamSupplier) {
48+
this.outputStreamSupplier = outputStreamSupplier;
5749
resetAll();
5850
}
5951

@@ -69,13 +61,7 @@ public void resetAll() {
6961
errorCode = SC_OK;
7062
statusCode = SC_OK;
7163
cookies = new ArrayList();
72-
outputStream = new MockServletOutputStream(characterEncoding);
73-
try {
74-
writer = new PrintWriter(new OutputStreamWriter(outputStream,
75-
characterEncoding), true);
76-
} catch (UnsupportedEncodingException exc) {
77-
throw new NestedApplicationException(exc);
78-
}
64+
resetBuffer();
7965
}
8066

8167
public String encodeURL(String url) {
@@ -102,10 +88,6 @@ public ServletOutputStream getOutputStream() throws IOException {
10288
return outputStream;
10389
}
10490

105-
public String getOutputStreamContent() {
106-
return outputStream.getContent();
107-
}
108-
10991
public void addCookie(Cookie cookie) {
11092
cookies.add(cookie);
11193
}
@@ -158,7 +140,7 @@ public void setHeader(String key, String value) {
158140
}
159141

160142
public void setIntHeader(String key, int value) {
161-
String stringValue = new Integer(value).toString();
143+
String stringValue = Integer.toString(value);
162144
setHeader(key, stringValue);
163145
}
164146

@@ -185,12 +167,11 @@ public String getCharacterEncoding() {
185167

186168
public void setCharacterEncoding(String encoding) {
187169
characterEncoding = encoding;
188-
outputStream.setEncoding(encoding);
189170
try {
190171
writer = new PrintWriter(new OutputStreamWriter(outputStream,
191172
characterEncoding), true);
192173
} catch (UnsupportedEncodingException exc) {
193-
throw new NestedApplicationException(exc);
174+
throw ExceptionUtils.asRuntimeException(exc);
194175
}
195176
}
196177

@@ -214,7 +195,13 @@ public void reset() {
214195
}
215196

216197
public void resetBuffer() {
217-
outputStream.clearContent();
198+
outputStream = outputStreamSupplier.get();
199+
try {
200+
writer = new PrintWriter(new OutputStreamWriter(outputStream,
201+
characterEncoding), true);
202+
} catch (UnsupportedEncodingException exc) {
203+
throw ExceptionUtils.asRuntimeException(exc);
204+
}
218205
}
219206

220207
public void clearHeaders() {
@@ -292,7 +279,16 @@ private String getDateString(long date) {
292279
return dateFormat.format(dateValue);
293280
}
294281

295-
282+
/**
283+
* Sets the length of the content body in the response
284+
* In HTTP servlets, this method sets the HTTP Content-Length header.
285+
*
286+
* @param len a long specifying the length of the
287+
* content being returned to the client; sets the Content-Length header
288+
*
289+
* @since Servlet 3.1
290+
*/
291+
// @Override is implied
296292
public void setContentLengthLong(long len) {
297293
contentLength = len;
298294
}

cdi-unit/src/main/java/io/github/cdiunit/internal/servlet/MockHttpSessionImpl.java cdi-unit-servlet30/src/main/java/io/github/cdiunit/internal/servlet/MockHttpSessionImpl.java

+5-17
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,10 @@
1515
*/
1616
package io.github.cdiunit.internal.servlet;
1717

18-
import java.util.ArrayList;
19-
import java.util.Enumeration;
20-
import java.util.HashMap;
21-
import java.util.Iterator;
22-
import java.util.List;
23-
import java.util.Map;
24-
import java.util.Vector;
25-
26-
import javax.inject.Inject;
2718
import javax.servlet.ServletContext;
28-
import javax.servlet.http.HttpSession;
29-
import javax.servlet.http.HttpSessionAttributeListener;
30-
import javax.servlet.http.HttpSessionBindingEvent;
31-
import javax.servlet.http.HttpSessionBindingListener;
32-
import javax.servlet.http.HttpSessionContext;
19+
import javax.servlet.http.*;
20+
21+
import java.util.*;
3322

3423
/**
3524
* Shamlessly ripped from mockrunner. If mockrunner supports servlet 3.1 https://github.com/mockrunner/mockrunner/issues/4 then this class can extend mockrunner instead.
@@ -44,13 +33,12 @@ public class MockHttpSessionImpl implements HttpSession {
4433
private boolean isValid;
4534
private long creationTime;
4635

47-
@Inject
48-
@CdiUnitServlet
4936
private ServletContext servletContext;
5037
private int maxInactiveInterval;
5138
private List attributeListener;
5239

53-
public MockHttpSessionImpl() {
40+
public MockHttpSessionImpl(ServletContext servletContext) {
41+
this.servletContext = servletContext;
5442
resetAll();
5543
}
5644

cdi-unit/src/main/java/io/github/cdiunit/internal/servlet/MockSessionContext.java cdi-unit-servlet30/src/main/java/io/github/cdiunit/internal/servlet/MockSessionContext.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@
1515
*/
1616
package io.github.cdiunit.internal.servlet;
1717

18-
import java.util.Enumeration;
19-
import java.util.Vector;
20-
2118
import javax.servlet.http.HttpSession;
2219
import javax.servlet.http.HttpSessionContext;
2320

21+
import java.util.Enumeration;
22+
import java.util.Vector;
23+
2424
/**
2525
* Mock implementation of <code>HttpSessionContext</code>.
2626
*/
27-
public class MockSessionContext implements HttpSessionContext
27+
class MockSessionContext implements HttpSessionContext
2828
{
2929
public Enumeration getIds()
3030
{

0 commit comments

Comments
 (0)