Skip to content

Commit abd1a43

Browse files
committed
Call CompletionCallback just once with DefaultExceptionMapper
Do not propagate error to the client Signed-off-by: jansupol <[email protected]>
1 parent 54a2854 commit abd1a43

File tree

3 files changed

+90
-14
lines changed

3 files changed

+90
-14
lines changed

core-server/src/main/java/org/glassfish/jersey/server/DefaultExceptionMapper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
1919
import jakarta.ws.rs.WebApplicationException;
2020
import jakarta.ws.rs.core.Response;
2121
import jakarta.ws.rs.ext.ExceptionMapper;
22+
import org.glassfish.jersey.server.internal.LocalizationMessages;
2223

2324
class DefaultExceptionMapper implements ExceptionMapper<Throwable> {
2425
@Override
@@ -35,6 +36,8 @@ private static Response processWebApplicationException(WebApplicationException e
3536
}
3637

3738
private static Response processDefaultException(Throwable exception) {
38-
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()).build();
39+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
40+
.entity(LocalizationMessages.ERROR_EXCEPTION_MAPPING_THROWN_TO_CONTAINER())
41+
.build();
3942
}
4043
}

core-server/src/main/java/org/glassfish/jersey/server/ServerRuntime.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@ public Responder(final RequestProcessingContext processingContext, final ServerR
365365

366366
public void process(ContainerResponse response) {
367367
processingContext.monitoringEventBuilder().setContainerResponse(response);
368-
response = processResponse(response);
368+
response = processResponse(response, null);
369369
release(response);
370370
}
371371

372-
private ContainerResponse processResponse(ContainerResponse response) {
372+
private ContainerResponse processResponse(ContainerResponse response, Throwable unmappedThrowable) {
373373
final Stage<ContainerResponse> respondingRoot = processingContext.createRespondingRoot();
374374

375375
if (respondingRoot != null) {
@@ -379,7 +379,7 @@ private ContainerResponse processResponse(ContainerResponse response) {
379379

380380
// no-exception zone
381381
// the methods below are guaranteed to not throw any exceptions
382-
completionCallbackRunner.onComplete(null);
382+
completionCallbackRunner.onComplete(unmappedThrowable);
383383
return response;
384384
}
385385

@@ -427,7 +427,7 @@ public void process(final Throwable throwable) {
427427
final Response exceptionResponse = mapException(throwable);
428428
try {
429429
response = preProcessResponse(exceptionResponse, request);
430-
processResponse(response);
430+
processResponse(response, null);
431431
} catch (final Throwable respError) {
432432
LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_PROCESSING_RESPONSE_FROM_ALREADY_MAPPED_EXCEPTION());
433433
processingContext.monitoringEventBuilder()
@@ -448,9 +448,10 @@ public void process(final Throwable throwable) {
448448
try {
449449
request.getResponseWriter().failure(responseError);
450450
} finally {
451-
completionCallbackRunner.onComplete(responseError);
452-
453451
defaultMapperResponse = processResponseWithDefaultExceptionMapper(responseError, request);
452+
453+
// completionCallbackRunner.onComplete(responseError); is called from
454+
// processResponseWithDefaultExceptionMapper
454455
}
455456

456457
}
@@ -488,7 +489,7 @@ private boolean processResponseError(final Throwable responseError) {
488489

489490
if (processedError != null) {
490491
processedResponse =
491-
processResponse(new ContainerResponse(processingContext.request(), processedError));
492+
processResponse(new ContainerResponse(processingContext.request(), processedError), null);
492493
processed = true;
493494
}
494495
} catch (final Throwable throwable) {
@@ -545,10 +546,7 @@ private Response mapException(final Throwable originalThrowable) throws Throwabl
545546

546547
final long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
547548
final ExceptionMapper mapper = runtime.exceptionMappers.findMapping(throwable);
548-
if (mapper != null
549-
&& !DefaultExceptionMapper.class.getName()
550-
.equals(mapper.getClass().getName())
551-
) {
549+
if (mapper != null && !DefaultExceptionMapper.class.isInstance(mapper)) {
552550
return processExceptionWithMapper(mapper, throwable, timestamp);
553551
}
554552
if (waeResponse != null) {
@@ -625,7 +623,7 @@ private ContainerResponse processResponseWithDefaultExceptionMapper(Throwable ex
625623
ContainerRequest request) {
626624
long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
627625
final Response response = processExceptionWithMapper(DEFAULT_EXCEPTION_MAPPER, exception, timestamp);
628-
return processResponse(preProcessResponse(response, request));
626+
return processResponse(preProcessResponse(response, request), exception);
629627
}
630628

631629
private ContainerResponse writeResponse(final ContainerResponse response) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.server;
18+
19+
import jakarta.ws.rs.GET;
20+
import jakarta.ws.rs.Path;
21+
import jakarta.ws.rs.container.AsyncResponse;
22+
import jakarta.ws.rs.container.CompletionCallback;
23+
import jakarta.ws.rs.container.Suspended;
24+
import jakarta.ws.rs.core.Response;
25+
import org.junit.Assert;
26+
import org.junit.Test;
27+
28+
import java.io.IOException;
29+
import java.util.concurrent.atomic.AtomicInteger;
30+
31+
public class DefaultExceptionMapperTest {
32+
public static final String MESSAGE = "DefaultExceptionMapperTest I/O Exception";
33+
@Test
34+
public void testIOException() {
35+
IOException ioe = new IOException(MESSAGE);
36+
DefaultExceptionMapper mapper = new DefaultExceptionMapper();
37+
Response response = mapper.toResponse(ioe);
38+
Assert.assertFalse(response.getEntity().toString().contains(MESSAGE));
39+
}
40+
41+
@Test
42+
public void testCompletionCallback() {
43+
AtomicInteger counter = new AtomicInteger();
44+
CompletionCallback hitOnceCallback = new CompletionCallback() {
45+
@Override
46+
public void onComplete(Throwable throwable) {
47+
counter.incrementAndGet();
48+
}
49+
};
50+
ResourceConfig resourceConfig = new ResourceConfig().register(new IOExThrowingResource(hitOnceCallback));
51+
ApplicationHandler applicationHandler = new ApplicationHandler(resourceConfig);
52+
try {
53+
applicationHandler.apply(RequestContextBuilder.from("/", "GET").build()).get();
54+
} catch (Exception e) {
55+
// expected
56+
}
57+
58+
Assert.assertEquals(1, counter.get());
59+
}
60+
61+
@Path("/")
62+
public static class IOExThrowingResource {
63+
private final CompletionCallback callback;
64+
65+
public IOExThrowingResource(CompletionCallback callback) {
66+
this.callback = callback;
67+
}
68+
69+
@GET
70+
public String doGet(@Suspended AsyncResponse asyncResponse) throws IOException {
71+
asyncResponse.register(callback);
72+
throw new IOException(MESSAGE);
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)