1
votes

When I sent messages in a Camel Context Component to its endpoint, I have to wait for a response message with acknowledgement. If no response is received within timeout time, an exception shall be thrown back to the camel route.

I tried to implement it the following way: I used a multicast to generate a timeout response while the original message is sent to the endpoint. The timeout response is delayed and if no response is received after this timeout, a timeout exception shall be thrown back on the route.

So I have the following route:

private final String internalRespUri = "direct:internal_resp";
private final String internalRespTimeout = "seda:internaltimeout";

@Override
public void configure() {
    SendController send_controller = new SendController();
    TimeoutResponse resp = new TimeoutResponse();

    from(Endpoints.MESSAGE_IN.direct())
                    .errorHandler(noErrorHandler())
                    .routeId(Endpoints.MESSAGE_IN.atsm())
                    .log("Incoming message at segment in")
                    .process(send_controller)
                    .log("Message after send controller")
                    .multicast().parallelProcessing()
                    .log("After wiretap")
                    .to(internalRespTimeout, Endpoints.SEGMENT_OUT.direct());
    from(internalRespTimeout)
                    .errorHandler(noErrorHandler())
                    .routeId(internalRespTimeout)
                    .log("begin response route")
                    .log("timeout response route")
                    .process(resp)
                    .log("modify message to response")
                    .delay(1000)
                    .log("after delay")
                    .to(internalRespUri);
    from(Endpoints.SEGMENT_IN.seda())
                    .routeId(Endpoints.SEGMENT_IN.atsm())
                    .to(internalRespUri);
    from(internalRespUri)
                    .errorHandler(noErrorHandler())
                    .routeId(internalRespUri)
                    .log("after response gathering point")
                    .choice()
                    .when(header(HeaderKeys.TYPE.key()).isEqualTo(UserMessageType.RESP.toString()))
                    .log("process responses")
                    .process(send_controller)
                    .otherwise()
                    .log("no response")
                    .to(Endpoints.MESSAGE_OUT.direct());
}

The problem is that the exception thrown in the SendController is not propagated over the SEDA endpoint internalRespTimeout. If I use a direct endpoint instead it works, but then I have another problem: The delay blocks the route while a received response message from endpoint Endpoints.SEGMENT_IN.seda() may not be transmitted.

Are SEDA endpoint generally not able to propagate exceptions? How can I achieve a solution to my problem?

Thanks, Sven

2

2 Answers

0
votes

I have an idea:

Instead of throwing an exception, I possibly could use transactions for timeout.

Could this work?

0
votes

I am currently not aware of a way to propagate and exception back over a SEDA endpoint in camel. The way the error handling works is based on channels between endpoints. When you use a SEDA endpoint the code will keep processing and not wait for the code since it will keep processing. I am having a bit of trouble understanding what you would like to accomplish, but I will list some similar alternatives you might be able to use.

-The first is to use a route level error handler in your SEDA based route and store the exception using a unique Id that you can lookup later.

-The second is to pass the data into a Java Bean where you have full control of what you are doing and could even consider something like using a Guava's Futures to run the code asynchronously while doing other tasks.

If you can explain what you are trying to accomplish a bit better I might be able to make a clearer suggestion.