Consider Asynchronous SOAPServices as Synchronous using Camel CXF

Martien van den Akker
virtualsciences
Published in
4 min readJun 1, 2022

--

Synchronous SOAP Bubbles

Earlier I wrote about consuming a SOAP Service, and handling SOAP Faults. These stories talk about using Synchronous Webservices.

Message Exchange Patterns

When considering SOAP Webservices, there are several so-called Message Exchange Patterns:

  • Synchronous: this is the most obvious pattern. You do a request, and in the same call, you expect a response from your service. The Service Provider receives the request and processes it, while the Service Consumer waits for the response. The response can be the expected response message, but also one from several possible SOAP Faults. But, a SOAP Fault is in essence a valid SOAP response message.
    In a WSDL you can recognize this in WSDL operations that have both an input and an output message and possibly one or more possible Fault Messages.
  • Asynchronous Fire & Forget: most people consider this as asynchronous. But, we have another asynchronous pattern. Fire & Forget services are invoked, but you won’t get a response. The Service Provider reads the request and immediately responds with an HTTP-200 response code, unless not authenticated, authorized, incorrect URI, etc.
    You can recognize this in a WSDL when there is one port type with an operation that only has an input message.
  • Asynchronous Request & Response: this pattern is actually a combination of two complementary Fire & Forget services. The service invoker calls the service provider in a Fire & Forget way. It immediately gets an OK (HTTP-200) or Not OK (any other HTTP response code) and continues processing. In parallel, the service consumer started an endpoint to listen for the response. This endpoint is provided in a ReplyTo Address WS-Addressing SOAP Header element in the request. Together with a referencing MessageId. When done, the Service Provider can invoke that address with the response. In a RelatesTo element, it can provide the given MessageId to indicate for which request this is an answer.
    You can recognize this in a WSDL when there are two port types, both with an operation that only has an input message. One port type is meant for the Service Consumer, the invoking process. The other is the callback port type used by the Service Provider, to invoke the Service Consumer with the response.

The Problem

If due to a time out or a Connection Refused exception, for instance, the invocation of a synchronous service fails, you won’t get a response. It is quite easily recognized. Handling errors like that is not a real problem with synchronous services.

However, with asynchronous services, it is not that obvious. You won’t get a response. But, you do want to be sure that the remote service is invoked successfully. However, CXF turns out to handle the invocation asynchronously. But, with a connection refused (the remote service is not reachable) CXF logs the exception, but for Camel, it acts as if nothing happened.

I tend to mix up the Camel concepts of Consumer and Producer. But, a Consumer is a component that you reference in a from-activity. An incoming message is wrapped into an Exchange and delivered to the Camel route for processing. A Producer is the component that you reference in a to-activity and can be used to send messages. When I talk about a Camel route that acts as a Service Consumer invoking a WebService, then the route references that WebService as a producer.

You can set an ExceptionHandler as a Consumer (Advanced) property:

Camel ExceptionHandler property

This will not do anything, since we don’t use the reference as a consumer.

The Solution

There is a Producer (Advanced) CXF property that helps in this case:

Producer (Advanced) property — synchronous

As described above, this suggests that by default CXF will handle an service invocation asynchronously. So, the Camel route will process further apart from the CXF call.

But, when this property is set to true the processing is done synchronously.

Now, in case of a Connection Refuse an exception will pop-up in Camel:

Connection Refused exception in Camel during Asynch Service call using CXF

Conclusion

In the case of asynchronous services, you’ll probably set the synchronous property in all or most situations. In other words: handle asynchronous service calls synchronously. Doing so, you’ll be able to catch exceptions that raise during the call.

--

--

Martien van den Akker
virtualsciences

Technology Architect at Oracle Netherlands. The views expressed on this blog are my own and do not necessarily reflect the views of Oracle