2016-07-26 10 views
0

In meiner REST-Anwendung senden verwende ich diese Klasse Anfragen senden:Kann nicht die Ausnahme abfangen, wenn ich eine REST-Anfrage an einen HTTP-Server offline

public final class Utility { 

private static Client client = ClientBuilder.newClient(); 

private Utility(){ 
} 

public static <T> Response sendRequest(String URI, String method, T payload){ 
    Response response = null; 
    WebTarget target = client.target(URI); 
    switch(method){ 
    case "GET": 
     response = target.request().header("Content-type", "application/json").get(); 
     break; 
    case "POST": 
     response = target.request().header("Content-type", "application/json").post(Entity.json(payload)); 
     break; 
    case "PUT": 
     response = target.request().header("Content-type", "application/json").put(Entity.json(payload)); 
     break; 
    case "DELETE": 
     response = target.request().header("Content-type", "application/json").delete(); 
     break; 
    default: 
     throw new NotAllowedException("Invalid method type was given " 
       + "to the Utility.sendRequest() method"); 
    } 

    if(response == null){ 
     throw new UnavailableServerException("The server at (" + URI + ") did not respond."); 

    } 

    return response; 
} 
} 

Ich habe vor kurzem hatte die Idee, die ich behandeln mag Fälle, wenn ich eine Anfrage an einen Endpunkt sende, der nicht antworten kann. (Ich habe den grizzly http-Server dafür nicht gestartet). Ich habe gelernt, dass, wenn ich versuche, eine Anfrage an einen solchen Endpunkt zu senden, mein allgemeiner ExceptionMapper (der ExceptionMapper (ExceptionMapper) implementiert) ihn abfängt, und die Ausnahme war eine NullPointerException (NPE).

Also dachte ich, alles, was ich tun muss, ist einfach die Response an eine Variable auszulagern und vor dem Zurückgeben zu prüfen, ob es == null ist. Mit printfs und Debug-Modus sah ich das folgende Verhalten:

  • Auch für die fehlgeschlagene Anforderung ist response == null nicht wahr.
  • Die fehlgeschlagene Anfrage wird an die Zeile, aber die nächste Zeile in meiner Ressourcenmethode wird nicht ausgeführt, Ausnahme passiert.
  • Ich habe versucht, die NPE (auch mit catch(Exception e)) mit try-catch-Blöcke innerhalb der Utility-Klasse und innerhalb der Ressource-Methode auch, ohne Erfolg.
  • Ich habe versucht, herauszufinden, was wirft NPE in der javax.ws.rs.core.Response; Dokumentation -> kein Erfolg. Ich habe keine Ideen:/(Btw UnavailableServerException ist meine benutzerdefinierte Ausnahme auch.)

    Auch was ist der richtige Weg zu überprüfen, ist die Anfrage erfolgreich, da der Null-Check offensichtlich keine gute Lösung.

    EDIT: hier die stacktrace

    javax.ws.rs.ProcessingException: Already connected 
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:264) 
    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:437) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.put(JerseyInvocation.java:326) 
    at eu.arrowhead.common.Utility.sendRequest(Utility.java:32) 
    at eu.arrowhead.core.gatekeeper.GatekeeperResource.GSDPoll(GatekeeperResource.java:146) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) 
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) 
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) 
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) 
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 
    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:267) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) 
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) 
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) 
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384) 
    at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224) 
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591) 
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571) 
    at java.lang.Thread.run(Unknown Source) 
    Caused by: java.lang.IllegalStateException: Already connected 
    at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(Unknown Source) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector.setOutboundHeaders(HttpUrlConnector.java:421) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector.access$100(HttpUrlConnector.java:96) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector$4.getOutputStream(HttpUrlConnector.java:384) 
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:200) 
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:194) 
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:262) 
    at org.glassfish.jersey.message.internal.OutboundMessageContext.commitStream(OutboundMessageContext.java:816) 
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:545) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285) 
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:255) 
    ... 37 more 
    

    EDIT2 ist:

    @Provider 
    public class GenericExceptionMapper implements ExceptionMapper<Exception> { 
    
    @Override 
    public Response toResponse(Exception ex) { 
        ErrorMessage errorMessage = new ErrorMessage("Class: " + ex.getClass().toString() + 
          " Message: " + ex.getMessage(), 500, "No documentation yet."); 
        return Response.status(Status.INTERNAL_SERVER_ERROR) 
          .entity(errorMessage) 
          .build(); 
    } 
    
    } 
    

    Auch hier ist mein allgemeiner Ausnahme-Mapper, obwohl ich denke, das ist nicht Teil des Problems ist, anstatt dass in meinem Beispiel meine Anfrage 3 Server beinhaltet. Diese Anfrage wird an einen Online-Server gesendet, der etwas an einen zweiten Online-Server sendet (mit der gleichen Nutzungsklassenmethode), der eine dritte abfragt, die in meinem Test offline ist. Der 2. Server bricht die ProcessingException ab (soweit ich weiß, kann die OK-Antwort sein, wenn der 3. Server offline ist) und sendet meine benutzerdefinierte Ausnahme zurück. aber dann auf dem ersten Server kann irgendwie diese Ausnahme nicht zurück zu meinem Postman-Client senden, und eine generische NPE wird geworfen.

    Ich werde versuchen, den Grund dafür morgen aber zu finden. Ich werde auch Jersey von 2.22.1 auf 2.23.1 aktualisieren.

    +0

    versuchen Sie, Ihren Code in den 'try catch' Block zu setzen. Ich denke, wenn Server nicht verfügbar ist, wird HttpException ausgelöst. – Valijon

    +0

    Bitte zeigen Sie den tatsächlichen Stacktrace –

    +0

    Ich kann leider nicht wirklich einen Stacktrace zeigen. Selbst wenn ich meinen generischen Exception Mapper abmelde, ist das einzige, was ich im Postboten zurückbekomme, die Grizzly html Seite, ich glaube etwas maskiert den Stacktrace. @Valijon Ich habe das schon probiert, wie ich in der Post erwähnt habe, keine Ahnung, wieso geht das nicht. –

    Antwort

    -1

    Ich habe try catch Block gesetzt und bekam ProcessingException

    ScopedJaxrsResponse{ClientResponse{method=GET, uri=http://google.com/, status=200, reason=OK}} 
    javax.ws.rs.ProcessingException: java.net.UnknownHostException: foo.bar 
        at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:205) 
        at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:217) 
        at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:655) 
        at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:652) 
        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:422) 
        at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:652) 
        at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:387) 
        at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:291) 
        at foo.Utility.sendRequest(Utility.java:32) 
        at foo.Utility.a(Utility.java:23) 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
        at java.lang.reflect.Method.invoke(Method.java:606) 
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
    Caused by: java.net.UnknownHostException: foo.bar 
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:178) 
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) 
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) 
        at java.net.Socket.connect(Socket.java:579) 
        at sun.net.NetworkClient.doConnect(NetworkClient.java:175) 
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:432) 
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:527) 
        at sun.net.www.http.HttpClient.<init>(HttpClient.java:211) 
        at sun.net.www.http.HttpClient.New(HttpClient.java:308) 
        at sun.net.www.http.HttpClient.New(HttpClient.java:326) 
        at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:997) 
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:933) 
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:851) 
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301) 
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468) 
        at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:296) 
        at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:203) 
        ... 35 more 
    

    Junit Fehler:

    java.lang.IllegalArgumentException: The server at (http://foo.bar/) did not respond. 
        at foo.Utility.sendRequest(Utility.java:53) 
        at foo.Utility.a(Utility.java:23) 
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
        at java.lang.reflect.Method.invoke(Method.java:606) 
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
    

    Code:

    import javax.ws.rs.NotAllowedException; 
    import javax.ws.rs.client.Client; 
    import javax.ws.rs.client.ClientBuilder; 
    import javax.ws.rs.client.Entity; 
    import javax.ws.rs.client.WebTarget; 
    import javax.ws.rs.core.Response; 
    
    import org.junit.Test; 
    
    public final class Utility { 
    
        private static Client client = ClientBuilder.newClient(); 
    
        public Utility() { 
    
        } 
    
        @Test 
        public void a() { 
         System.out.println(Utility.sendRequest("http://google.com/", "GET", "")); 
         System.out.println(Utility.sendRequest("http://foo.bar/", "GET", "")); 
        } 
    
        public static <T> Response sendRequest(String URI, String method, T payload) { 
         Response response = null; 
         try { 
          WebTarget target = client.target(URI); 
          switch (method) { 
          case "GET": 
           response = target.request().header("Content-type", "application/json").get(); 
           break; 
          case "POST": 
           response = target.request().header("Content-type", "application/json").post(Entity.json(payload)); 
           break; 
          case "PUT": 
           response = target.request().header("Content-type", "application/json").put(Entity.json(payload)); 
           break; 
          case "DELETE": 
           response = target.request().header("Content-type", "application/json").delete(); 
           break; 
          default: 
           throw new NotAllowedException("Invalid method type was given " + "to the Utility.sendRequest() method"); 
          } 
         } catch(Exception e) { 
          e.printStackTrace(); 
          response = null; 
         } 
    
         if (response == null) { 
          throw new IllegalArgumentException("The server at (" + URI + ") did not respond."); 
    
         } 
    
         return response; 
        } 
    } 
    
    +0

    ich vergaß ich kann den Stacktrace wie folgt bekommen. siehe mein Edit –

    +0

    übrigens in Postman zeigt es immer noch ein frikin NPE, wenn ich meinen try-catch-block habe und die if-aussage danach eingerichtet habe, genau wie deins. wie ist das möglich? –

    +0

    Was ist Ihre Jax-RS-Version? – Valijon

    1

    Die Antwort sollte nicht null sein.Genau wie beim Besuch einer Seite durch den Browser, wenn sie nicht existiert, sollten Sie einen Serverfehler bekommen. Überprüfen Sie die Antwort.getStatus() für etwas in den 400

    Sie könnten auch versuchen, einige sinnvolle Timeouts.

    public static <T> Response sendRequest(String URI, String method, T payload){ 
    try{ 
        ClientConfig configuration = new ClientConfig(); 
        configuration.property(ClientProperties.CONNECT_TIMEOUT, 10000); 
        configuration.property(ClientProperties.READ_TIMEOUT, 10000); 
        Client client = ClientBuilder.newClient(configuration); 
    
        Response response = null; 
        WebTarget target = client.target(UriBuilder.fromUri(URI).build()) 
        switch(method){ 
        case "GET": 
         response = target.request().header("Content-type", "application/json").get(); 
         break; 
        case "POST": 
         response = target.request().header("Content-type", "application/json").post(Entity.json(payload)); 
         break; 
        case "PUT": 
         response = target.request().header("Content-type", "application/json").put(Entity.json(payload)); 
         break; 
        case "DELETE": 
         response = target.request().header("Content-type", "application/json").delete(); 
         break; 
        default: 
         throw new NotAllowedException("Invalid method type was given " 
           + "to the Utility.sendRequest() method"); 
        } 
    
        if(response.getStatus() != 200){ //200 OK! 
         throw new UnavailableServerException("The server at (" + URI + ") did not respond."); 
        } 
        return response; 
    }catch(Exception e){ 
        e.printStackTrace(); 
    } 
    return Response.status(Status.NOT_FOUND).build(); 
    }