4141
4242import java .io .IOException ;
4343import java .io .OutputStream ;
44+ import java .lang .annotation .Annotation ;
45+ import java .lang .reflect .Type ;
4446import java .net .ConnectException ;
4547import java .net .NoRouteToHostException ;
4648import java .net .SocketTimeoutException ;
5961import javax .ws .rs .core .GenericType ;
6062import javax .ws .rs .core .HttpHeaders ;
6163import javax .ws .rs .core .MediaType ;
64+ import javax .ws .rs .core .MultivaluedMap ;
6265import javax .ws .rs .core .Response ;
6366import javax .ws .rs .core .Variant ;
6467import javax .ws .rs .ext .ReaderInterceptor ;
6568import javax .ws .rs .ext .WriterInterceptor ;
6669
70+ import javax .net .ssl .SSLException ;
71+
6772import org .glassfish .jersey .client .internal .LocalizationMessages ;
6873import org .glassfish .jersey .internal .MapPropertiesDelegate ;
6974import org .glassfish .jersey .internal .PropertiesDelegate ;
@@ -495,11 +500,24 @@ public void writeEntity() throws IOException {
495500 entityWritten = true ;
496501 ensureMediaType ();
497502 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 {
498516 OutputStream entityStream = null ;
499517 boolean connectionFailed = false ;
500518 try {
501519 try {
502- entityStream = workers .writeTo (
520+ entityStream = writeWorkers .writeTo (
503521 getEntity (),
504522 entityType .getRawType (),
505523 entityType .getType (),
@@ -510,21 +528,8 @@ public void writeEntity() throws IOException {
510528 getEntityStream (),
511529 writerInterceptors );
512530 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
528533 connectionFailed = true ;
529534 throw e ;
530535 }
0 commit comments