---
title: Registering implementations with ServiceLoader
---

Some Deephaven Enterprise extension points, such as [custom table access](../../deephaven-database/table-access.md#building-a-custom-table-access),
are discovered at runtime using [`java.util.ServiceLoader`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html), a standard part of the Java platform. This page is a
short primer on registering a provider for one of these extension points; see the [`ServiceLoader`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html)
Javadoc for the full specification.

## The three pieces

- **The service** — the interface or abstract class defined by the feature you're extending.
- **The provider** — your implementation of the service. It must be a `public` class with either a `public` no-argument constructor or (since Java 9) a `public static provider()` method that returns an instance.
- **The provider-configuration file** — a text file telling `ServiceLoader` which of your classes implement which service.

## Registering a provider

Create a file at `META-INF/services/<binary name of the service>`, on the classpath (in a typical Gradle project, that's
`src/main/resources/META-INF/services/...`, so it ends up in your jar). The file is UTF-8 text, with one fully qualified
provider class name per line; blank lines and lines starting with `#` are ignored.

Both the file name and its contents use **binary names**, not source-level names; for a nested type, that means `$`
rather than `.`. For example, a provider for `Database.TableAccessAdapter.Provider` (nested inside `Database`) is
registered with a file named:

```
META-INF/services/io.deephaven.enterprise.database.Database$TableAccessAdapter$Provider
```

This file contains the fully qualified name of your implementation class, e.g., `com.example.MyTableAccessAdapterProvider`.

Misconfiguration (for example, a missing or misnamed file, a provider class that can't be instantiated) fails silently
at runtime rather than at compile time. Confirm that your provider is discovered rather than assuming it is.

## Automating with Google AutoService

Hand-maintaining this file is error-prone: a typo or a forgotten `$` for a nested type breaks discovery. [Google AutoService](https://github.com/google/auto/tree/master/service)
is an annotation processor that generates the file at compile time:

```java
@AutoService(MyService.class)
public final class MyServiceImpl implements MyService {
    // ...
}
```

This is a convenience, not a requirement: `ServiceLoader` has no idea whether a `META-INF/services` file was hand-written
or generated, so use whatever fits your own build tooling, or just write the file by hand as shown above.

## Related documentation

- [Type-specific table access](../../deephaven-database/table-access.md)
- [`ServiceLoader` Javadoc](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/ServiceLoader.html)
