Search code examples
javajersey-2.0jersey-client

Why am I getting an IllegalArgumentException when calling DELETE over HTTPS but not when using HTTP and not when calling GET over HTTPS?


Any thoughts on this issue would be appreciated.

I am accessing a Play Framework server's REST API with a Jersey 2.24.1 client. Generally I can access most API endpoints (GET, POST, PUT) fine (or seemingly so):

Response response = ClientBuilder.newClient().target("https://api.myserver.com")
                                .path("/getEndpointPath")
                                .request()
                                .header(HttpHeaders.AUTHORIZATION, "encoded auth string")
                                .get();

However, calls to DELETE methods will throw an exception when using HTTPS but will not fail exceptionally if the url is changed to use HTTP:

Response response = ClientBuilder.newClient().target("https://api.myserver.com")
                                .path("/deleteEndpointPath")
                                .request()
                                .header(HttpHeaders.AUTHORIZATION, "encoded auth string")
                                .delete();

The stack trace:

javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: protocol = https host = null

    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:261)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.delete(JerseyInvocation.java:360)
    at com.signifyd.integrationTest.v2api.HttpsTest.troubleshootDelete(HttpsTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at com.intellij.junit4.JUnit4TestRunnerUtil$IgnoreIgnoredTestJUnit4ClassRunner.runChild(JUnit4TestRunnerUtil.java:365)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: protocol = https host = null
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1455)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
    at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2979)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:489)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:399)
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
    ... 36 more
Caused by: java.lang.IllegalArgumentException: protocol = https host = null
    at sun.net.spi.DefaultProxySelector.select(DefaultProxySelector.java:176)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1099)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177)
    at sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2662)
    at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2584)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1770)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    ... 40 more

Also, I can access these endpoints via HTTPS using Postman, so it appears that the endpoints are not completely broken.

Any idea how this can happen?

Additional Information

The request header looks like:

INFO: 1 * Sending client request on thread main
1 > DELETE https://api.myserver.com/deleteEndpointPath
1 > Authorization: Basic THSAHASDFJalkasdlgjisadjkladfsk09A==:

Solution

  • I had this issue and it was a simple mistake, leaving it here in case it helps anyone else. In the code below I had omitted @PathVariable (value = "id"). Now that it's included the below works.

    @DeleteMapping("/deletePosition/{id}")
    public ResponseEntity<?> deletePositionById(@PathVariable (value = "id") Long positionId) {
        return positionService.deletePositionById(positionId);
        
    }