Beyond Citation Blog

SOAP integration requires robust error handling and retry logic

SOAP still turns up in academic systems because older repositories, library tools, and vendor platforms often keep it alive at the edges. The hard part is not sending a request. The hard part is deciding what happens when the request fails halfway, times out, or comes back in a shape the client did not expect.

That is where error handling and retry logic matter. In plain terms, error handling means a system notices a problem and responds in a controlled way. Retry logic means it tries again under set rules instead of failing once and giving up.

I keep coming back to this because integration work fails quietly when these pieces are weak. A SOAP service may be slow. A network may drop a packet. A server may answer with a fault, which is SOAP’s own error message. Or the service may be up, but the data in the response may be incomplete. If the client treats every failure the same, it can lose records, repeat actions, or hide the real problem.

The first rule is simple. Not every failure should trigger a retry. Some errors are temporary. Others are telling the caller that the request itself is wrong. A bad date, a missing identifier, or a malformed XML document will not improve on the second try. Retrying those calls only adds noise and load.

SOAP adds another layer because the protocol can return a structured fault instead of a plain transport error. That fault is useful. It can tell the client whether the problem is with the message, the server, or the processing step. Good integration code reads that signal and uses it. It does not flatten every fault into a generic “failed” message.

I find this distinction especially important in systems that unify data from several repositories. Those systems often depend on many small calls. One call might fetch a person record. Another might fetch a holding. Another might pull a full text item. If one of those steps fails, the integration layer has to know whether to pause, retry, or stop. Without that judgment, the whole workflow becomes brittle.

A retry policy works best when it is narrow and explicit. The system needs rules for how many times to try again, how long to wait between tries, and which errors qualify. A short pause can help when the server is busy. A longer pause can help when traffic spikes. But repeated instant retries can make a weak service fail even harder.

Exponential backoff is the common pattern here. Each retry waits longer than the last one. That gives the server breathing room and keeps clients from piling on at the same moment. In practice, this is a small design choice with a large effect. It turns a burst of failure into a controlled recovery path.

Idempotency also matters. That word means the same request can be sent again without causing extra harm. Many read operations are idempotent. Some write operations are not. If a SOAP call creates a record and the response never arrives, the client may not know whether the server already accepted the request. In that case, a blind retry could duplicate the record. Strong error handling asks that question before it retries.

This is why the safest integrations do more than catch exceptions. They classify them. They log them. They preserve the request ID, the timestamp, and the fault code where possible. That record helps later when a librarian, developer, or systems manager has to explain why a harvest missed a set of items or why a sync stalled overnight.

Here is a small example. A repository system calls a SOAP endpoint to update a holdings record. The server is briefly overloaded and returns a timeout. The client waits, then retries after a short delay. The second call succeeds. That is a good retry case. Now change one detail. The request contains an invalid call number format. The server returns a fault that names the bad field. That is not a retry case. The client should surface the fault and stop.

The difference may sound obvious on paper. In real systems, it is easy to blur it. Teams sometimes write retry code for every failure because it feels safer. It is not safer if the same broken message is sent five times. It is not safer if a failed write is repeated without checking whether the first attempt already landed.

I also think error handling needs a human shape. A message that says only “SOAP error” tells too little. A message that says “timeout while calling holdings update endpoint, retry scheduled in 10 seconds” gives a person something to work with. It does not solve the problem by itself, but it shows where the system stands. That is a real form of honesty in integration work.

For Beyond Citation, this matters because unifying data repositories depends on systems that fail in predictable ways. I care less about polished success stories than about the points where an integration can bend without breaking. Robust error handling is one of those points. It keeps a bad response from becoming bad data.

SOAP integration works best when the client expects trouble and plans for it. It needs to tell transport failure from message failure. It needs to retry only the cases that may recover. It needs to leave a clear trail when something goes wrong. With that in place, I can understand what a SOAP connection is doing, and what it is refusing to do, in a way I could not before.

The Source List fits that same habit of care: one digital source worth knowing, one search tip, and one honest limitation. That is the part I trust most, because it names the limits as clearly as the use.