41
41
42
42
import java .io .IOException ;
43
43
import java .io .OutputStream ;
44
+ import java .lang .annotation .Annotation ;
45
+ import java .lang .reflect .Type ;
44
46
import java .net .ConnectException ;
45
47
import java .net .NoRouteToHostException ;
46
48
import java .net .SocketTimeoutException ;
59
61
import javax .ws .rs .core .GenericType ;
60
62
import javax .ws .rs .core .HttpHeaders ;
61
63
import javax .ws .rs .core .MediaType ;
64
+ import javax .ws .rs .core .MultivaluedMap ;
62
65
import javax .ws .rs .core .Response ;
63
66
import javax .ws .rs .core .Variant ;
64
67
import javax .ws .rs .ext .ReaderInterceptor ;
65
68
import javax .ws .rs .ext .WriterInterceptor ;
66
69
70
+ import javax .net .ssl .SSLException ;
71
+
67
72
import org .glassfish .jersey .client .internal .LocalizationMessages ;
68
73
import org .glassfish .jersey .internal .MapPropertiesDelegate ;
69
74
import org .glassfish .jersey .internal .PropertiesDelegate ;
@@ -495,11 +500,24 @@ public void writeEntity() throws IOException {
495
500
entityWritten = true ;
496
501
ensureMediaType ();
497
502
final GenericType <?> entityType = new GenericType (getEntityType ());
503
+ doWriteEntity (workers , entityType );
504
+ }
505
+
506
+ /**
507
+ * Added only to make the code testable.
508
+ *
509
+ * @param writeWorkers Message body workers instance used to write the entity.
510
+ * @param entityType entity type.
511
+ * @throws IOException when {@link MessageBodyWorkers#writeTo(Object, Class, Type, Annotation[], MediaType,
512
+ * MultivaluedMap, PropertiesDelegate, OutputStream, Iterable)} throws an {@link IOException}.
513
+ * This state is always regarded as connection failure.
514
+ */
515
+ /* package */ void doWriteEntity (final MessageBodyWorkers writeWorkers , final GenericType <?> entityType ) throws IOException {
498
516
OutputStream entityStream = null ;
499
517
boolean connectionFailed = false ;
500
518
try {
501
519
try {
502
- entityStream = workers .writeTo (
520
+ entityStream = writeWorkers .writeTo (
503
521
getEntity (),
504
522
entityType .getRawType (),
505
523
entityType .getType (),
@@ -510,21 +528,8 @@ public void writeEntity() throws IOException {
510
528
getEntityStream (),
511
529
writerInterceptors );
512
530
setEntityStream (entityStream );
513
- } catch (final ConnectException ce ) {
514
- // MessageBodyWorkers.writeTo() produces more general IOException, but we are only interested in specifying if
515
- // the failure was caused by connection problems or by other circumstances
516
- connectionFailed = true ;
517
- throw ce ;
518
- } catch (final SocketTimeoutException e ) {
519
- // if MessageBodyWorkers.writeTo() fails because of non-routable target, SocketTimeOutException is thrown.
520
- // In that case, exception is rethrown and the connectionFailed flag is set to prevent the attempt to commit.
521
- // Calling commitStream() would lead to another wait time and the final timeout time would be twice as long
522
- // as described in JERSEY-1984. Depending on a system and configuration, NoRouteToHostException may be thrown
523
- // instead of SocketTimeoutException (see below).
524
- connectionFailed = true ;
525
- throw e ;
526
- } catch (final NoRouteToHostException e ) {
527
- // to cover all the cases, also NoRouteToHostException is to be handled similarly.
531
+ } catch (final IOException e ) {
532
+ // JERSEY-2728 - treat SSLException as connection failure
528
533
connectionFailed = true ;
529
534
throw e ;
530
535
}
0 commit comments