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.
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. –
Ich versuchte dies, aber wenn ich Uri, bekomme eine Nachricht wie http4 wird nicht unterstützt, wenn der Anruf erfolgt – victorjpe
Ich änderte die URI zu http Anruf, aber immer noch die sogar gleichmäßige Antwort ist 204, die HttpOperationFailedException nicht geworfen – victorjpe