Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "bugfix",
"category": "Url Connection Client",
"contributor": "",
"description": "Allow retry when URL Connection HTTP Client encounters a NullPointerException wrapped in a RuntimeException"
}
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ private <T> Optional<T> getAndHandle100Bug(Supplier<T> supplier, boolean failOn1
try {
return Optional.ofNullable(supplier.get());
} catch (RuntimeException e) {
if (e.getCause() instanceof NullPointerException) {
throw new UncheckedIOException(new IOException(
"Unexpected NullPointerException when calling HttpURLConnection", e));
}

if (!exceptionCausedBy100HandlingBug(e)) {
throw e;
}
Expand Down Expand Up @@ -431,6 +436,12 @@ private static int getResponseCodeSafely(HttpURLConnection connection) throws IO
return connection.getResponseCode();
} catch (NullPointerException e) {
throw new IOException("Unexpected NullPointerException when trying to read response from HttpURLConnection", e);
} catch (RuntimeException e) {
if (e.getCause() instanceof NullPointerException) {
throw new IOException("Unexpected NullPointerException when trying to read response from "
+ "HttpURLConnection", e);
}
throw e;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
Expand Down Expand Up @@ -75,6 +76,46 @@ public int getResponseCode() {
.hasCauseInstanceOf(NullPointerException.class);
}

@Test
public void testGetResponseCodeRuntimeExceptionWrappingNpeIsWrappedAsIo() throws Exception {
connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) {
@Override
public int getResponseCode() {
throw new RuntimeException(new NullPointerException("this.http is null"));
}
});

assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK))
.isInstanceOf(IOException.class)
.hasCauseInstanceOf(RuntimeException.class);
}

@Test
public void testGetOutputStreamRuntimeExceptionWrappingNpeIsWrappedAsIo() throws Exception {
connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) {
@Override
public OutputStream getOutputStream() {
throw new RuntimeException(new NullPointerException("this.http is null"));
}
});

assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK))
.isInstanceOf(UncheckedIOException.class);
}

@Test
public void testGetInputStreamRuntimeExceptionWrappingNpeIsWrappedAsIo() throws Exception {
connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) {
@Override
public InputStream getInputStream() {
throw new RuntimeException(new NullPointerException("this.http is null"));
}
});

assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK))
.isInstanceOf(UncheckedIOException.class);
}

private class DelegateHttpURLConnection extends HttpURLConnection {
private final HttpURLConnection delegate;

Expand Down
Loading