Jonathan
Jonathan

Reputation: 2776

Mutual calls using camel rest-dsl

We have two applications A and B configured with camel rest-dsl to listen for incoming calls. Triggering either of them works just fine. However, whenever we have A calling B and within this call B calling A as well, we get a HTTP 500 on A although B is not reporting any problem and the answer-processing on A is performed correctly.

We have narrowed it down to the following example:

System A:

from("timer://myTimer?period=600s")
    .process(new Processor() {...})
    .setHeader(Exchange.HTTP_METHOD, constant("PUT"))
    .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
    .marshal().json(JsonLibrary.Jackson)
    .to("http4://localhost:8080/B/call")
    .end();

rest("/A").post("callResponse")
    .type(BResponse.class).consumes("application/json")
    .to("direct:handle");

from("direct:handle")
    .to("stream:out")
    .end();

System B

rest("/B").put("/call")
    .consumes("application/json")
    .type(BRequest.class)
    .to("direct:doB");

from("direct:doB")
    .process(requestToResponse)
    .marshal().json(JsonLibrary.Jackson)
    .setHeader(Exchange.HTTP_METHOD, constant("POST"))
    .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
    .to("http4://localhost:8081/A/callResponse?bridgeEndpoint=true")
    .end();
}

Using a lot of logging within the processors and routes, we can see that the BRequest object is created correctly and we can also see it arriving undamaged at B. There we can trace it to be converted to a BResponse and this reponse is again correctly sent to A. We can see all stages of the A-Rest-Endpoint to be executed correctly and after a final .to("stream:out)" the exception is thrown at A with the message "HTTP operation failed invoking http://localhost:8081/B/call with status code 500".

Our original goal was to decouple the executions of A and B such that A calls B via rest, immediately gets an answer and continues working while B processes the request asynchronously. This obviously does not happen (A waits for B waits for A) and may be part of the problem?

Upvotes: 1

Views: 941

Answers (1)

Souciance Eqdam Rashti
Souciance Eqdam Rashti

Reputation: 3191

I took your code and removed parts which were not necessary and ran it and also included full logging with seda queue and exchange pattern set. I didn't get any errors and the logs were produced at the right places. Here is my code:

System A

public void configure() {
    restConfiguration().component("undertow").host("localhost").port(8080).bindingMode(RestBindingMode.auto);
    from("timer://myTimer?period=600s")
            .setBody(constant("{\"hello\":\"hello\"}"))
            .setHeader(Exchange.HTTP_METHOD, constant("PUT"))
            .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))

            .marshal().json(JsonLibrary.Jackson)
            .to("http4://localhost:8080/B/call")
            .end();

    rest("/A").post("callResponse")
            .consumes("application/json")
            .to("seda:handle");

    from("seda:handle")
    .to("log:com.mycompany.handle?showAll=true&multiline=true")
            .to("stream:out")
            .end();
}

System B

    public void configure() throws Exception {
        restConfiguration().component("undertow").host("localhost").port(8080).bindingMode(RestBindingMode.auto);
        rest("/B").put("/call")
                .consumes("application/json")
                //.type(BRequest.class)
                .to("direct:doB");

        from("direct:doB")
        .to("log:com.mycompany.B?showAll=true&multiline=true")
                .marshal().json(JsonLibrary.Jackson)

                .setHeader(Exchange.HTTP_METHOD, constant("POST"))
                .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
                .to("log:com.mycompany.BeforeSendingToA?showAll=true&multiline=true")
                .to("http4://localhost:8080/A/callResponse?bridgeEndpoint=true")
                .to("log:com.mycompany.AfterSendingToA?showAll=true&multiline=true")
                .end(); 
}

My logs when the camel app starts:

[ouciance.random.MainApp.main()] HttpComponent                  INFO  Created ClientConnectionManager org.apache.http.impl.conn.PoolingHttpClientConnectionManager@4466f1ee
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
[ouciance.random.MainApp.main()] SedaEndpoint                   INFO  Endpoint seda://handle is using shared queue: seda://handle with size: 2147483647
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Route: route3 started and consuming from: timer://myTimer?period=600s
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Route: route4 started and consuming from: seda://handle
[ouciance.random.MainApp.main()] DefaultUndertowHost            INFO  Starting Undertow server on http://localhost:8080
[ouciance.random.MainApp.main()] xnio                           INFO  XNIO version 3.3.8.Final
[ouciance.random.MainApp.main()] nio                            INFO  XNIO NIO Implementation Version 3.3.8.Final
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Route: route1 started and consuming from: http://localhost:8080/A/callResponse?httpMethodRestrict=POST%2COPTIONS&matchOnUriPrefix=false
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Route: route5 started and consuming from: direct://doB
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Route: route2 started and consuming from: http://localhost:8080/B/call?httpMethodRestrict=PUT%2COPTIONS&matchOnUriPrefix=false
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Total 5 routes, of which 5 are started
[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Apache Camel 2.20.1 (CamelContext: camel-1) started in 1.696 seconds

My logs when the timer kicks in and the requests/responses are sent.

[ouciance.random.MainApp.main()] DefaultCamelContext            INFO  Apache Camel 2.20.1 (CamelContext: camel-1) started in 1.696 seconds
[                 XNIO-1 task-1] B                              INFO  Exchange[
, Id: ID-moeed-Dator-1517066840557-0-3
, ExchangePattern: InOut
, Properties: {CamelCharsetName=ISO-8859-1, CamelCreatedTimestamp=Sat Jan 27 16:27:23 CET 2018, CamelExternalRedelivered=false, CamelMessageHistory=[DefaultMessageHistory[routeId=route2, node=route2], DefaultMessageHistory[routeId=route5, node=to4]], CamelToEndpoint=log://com.mycompany.B?multiline=true&showAll=true}
, Headers: {Accept-Encoding=gzip,deflate, breadcrumbId=ID-moeed-Dator-1517066840557-0-1, CamelHttpCharacterEncoding=ISO-8859-1, CamelHttpMethod=PUT, CamelHttpPath=, CamelHttpQuery=, CamelHttpRawQuery=, CamelHttpUri=/B/call, CamelHttpUrl=http://localhost:8080/B/call, Connection=Keep-Alive, Content-Length=23, Content-Type=application/json, firedTime=Sat Jan 27 16:27:23 CET 2018, Host=localhost:8080, User-Agent=Apache-HttpClient/4.5.3 (Java/1.8.0_71)}
, BodyType: String
, Body: {"hello":"hello"}
, Out: null: 
]
[                 XNIO-1 task-1] BeforeSendingToA               INFO  Exchange[
, Id: ID-moeed-Dator-1517066840557-0-3
, ExchangePattern: InOut
, Properties: {CamelCharsetName=ISO-8859-1, CamelCreatedTimestamp=Sat Jan 27 16:27:23 CET 2018, CamelExternalRedelivered=false, CamelMessageHistory=[DefaultMessageHistory[routeId=route2, node=route2], DefaultMessageHistory[routeId=route5, node=to4], DefaultMessageHistory[routeId=route5, node=marshal2], DefaultMessageHistory[routeId=route5, node=setHeader3], DefaultMessageHistory[routeId=route5, node=setHeader4], DefaultMessageHistory[routeId=route5, node=to5]], CamelToEndpoint=log://com.mycompany.BeforeSendingToA?multiline=true&showAll=true}
, Headers: {Accept-Encoding=gzip,deflate, breadcrumbId=ID-moeed-Dator-1517066840557-0-1, CamelHttpCharacterEncoding=ISO-8859-1, CamelHttpMethod=POST, CamelHttpPath=, CamelHttpQuery=, CamelHttpRawQuery=, CamelHttpUri=/B/call, CamelHttpUrl=http://localhost:8080/B/call, Connection=Keep-Alive, Content-Length=23, Content-Type=application/json, firedTime=Sat Jan 27 16:27:23 CET 2018, Host=localhost:8080, User-Agent=Apache-HttpClient/4.5.3 (Java/1.8.0_71)}
, BodyType: byte[]
, Body: "{\"hello\":\"hello\"}"
, Out: null: 
]
[l-1) thread #2 - seda://handle] handle                         INFO  Exchange[
, Id: ID-moeed-Dator-1517066840557-0-8
, ExchangePattern: InOut
, Properties: {CamelCharsetName=ISO-8859-1, CamelCorrelationId=ID-moeed-Dator-1517066840557-0-5, CamelCreatedTimestamp=Sat Jan 27 16:27:23 CET 2018, CamelExternalRedelivered=false, CamelMessageHistory=[DefaultMessageHistory[routeId=route1, node=route1], DefaultMessageHistory[routeId=route4, node=to2]], CamelToEndpoint=log://com.mycompany.handle?multiline=true&showAll=true}
, Headers: {Accept-Encoding=gzip,deflate, breadcrumbId=ID-moeed-Dator-1517066840557-0-1, CamelHttpCharacterEncoding=ISO-8859-1, CamelHttpMethod=POST, CamelHttpPath=, CamelHttpQuery=, CamelHttpRawQuery=, CamelHttpUri=/A/callResponse, CamelHttpUrl=http://localhost:8080/A/callResponse, Connection=Keep-Alive, Content-Length=23, Content-Type=application/json, firedTime=Sat Jan 27 16:27:23 CET 2018, Host=localhost:8080, User-Agent=Apache-HttpClient/4.5.3 (Java/1.8.0_71)}
, BodyType: String
, Body: {"hello":"hello"}
, Out: null: 
]
{"hello":"hello"}
[                 XNIO-1 task-1] AfterSendingToA                INFO  Exchange[
, Id: ID-moeed-Dator-1517066840557-0-3
, ExchangePattern: InOut
, Properties: {CamelCharsetName=UTF-8, CamelCreatedTimestamp=Sat Jan 27 16:27:23 CET 2018, CamelExternalRedelivered=false, CamelMessageHistory=[DefaultMessageHistory[routeId=route2, node=route2], DefaultMessageHistory[routeId=route5, node=to4], DefaultMessageHistory[routeId=route5, node=marshal2], DefaultMessageHistory[routeId=route5, node=setHeader3], DefaultMessageHistory[routeId=route5, node=setHeader4], DefaultMessageHistory[routeId=route5, node=to5], DefaultMessageHistory[routeId=route5, node=to6], DefaultMessageHistory[routeId=route5, node=to7]], CamelSkipGzipEncoding=true, CamelToEndpoint=log://com.mycompany.AfterSendingToA?multiline=true&showAll=true}
, Headers: {Accept-Encoding=gzip,deflate, breadcrumbId=ID-moeed-Dator-1517066840557-0-1, CamelHttpCharacterEncoding=ISO-8859-1, CamelHttpMethod=POST, CamelHttpPath=, CamelHttpQuery=, CamelHttpRawQuery=, CamelHttpResponseCode=200, CamelHttpResponseText=OK, CamelHttpUri=/B/call, CamelHttpUrl=http://localhost:8080/B/call, Connection=keep-alive, Content-Length=23, Content-Type=application/json, Date=Sat, 27 Jan 2018 15:27:23 GMT, firedTime=Sat Jan 27 16:27:23 CET 2018, User-Agent=Apache-HttpClient/4.5.3 (Java/1.8.0_71)}
, BodyType: org.apache.camel.converter.stream.CachedOutputStream.WrappedInputStream
, Body: [Body is instance of java.io.InputStream]
, Out: null: 
]

As you can see I don't get the http error which you could.

Upvotes: 3

Related Questions