2016-08-10 3 views
0

Ich bin relativ neu auf Kamel. Ich stehe vor dem Problem, während ich die folgenden Funktionen implementiere.Apache Kamel mit HttpEndpoint Optionen mit http4

Voraussetzung: Rufen Sie den GET-Service, wenn die Antwort als 200 anderer Status ist, braucht ein HttpOperationFailedException zu werfen, so dass 204 Ausnahme i eine OnException auf meinen Eltern Route mit umgehen kann.

Ich konnte es mit dem folgenden Code erreichen:

from("direct:parent") 
.onException(HttpOperationFailedException.class) 
.onWhen(exchange ->{ 
    HttpOperationFailedException exe = exchange.getException(HttpOperationFailedException.class); 
    if(204 == exe.getStatusCode()){ 
     return true; 
    } 
    return false; 
}) 
.setBody(constant(null)) 
.end() 
.to("direct:a"); 

from("direct:a") 
.recipientList("false") 
.simple("http4://localhost:8022/test/service?okStatusCodeRange=200-201") 
.convertBodyTo(String.class); 

jedoch die Ausnahme nicht ausgelöst wird, wenn mit dem folgenden Code:

from("direct:parent") 
.onException(HttpOperationFailedException.class) 
.onWhen(exchange ->{ 
    HttpOperationFailedException exe = exchange.getException(HttpOperationFailedException.class); 
    if(204 == exe.getStatusCode()){ 
     return true; 
    } 
    return false; 
}) 
.setBody(constant(null)) 
.end() 
.to("direct:a"); 

from("direct:a") 
.to("http4://localhost:8022/test/service?okStatusCodeRange=200-201") 
.convertBodyTo(String.class); 

Würde jemand erklären, was geändert werden muss bekomme ich es mit statt einer receiveList Liste?

+0

Sie können versuchen, die URL als 'Exchange.HTTP_URI'-Header hinzuzufügen. Laut der [docs] (http://camel.apache.org/http4.html) überschreibt diese Kopfzeile jede direkt angegebene URL. Der Unterschied besteht darin, dass die in der Kopfzeile angegebene URL keine Konfigurationsoptionen unterstützt, während der '.to (...)' URI sie berücksichtigt. Wenn Sie den HTTP_URI-Header verwenden, können Sie auch eine Dummy-URL in der '.to (...)' verwenden, um den Endpunkt mit Sicherheit und verwandten Themen zu konfigurieren, da das tatsächliche Ziel durch den HTTP_URI-Header festgelegt wird. –

+0

Ich versuchte dies, aber wenn ich Uri, bekomme eine Nachricht wie http4 wird nicht unterstützt, wenn der Anruf erfolgt – victorjpe

+0

Ich änderte die URI zu http Anruf, aber immer noch die sogar gleichmäßige Antwort ist 204, die HttpOperationFailedException nicht geworfen – victorjpe

Antwort

0

Wenn Sie den HTTP-URI Aufruf direct:parent-direct:a propagieren, sondern eine verschachtelte Ausnahmeklausel in direct:parent, die Ausnahme in direct:a ist NICHT vermehrt nach oben zum übergeordneten Weg geworfen zu halten. Was Sie jedoch tun sollten, ist, die verschachtelte Ausnahmeklausel in eine globale Ausnahmeklausel umzuwandeln.

Ich habe einen einfachen Testfall erstellt, dass entweder die Ausnahme auf einem 204 Nachricht geworfen verspottet oder kann den wirklichen Dienst und nicht im Falle einer 204 Antwort aufrufen:

import org.apache.camel.Produce; 
import org.apache.camel.ProducerTemplate; 
import org.apache.camel.builder.AdviceWithRouteBuilder; 
import org.apache.camel.builder.RouteBuilder; 
import org.apache.camel.http.common.HttpOperationFailedException; 
import org.apache.camel.test.junit4.CamelTestSupport; 
import org.junit.Test; 

import java.util.HashMap; 
import java.util.Map; 

import static org.hamcrest.CoreMatchers.equalTo; 
import static org.hamcrest.CoreMatchers.is; 
import static org.hamcrest.CoreMatchers.nullValue; 

public class Http4ExceptionHandlingTest extends CamelTestSupport { 

    @Produce(uri = "direct:parent") 
    protected ProducerTemplate template; 

    @Override 
    public boolean isUseAdviceWith() { 
    return true; 
    } 

    @Override 
    protected RouteBuilder createRouteBuilder() { 
    return new RouteBuilder() { 
     @Override 
     public void configure() throws Exception { 

     onException(HttpOperationFailedException.class) 
      .onWhen(exchange -> { 
       HttpOperationFailedException 
        exe = exchange.getException(HttpOperationFailedException.class); 
       return 204 == exe.getStatusCode(); 
      }) 
      .log("HTTP exception handled") 
      .handled(true) 
      //.continued(true) 
      .setBody(constant(null)); 

     from("direct:parent").routeId("parent") 
//   .onException(HttpOperationFailedException.class) 
//    .onWhen(exchange -> { 
//     HttpOperationFailedException 
//      exe = exchange.getException(HttpOperationFailedException.class); 
//     return 204 == exe.getStatusCode(); 
//    }) 
//    .setBody(constant(null)) 
//   .end() 
      .log("Parent start"); 
      .to("direct:a") 
      .log("Parent done"); 

     from("direct:a").routeId("a") 
      .log("a start") 
      .to("http4://localhost:8022/test/service?okStatusCodeRange=200-201") 
      .convertBodyTo(String.class) 
      .log("a done"); 
     } 
    }; 
    } 

    @Test 
    public void testExceptionHandling() throws Exception { 
    // comment the following line out if you want to invoke the real service instead! 
    weaveRoute(); 

    context.start(); 

    Object response = template.requestBody("foo"); 

    assertThat(response, is(nullValue())); 
    } 

    @Test 
    public void testSuccessfulResponse() throws Exception { 
    // comment the following line out if you want to invoke the real service instead! 
    weaveRoute(); 

    context.start(); 

    Object response = template.requestBody("bar"); 

    assertThat(response, is(equalTo("bar"))); 
    } 

    private void weaveRoute() throws Exception { 
    context.getRouteDefinition("a").adviceWith(context, new AdviceWithRouteBuilder() { 
     @Override 
     public void configure() throws Exception { 
     this.interceptSendToEndpoint("http4*") 
      .skipSendToOriginalEndpoint() 
      .process(exchange -> { 
       String body = exchange.getIn().getBody(String.class); 
       if ("foo".equals(body)) { 
       Map<String, String> headers = new HashMap<>(); 
       String location = ""; 
       HttpOperationFailedException exe = 
        new HttpOperationFailedException("http://bla", 204, "No Content", location, 
                headers, "response body"); 
       throw exe; 
       } 
      }); 
     } 
    }); 
    } 
} 

ich das Original verlassen haben geschachtelte Ausnahmeklausel in der übergeordneten Route, so dass Sie die Ergebnisse vergleichen können. Der globale Exception-Handler hat eine zusätzliche .handled(true) Anweisung bekommen, die gerade aus der aktuellen Route ausbricht. Die Dokumentation gibt daher Folgendes an:

Wenn behandelt wird, wird die ausgelöste Ausnahme behandelt und Camel wird das Routing in der ursprünglichen Route nicht fortsetzen, aber ausbrechen. Sie können jedoch eine Route in der onException konfigurieren, die stattdessen verwendet wird. Sie verwenden diese Route, wenn Sie eine benutzerdefinierte Antwortnachricht an den Aufrufer oder eine andere Verarbeitung erstellen müssen, da diese Ausnahme ausgelöst wurde. (Source)

Nicht die abgefangene Ausnahme zu .handled(true) Einstellung wird actaully in einer Präsentation des stacktrace führen eher dann mit der Ausführung fortzufahren.

Ich habe weitere Protokollanweisungen hinzugefügt, um das Verhalten bei der Ausnahmebehandlung zu visualisieren. Auf die Ausführung des Codes über Ihnen präsentiert wird eine Ausgabe wie erhalten:

[INFO ] - - Parent start [   ] [parent] [    ] [main] 
[INFO ] - - a start [   ] [a] [    ] [main] 
[INFO ] - - HTTP exception handled [   ] [a] [    ] [main] 

Statt .handled(true) können Sie auch .continued(true) verwenden, um mit der Ausführung gehen Sie wie dokumentiert:

Wenn weiterhin wahr ist, dann Camel wird die Ausnahme abfangen und sie einfach ignorieren und weiter auf der ursprünglichen Route routen. Wenn Sie jedoch eine Route in der onException konfiguriert haben, wird diese Route zuerst routen, bevor das Routing in der ursprünglichen Route fortgesetzt wird.

Durchführung des Tests mit einem aktivierten .continued(true) und einem behinderten .handled(true) in der globalen Ausnahmeklausel wird die folgende Protokoll produzieren:

[INFO ] - - Parent start [   ] [parent] [    ] [main] 
[INFO ] - - a start [   ] [a] [    ] [main] 
[INFO ] - - HTTP exception handled [   ] [a] [    ] [main] 
[ERROR] - - Failed delivery for (MessageId: ...). Exhausted after delivery attempt: 1 caught: null. Handled and continue routing. 

Message History 
--------------------------------------------------------------------------------------------------------------------------------------- 
RouteId    ProcessorId   Processor                  Elapsed (ms) 
[parent   ] [parent   ] [direct://parent                ] [   8] 
[parent   ] [log9    ] [log                   ] [   0] 
[parent   ] [to4    ] [direct:a                  ] [   8] 
[a     ] [log7    ] [log                   ] [   1] 
[a     ] [to3    ] [http4://localhost:8022/test/service?okStatusCodeRange=200-201     ] [   8] 
[     ] [process2   ] [[email protected]               ] [   8] 
[a     ] [log6    ] [log                   ] [   1] 
[a     ] [setBody2   ] [setBody[{null}]                ] [   0] 

Stacktrace 
--------------------------------------------------------------------------------------------------------------------------------------- [   ] [o.a.c.p.DefaultErrorHandler] [    ] [main] 
org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://bla with statusCode: 204, redirectLocation: 
    at at.erpel.messaginghub.services.unit.routes.rest.Http4ExceptionHandlingTest$2.lambda$configure$1(Http4ExceptionHandlingTest.java:103) 
    at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63) 
    ... 
[INFO ] - - a done [   ] [a] [    ] [main] 
[INFO ] - - Parent done [   ] [parent] [    ] [main] 

Wie aus dem vereinfachten Protokoll zu sehen ist, .continued(true) nicht ausbrechen der Route protokolliert jedoch sowohl einen Nachrichtenverlauf als auch einen Stacktrace der ignorierten Ausnahme.

Im Fall einer nesed Ausnahmeklausel in der übergeordneten Route, während das Kind Weg in eine Ausnahme ausgeführt wird, das Hinzufügen .handled(true) oder .continuted(true) auf die verschachtelte Ausnahmeklausel hat keine Auswirkung als die eigentliche Ausnahme in der Route Kind gefangen wird nicht propagiert die verschachtelte Ausnahmeklausel der Eltern und wird daher überhaupt nicht behandelt.

Ich habe das Codebeispiel gegen den Mock sowie gegen einen echten Dienst getestet, der eine 204 Antwort auf einen foo Körper und eine 200 Antwort auf etwas anderes zurückgegeben zurückgegeben. Das Konfigurationsargument ?okStatusCodeRange=200-201 funktioniert daher in meinem Fall wie erwartet. Für Completenes: Ich benutze Camel 2.17.0.

+0

Danke für im Detail zu erklären, hatte ich versucht, das gleiche in meiner Route zu verwenden. Allerdings wird für mich die httpOperationFailureException nicht ausgelöst, wenn der Dienst eine 204 zurückgibt, wenn .to() verwendet. Das Gleiche funktioniert jedoch bei der Verwendung von .recipentList(). Kann auch sehen, dass bei Verwendung der recipentList in der Konsole eine Meldung wie die Konfiguration der Eigenschaft: okStatusCodeRange angezeigt wird. Dies wird jedoch nicht angezeigt, wenn .to() verwendet wird. Ich benutze Camel 2.17.2. Wird dies zu diesem Problem führen? – victorjpe

+0

Die einfachste Sache zu testen, wenn Camel 2.17.2 einige Probleme hat, ist, vorübergehend zurück zu 2.17.0 zu gehen, da dies für mich funktionierte, wie in der Antwort gezeigt. Hast du versucht, den Test durchzuführen? Funktioniert der Test für Sie? Falls die Mock-Version grün ist, können Sie waveRoute() 'im Test auskommentieren und den Test erneut ausführen. Diesmal sollte jedoch statt der Mocks der echte Dienst aufgerufen werden. Wenn das auch funktioniert, könnte das Problem irgendwo anders sein, vielleicht in einem anderen Fall, den Sie nicht in das vereinfachte Szenario aufgenommen haben. –

+0

Ich habe versucht, den Testfall mit 'webenRoute()' und nach dem Kommentieren auszuführen. Der Testfall funktioniert gut. Daher glaube ich, es ist kein Fehler in Kamel 2.17.2. Wie Sie bereits erwähnt haben, habe ich im Code die Elternroute innerhalb von '.doTry()' mit '.doCatch (exception)' aufgerufen, was möglicherweise das Problem verursacht. Werde etwas Refactoring versuchen. Vielen Dank @Roman Vottner – victorjpe

Verwandte Themen