DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • MuleSoft Integrate With ServiceNow
  • Demystifying APIs for Product Managers
  • How to Seamlessly Integrate Data Into NetSuite
  • Writing a Chat With Akka

Trending

  • How to Interpret the Number of Spring ApplicationContexts in Integration Tests
  • WebSockets, gRPC, and GraphQL in the Core
  • Stop Fine-Tuning Everything: A Decision Framework for Model Adaptation
  • Building Production-Ready AI Vector Search in Databricks: Chunking, Embeddings, ML Pipelines, and RAG
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Building a Config-Driven SOAP/REST Integration Layer: One Service, Many Protocols

Building a Config-Driven SOAP/REST Integration Layer: One Service, Many Protocols

Learn how to build protocol-agnostic middleware that supports SOAP and REST integrations with configurable authentication and customer-specific transformations.

By 
Balaji Venkatasubramaniyar user avatar
Balaji Venkatasubramaniyar
·
Jul. 30, 26 · Analysis
Likes (0)
Comment
Save
Tweet
Share
281 Views

Join the DZone community and get the full member experience.

Join For Free

If you've spent time in enterprise integration, you know the pattern: your platform needs to talk to dozens (sometimes hundreds) of external partner systems, and none of them agree on how they want to be talked to. Some expect SOAP envelopes. Others have moved to REST/JSON. Some want Basic Auth, others OAuth, others a bespoke token scheme. Multiply that by data formats that differ subtly — different XML schemas, different field names, different nesting — and you have a classic integration headache.

Back in 2019, I inherited a service in exactly this position. It was a .NET-based SOAP web service acting as a middleware layer: a caller would hit our service, our service would reach out to a customer's web service, retrieve the data, and hand a response back to the original caller. Request and response payloads were transformed using XSLT, with a distinct transformation mapped to each customer's expected schema.

It worked — as long as every customer on the other end was also SOAP-based. The problem was that fewer and fewer of them were. New customers were arriving with REST/JSON-only APIs, and the existing architecture had no way to talk to them without either forking the service or building a parallel one from scratch. Neither option scales well when you're maintaining integrations for a large, growing customer base.

The Goal: One Service, Protocol-Agnostic

Rather than duplicate the service or maintain two codebases, the objective was to make the existing service protocol-agnostic — capable of speaking SOAP to SOAP customers and REST to REST customers, from a single deployable unit, with the protocol decision made dynamically rather than hardcoded per environment or build.

That last point matters. This wasn't a matter of standing up REST and SOAP versions side by side. It was one service where the protocol used to talk to any given downstream customer was determined by a database configuration record tied to that customer. Add a new customer, flip a config flag, and the service knows how to reach them — no redeploy, no branching codebase.

High-Level Flow

  1. Original caller sends a request into the service (as XML/SOAP).
  2. The service looks up the target customer's configuration in the database.
  3. Based on that configuration:
    • SOAP path: request is transformed via XSLT into the customer's expected SOAP/XML schema and sent as-is.
    • REST path: request XML is transformed via XSLT, then serialized into JSON, and sent as a REST call.
  4. The customer's response comes back in whatever format they use (XML or JSON).
  5. If REST/JSON: the response is deserialized and converted back into XML.
  6. The final XML response — normalized regardless of which protocol was used under the hood — is transformed (again via XSLT) and returned to the original caller.

The key design principle: the original caller never needs to know or care what protocol the downstream customer speaks. From their perspective, they send XML and get XML back. All protocol and format negotiation happens inside the service, driven entirely by configuration.

Why XSLT Stayed at the Core

It might seem odd to keep XSLT as the backbone of a service that's now also fluent in JSON, but there's a good reason: XSLT was already doing the heavy lifting of per-customer schema mapping for the SOAP path, and that logic didn't need to be thrown away when REST support was added — it needed to be extended.

For REST customers, the pipeline became:

Plain Text
 
Internal XML → XSLT transform (customer-specific schema) → JSON serialization → REST call


And on the way back:

Plain Text
 
JSON response → XML conversion → XSLT transform (normalize to caller's expected schema) → Response to caller


This meant the substantial investment in customer-specific XSLT mappings carried forward. Instead of writing all-new transformation logic for every REST customer, the same schema-mapping approach was reused, with a JSON conversion step bolted onto either end. It also meant that if a customer migrated from SOAP to REST on their side (which happened more than once), the mapping logic didn't need to be re-engineered from scratch — only the transport and serialization layer changed.

Designing the Auth Layer

Protocol wasn't the only thing that varied by customer — so did authentication. Some customers were still on Basic Authentication. Others required OAuth token flows. A few had proprietary token-based schemes that didn't fit neatly into either category.

Rather than hardcode auth logic per customer (which would have recreated the same maintenance problem the protocol switch was meant to solve), the auth layer was built as a pluggable component, selected — like the protocol — via configuration:

  • Basic authentication –  credentials stored securely and attached to outbound requests per customer config.
  • OAuth – token acquisition and refresh handled transparently before the outbound call, with tokens cached and renewed as needed.
  • Token-based auth – support for customer-issued tokens that didn't follow standard OAuth flows.

The auth layer was designed to sit orthogonally to the protocol layer. A customer's auth scheme and their transport protocol were independent configuration dimensions — a SOAP customer could use OAuth, a REST customer could use Basic Auth, and so on, in any combination. This separation of concerns turned out to be important: protocol and auth requirements rarely change in lockstep when a customer updates their infrastructure, so keeping them decoupled avoided a lot of "well, we changed one thing, but now we have to change three things" maintenance pain.

What This Bought Us

A few concrete benefits came out of this design:

  • Onboarding speed. Adding a new customer — regardless of whether they were SOAP or REST, and regardless of their auth scheme — became a configuration exercise plus a customer-specific XSLT mapping, rather than a new development effort.
  • Single codebase, single deployment. No fork-and-maintain-two-versions problem. Bug fixes, performance improvements, and security patches applied once, benefited every customer.
  • Future-proofing. As more customers migrated from SOAP to REST over time (which, unsurprisingly, kept happening), the service didn't need architectural rework — just configuration changes and new mappings.
  • Consistent caller experience. The original caller's contract never changed. Internal complexity was fully absorbed by the service; external consumers were shielded from it entirely.

Lessons for Anyone Building Similar Middleware

If you're facing a similar integration sprawl problem, a few things I'd emphasize:

  1. Push protocol and format decisions into configuration, not code. The moment you're writing if (customerX) { ... } else if (customerY) { ... } for protocol handling, you've built something that won't scale past a handful of customers.
  2. Don't throw away working transformation logic when you add a new protocol. In this case, the existing XSLT investment for SOAP customers extended cleanly to REST customers with a serialization step added — no need to rebuild schema mapping from scratch.
  3. Decouple auth from transport. They're separate concerns, and customers will mix and match schemes in ways your first design probably didn't anticipate.
  4. Design for the direction things are moving. In this case, that was SOAP-to-REST migration. Building flexibility in ahead of that trend, rather than reacting to each customer's migration individually, saved a lot of one-off engineering work down the line.

The result was a service that started as a single-protocol SOAP integration point and evolved, without a rewrite, into a durable piece of infrastructure that's been reused across multiple products and customer bases well beyond its original scope — which, in hindsight, is the real test of whether an integration architecture was designed well: not whether it solves today's problem, but whether it absorbs tomorrow's without a rewrite.

REST SOAP Protocol (object-oriented programming)

Opinions expressed by DZone contributors are their own.

Related

  • MuleSoft Integrate With ServiceNow
  • Demystifying APIs for Product Managers
  • How to Seamlessly Integrate Data Into NetSuite
  • Writing a Chat With Akka

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook