Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java ServiceLoader: treat provider discovery as fallible startup work

Last updated: 5 Oct 20265 min read
tutorial
AdvancedBy AITrove Editorial

ServiceLoader locates implementations registered for a service interface. Iteration can fail when provider metadata, construction, or linkage is broken.

Operational contract

The loader selects one provider during startup and converts ServiceConfigurationError into a clear configuration failure. It does not silently skip a broken provider, because doing so could change the selected receipt codec. The classpath registration file or named-module provides directive belongs in the deployment artifact; a service interface alone does not register implementations. ServiceLoader lazily discovers and instantiates providers, so moving iteration into a request path can turn a packaging problem into a customer-visible failure. If multiple providers are legal, selection needs an explicit stable policy.

Failure case

A deployment lists a provider whose constructor throws. The service fails initialization instead of pretending no codec exists and processing receipts with an unintended fallback.

Java code

Java
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;

public class ReceiptCodecDiscovery {
    public interface ReceiptCodec { byte[] encode(String receipt); }

    public static ReceiptCodec requiredProvider() {
        try {
            Iterator<ReceiptCodec> providers = ServiceLoader.load(ReceiptCodec.class).iterator();
            if (!providers.hasNext())
                throw new IllegalStateException("No receipt codec registered");
            ReceiptCodec selected = providers.next();
            if (providers.hasNext())
                throw new IllegalStateException("Multiple receipt codecs registered");
            return selected;
        } catch (ServiceConfigurationError broken) {
            throw new IllegalStateException("Receipt codec registration is invalid", broken);
        }
    }
}

Performance and ownership cost

Discovery scans P registered providers and instantiates at least those visited, costing O(P) startup time and provider-dependent memory; this sample visits enough to reject a second provider. Holding the selected provider afterward makes per-request discovery cost O(0).

Common Mistakes

  • Do not expect an interface declaration to register a provider.
  • Do not swallow ServiceConfigurationError and select a different provider without policy.
  • Do not repeat lazy discovery on every request when providers are deployment configuration.

Connected lessons

java
runtime adapters
service-loader-provider-failure
Storage details