Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit 8502d97

Browse files
committed
Not masking exceptions being thrown during entity write of Jersey Client.
This fix prevents useless exception 'java.lang.IllegalStateException: Already connected' to be printed instead of an original reason. Related to JERSEY-2728. Change-Id: I7c5dbf49c14fd3c7e3bcac9a25300c97fcd15cb8 (cherry picked from commit 4830e32)
1 parent 74d6c2c commit 8502d97

File tree

3 files changed

+143
-14
lines changed

3 files changed

+143
-14
lines changed

core-client/src/main/java/org/glassfish/jersey/client/ClientRequest.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2012-2016 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -43,9 +43,6 @@
4343
import java.io.OutputStream;
4444
import java.lang.annotation.Annotation;
4545
import java.lang.reflect.Type;
46-
import java.net.ConnectException;
47-
import java.net.NoRouteToHostException;
48-
import java.net.SocketTimeoutException;
4946
import java.net.URI;
5047
import java.util.Collection;
5148
import java.util.List;
@@ -67,12 +64,11 @@
6764
import javax.ws.rs.ext.ReaderInterceptor;
6865
import javax.ws.rs.ext.WriterInterceptor;
6966

70-
import javax.net.ssl.SSLException;
71-
7267
import org.glassfish.jersey.client.internal.LocalizationMessages;
7368
import org.glassfish.jersey.internal.MapPropertiesDelegate;
7469
import org.glassfish.jersey.internal.PropertiesDelegate;
7570
import org.glassfish.jersey.internal.inject.ServiceLocatorSupplier;
71+
import org.glassfish.jersey.internal.util.ExceptionUtils;
7672
import org.glassfish.jersey.internal.util.PropertiesHelper;
7773
import org.glassfish.jersey.message.MessageBodyWorkers;
7874
import org.glassfish.jersey.message.internal.OutboundMessageContext;
@@ -515,6 +511,7 @@ public void writeEntity() throws IOException {
515511
/* package */ void doWriteEntity(final MessageBodyWorkers writeWorkers, final GenericType<?> entityType) throws IOException {
516512
OutputStream entityStream = null;
517513
boolean connectionFailed = false;
514+
boolean runtimeException = false;
518515
try {
519516
try {
520517
entityStream = writeWorkers.writeTo(
@@ -532,6 +529,9 @@ public void writeEntity() throws IOException {
532529
// JERSEY-2728 - treat SSLException as connection failure
533530
connectionFailed = true;
534531
throw e;
532+
} catch (final RuntimeException e) {
533+
runtimeException = true;
534+
throw e;
535535
}
536536
} finally {
537537
// in case we've seen the ConnectException, we won't try to close/commit stream as this would produce just
@@ -542,14 +542,22 @@ public void writeEntity() throws IOException {
542542
if (entityStream != null) {
543543
try {
544544
entityStream.close();
545-
} catch (final IOException ex) {
546-
LOGGER.log(Level.FINE, LocalizationMessages.ERROR_CLOSING_OUTPUT_STREAM(), ex);
545+
} catch (final IOException e) {
546+
ExceptionUtils.conditionallyReThrow(e, !runtimeException, LOGGER,
547+
LocalizationMessages.ERROR_CLOSING_OUTPUT_STREAM(), Level.FINE);
548+
} catch (final RuntimeException e) {
549+
ExceptionUtils.conditionallyReThrow(e, !runtimeException, LOGGER,
550+
LocalizationMessages.ERROR_CLOSING_OUTPUT_STREAM(), Level.FINE);
547551
}
548552
}
549553
try {
550554
commitStream();
551555
} catch (final IOException e) {
552-
LOGGER.log(Level.SEVERE, LocalizationMessages.ERROR_COMMITTING_OUTPUT_STREAM(), e);
556+
ExceptionUtils.conditionallyReThrow(e, !runtimeException, LOGGER,
557+
LocalizationMessages.ERROR_COMMITTING_OUTPUT_STREAM(), Level.SEVERE);
558+
} catch (final RuntimeException e) {
559+
ExceptionUtils.conditionallyReThrow(e, !runtimeException, LOGGER,
560+
LocalizationMessages.ERROR_COMMITTING_OUTPUT_STREAM(), Level.SEVERE);
553561
}
554562
}
555563
}

core-client/src/test/java/org/glassfish/jersey/client/ClientRequestTest.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -52,16 +52,18 @@
5252

5353
import org.glassfish.jersey.internal.MapPropertiesDelegate;
5454
import org.glassfish.jersey.internal.PropertiesDelegate;
55+
import org.glassfish.jersey.internal.util.ExceptionUtils;
5556
import org.glassfish.jersey.message.MessageBodyWorkers;
5657

58+
import org.hamcrest.core.Is;
5759
import org.junit.Assert;
5860
import org.junit.Test;
5961
import org.junit.runner.RunWith;
6062
import static org.junit.Assert.assertEquals;
6163
import static org.junit.Assert.assertFalse;
6264
import static org.junit.Assert.assertNull;
63-
import static org.junit.Assert.assertSame;
6465
import static org.junit.Assert.assertTrue;
66+
import static org.junit.Assert.fail;
6567

6668
import mockit.Mock;
6769
import mockit.MockUp;
@@ -87,7 +89,6 @@ public void testResolveProperty() {
8789
// test property in neither config nor request
8890
client = new JerseyClientBuilder().build();
8991

90-
9192
request = new ClientRequest(
9293
URI.create("http://example.org"),
9394
client.getConfiguration(),
@@ -179,9 +180,40 @@ OutputStream writeTo(Object entity, Class<?> rawType, Type type, Annotation[] an
179180

180181
try {
181182
request.doWriteEntity(workers, entityType);
182-
Assert.fail("An IOException exception should be thrown.");
183+
fail("An IOException exception should be thrown.");
183184
} catch (IOException e) {
184-
assertSame(ioException, e);
185+
Assert.assertThat("Detected a un-expected exception! \n" + ExceptionUtils.exceptionStackTraceAsString(e),
186+
e, Is.is(ioException));
187+
}
188+
}
189+
@Test
190+
public void testRuntimeExceptionBeingReThrown(@Mocked MessageBodyWorkers workers, @Mocked GenericType<?> entityType)
191+
throws Exception {
192+
JerseyClient client = new JerseyClientBuilder().build();
193+
final ClientRequest request = new ClientRequest(
194+
URI.create("http://example.org"),
195+
client.getConfiguration(),
196+
new MapPropertiesDelegate());
197+
198+
final RuntimeException runtimeException = new RuntimeException("Test");
199+
new MockUp<MessageBodyWorkers>(workers) {
200+
@Mock
201+
OutputStream writeTo(Object entity, Class<?> rawType, Type type, Annotation[] annotations,
202+
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
203+
PropertiesDelegate propertiesDelegate, OutputStream entityStream,
204+
Iterable<WriterInterceptor> writerInterceptors)
205+
throws java.io.IOException, javax.ws.rs.WebApplicationException {
206+
throw runtimeException;
207+
}
208+
};
209+
210+
try {
211+
request.doWriteEntity(workers, entityType);
212+
Assert.fail("A RuntimeException exception should be thrown.");
213+
} catch (RuntimeException e) {
214+
Assert.assertThat("Detected a un-expected exception! \n" + ExceptionUtils.exceptionStackTraceAsString(e),
215+
e, Is.is(runtimeException));
185216
}
186217
}
218+
187219
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
package org.glassfish.jersey.internal.util;
41+
42+
import java.io.PrintWriter;
43+
import java.io.StringWriter;
44+
import java.util.logging.Level;
45+
import java.util.logging.Logger;
46+
47+
/**
48+
* The Exception Utils class provide utility method for exception handling.
49+
*
50+
* @author Stepan Vavra ([email protected])
51+
*/
52+
public final class ExceptionUtils {
53+
54+
private ExceptionUtils() {
55+
}
56+
57+
/**
58+
* Gets the stack trace of the provided throwable as a string.
59+
*
60+
* @param t the exception to get the stack trace for.
61+
* @return the stack trace as a string.
62+
*/
63+
public static String exceptionStackTraceAsString(Throwable t) {
64+
StringWriter sw = new StringWriter();
65+
t.printStackTrace(new PrintWriter(sw));
66+
return sw.toString();
67+
}
68+
69+
/**
70+
* Based on the rethrow parameter, either rethrows the supplied exception or logs the provided message at the given level.
71+
*
72+
* @param e the exception to rethrow if rethrow is {@code true}.
73+
* @param rethrow whether to rethrow an exception or just log the provided message.
74+
* @param logger the logger to print the message with.
75+
* @param m the message to log if rethrow is {@code false}.
76+
* @param level the level of the logged message.
77+
* @param <T> the type of the exception to be conditionally rethrown.
78+
* @throws T if rethrow is {@code true}.
79+
*/
80+
public static <T extends Exception> void conditionallyReThrow(T e, boolean rethrow, Logger logger, String m, Level level)
81+
throws T {
82+
if (rethrow) {
83+
throw e;
84+
} else {
85+
// do not mask the other exception, just log this one
86+
logger.log(level, m, e);
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)