DEV Community

Said Olano
Said Olano

Posted on

Metro Web Services: High-Performance SOAP (2026-08-25 18:44)

Metro Web Services: High-Performance SOAP

While REST dominates modern API design, SOAP remains firmly entrenched in enterprise systems—particularly in finance, healthcare, telecommunications, and government sectors where contract-first design, strong typing, and standardized security matter. When you need SOAP on the Java platform, Metro is one of the most capable and performant stacks available.

This post explores what Metro is, how to build high-performance SOAP services with it, and the tuning strategies that separate a sluggish endpoint from a production-grade one.

What Is Metro?

Metro is a comprehensive web services stack that combines two major components:

  • JAX-WS (Jakarta XML Web Services) — the reference implementation of the Java API for XML-based web services.
  • WSIT (Web Services Interoperability Technologies) — support for WS-* standards like WS-Security, WS-ReliableMessaging, WS-AtomicTransaction, and WS-Policy.

Together they provide a full-featured, standards-compliant SOAP platform that interoperates cleanly with .NET (WCF) and other WS-* implementations.

Setting Up a Basic Service

Metro embraces a contract-first or code-first approach. Here's a minimal code-first service endpoint:

import jakarta.jws.WebService;
import jakarta.jws.WebMethod;

@WebService(serviceName = "QuoteService")
public class QuoteService {

    @WebMethod
    public double getQuote(String symbol, int shares) {
        double pricePerShare = lookupPrice(symbol);
        return pricePerShare * shares;
    }

    private double lookupPrice(String symbol) {
        // lookup logic
        return 142.75;
    }
}
Enter fullscreen mode Exit fullscreen mode

Publishing it for a quick test is trivial:

import jakarta.xml.ws.Endpoint;

public class Publisher {
    public static void main(String[] args) {
        Endpoint.publish(
            "http://localhost:8080/quotes",
            new QuoteService()
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Metro auto-generates the WSDL, available at http://localhost:8080/quotes?wsdl.

The Performance Challenge

SOAP's reputation for being "slow" is largely a matter of configuration. The primary bottlenecks are:

  1. XML parsing and serialization overhead
  2. JAXB (un)marshalling of large object graphs
  3. Verbose message payloads consuming bandwidth
  4. Repeated schema validation
  5. Security processing (signing, encryption)

Metro provides mechanisms to address each of these.

Optimization 1: Fast Infoset

The single biggest win for high-throughput scenarios is Fast Infoset (FI)—a binary encoding of XML that dramatically reduces message size and parse time. When both client and server support it, Metro negotiates FI automatically via content negotiation.

Enable it on the client via the FastInfosetFeature:

import com.sun.xml.ws.developer.FastInfosetFeature;

QuoteService port = service.getPort(
    QuoteService.class,
    new FastInfosetFeature()
);
Enter fullscreen mode Exit fullscreen mode

Or through a system property for pessimistic negotiation:

System.setProperty(
    "com.sun.xml.ws.client.ContentNegotiation",
    "optimistic"
);
Enter fullscreen mode Exit fullscreen mode

In benchmarks with document-heavy payloads, Fast Infoset commonly reduces payload size by 40–60% and parse time by a similar margin.

Optimization 2: MTOM for Binary Data

If your service transfers binary content (images, PDFs, documents), base64-encoding it inline bloats messages by ~33%. MTOM (Message Transmission Optimization Mechanism) streams binary attachments alongside the SOAP envelope instead.

import jakarta.xml.ws.soap.MTOM;

@MTOM(threshold = 1024)
@WebService(serviceName = "DocumentService")
public class DocumentService {

    @WebMethod
    public byte[] fetchDocument(String id) {
        return loadBytes(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

The threshold attribute means only payloads above 1 KB use MTOM optimization—small values stay inline to avoid attachment overhead.

Optimization 3: HTTP Persistent Connections and Streaming

Metro's stream-based architecture avoids buffering entire messages in memory where possible. On the client, reuse the Service and port instances—they're expensive to create but safe to reuse across threads when configured properly.

Enable HTTP connection pooling and set timeouts to prevent hung threads:

import jakarta.xml.ws.BindingProvider;
import java.util.Map;

Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("com.sun.xml.ws.connect.timeout", 5000);
ctx.put("com.sun.xml.ws.request.timeout", 10000);
Enter fullscreen mode Exit fullscreen mode

Optimization 4: JAXB Tuning

JAXB marshalling can dominate CPU time for complex types. Key strategies:

  • Reuse JAXBContext — it's thread-safe and costly to build. Metro caches this internally, but custom marshalling code should too.
  • Avoid unnecessary schema validation in production; validate at the boundary during testing instead.
  • Prefer flat, well-designed schemas over deeply nested polymorphic hierarchies.
// Build once, reuse everywhere
private static final JAXBContext CONTEXT =
    JAXBContext.newInstance(Quote.class);
Enter fullscreen mode Exit fullscreen mode

Optimization 5: Secure Without Sacrificing Speed

WS-Security is inherently

Top comments (0)