or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

content-streaming.mdhttp-clients.mdhttp-messages.mdindex.mdmetrics.mdservice-discovery.mdtls-configuration.md

service-discovery.mddocs/

0

# Service Discovery

1

2

ServiceLoader-based SPI interfaces that enable automatic discovery and instantiation of HTTP client implementations on the classpath. This follows standard Java service provider patterns to allow HTTP client implementations to be discovered and loaded dynamically.

3

4

## Capabilities

5

6

### SdkHttpService

7

8

Service Provider Interface for synchronous HTTP client implementations. HTTP client libraries implement this interface and register it via ServiceLoader to be automatically discovered by the AWS SDK.

9

10

```java { .api }

11

/**

12

* Service Provider interface for HTTP implementations. The core uses ServiceLoader

13

* to find appropriate HTTP implementations on the classpath. HTTP implementations

14

* that wish to be discovered by the default HTTP provider chain should implement

15

* this interface and declare that implementation as a service in the

16

* META-INF/services/software.amazon.awssdk.http.SdkHttpService resource.

17

* This interface is simply a factory for SdkHttpClient.Builder.

18

* Implementations must be thread safe.

19

*/

20

@ThreadSafe

21

@SdkPublicApi

22

public interface SdkHttpService {

23

/**

24

* @return An SdkHttpClient.Builder capable of creating SdkHttpClient instances.

25

* This factory should be thread safe.

26

*/

27

SdkHttpClient.Builder createHttpClientBuilder();

28

}

29

```

30

31

**Usage Example:**

32

33

```java

34

// Implementation of SdkHttpService

35

public class MyHttpService implements SdkHttpService {

36

@Override

37

public SdkHttpClient.Builder createHttpClientBuilder() {

38

return new MyHttpClientBuilder();

39

}

40

}

41

42

// Builder implementation

43

public class MyHttpClientBuilder implements SdkHttpClient.Builder<MyHttpClientBuilder> {

44

private Duration connectionTimeout = Duration.ofSeconds(30);

45

private int maxConnections = 50;

46

47

public MyHttpClientBuilder connectionTimeout(Duration timeout) {

48

this.connectionTimeout = timeout;

49

return this;

50

}

51

52

public MyHttpClientBuilder maxConnections(int maxConnections) {

53

this.maxConnections = maxConnections;

54

return this;

55

}

56

57

@Override

58

public SdkHttpClient buildWithDefaults(AttributeMap serviceDefaults) {

59

// Apply service-specific defaults from AttributeMap

60

Duration finalTimeout = serviceDefaults.get(SdkHttpConfigurationOption.CONNECTION_TIMEOUT)

61

.orElse(connectionTimeout);

62

63

return new MyHttpClient(finalTimeout, maxConnections);

64

}

65

}

66

```

67

68

### SdkAsyncHttpService

69

70

Service Provider Interface for asynchronous HTTP client implementations. Similar to SdkHttpService but for async HTTP clients.

71

72

```java { .api }

73

/**

74

* Service Provider interface for asynchronous HTTP implementations.

75

* HTTP implementations that wish to be discovered by the default async HTTP provider

76

* chain should implement this interface and declare that implementation as a service

77

* in the META-INF/services/software.amazon.awssdk.http.async.SdkAsyncHttpService resource.

78

* Implementations must be thread safe.

79

*/

80

@ThreadSafe

81

@SdkPublicApi

82

public interface SdkAsyncHttpService {

83

/**

84

* @return An SdkAsyncHttpClient.Builder capable of creating SdkAsyncHttpClient instances.

85

* This factory should be thread safe.

86

*/

87

SdkAsyncHttpClient.Builder createAsyncHttpClientFactory();

88

}

89

```

90

91

**Usage Example:**

92

93

```java

94

// Implementation of SdkAsyncHttpService

95

public class MyAsyncHttpService implements SdkAsyncHttpService {

96

@Override

97

public SdkAsyncHttpClient.Builder createAsyncHttpClientFactory() {

98

return new MyAsyncHttpClientBuilder();

99

}

100

}

101

102

// Async builder implementation

103

public class MyAsyncHttpClientBuilder implements SdkAsyncHttpClient.Builder<MyAsyncHttpClientBuilder> {

104

private Duration connectionTimeout = Duration.ofSeconds(30);

105

private int maxConcurrency = 100;

106

private boolean http2Enabled = true;

107

108

public MyAsyncHttpClientBuilder connectionTimeout(Duration timeout) {

109

this.connectionTimeout = timeout;

110

return this;

111

}

112

113

public MyAsyncHttpClientBuilder maxConcurrency(int maxConcurrency) {

114

this.maxConcurrency = maxConcurrency;

115

return this;

116

}

117

118

public MyAsyncHttpClientBuilder http2Enabled(boolean enabled) {

119

this.http2Enabled = enabled;

120

return this;

121

}

122

123

@Override

124

public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) {

125

// Apply service-specific defaults

126

Duration finalTimeout = serviceDefaults.get(SdkHttpConfigurationOption.CONNECTION_TIMEOUT)

127

.orElse(connectionTimeout);

128

Integer finalConcurrency = serviceDefaults.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)

129

.orElse(maxConcurrency);

130

131

return new MyAsyncHttpClient(finalTimeout, finalConcurrency, http2Enabled);

132

}

133

}

134

```

135

136

## ServiceLoader Registration

137

138

### META-INF Services Files

139

140

To register your HTTP client implementation for automatic discovery, create the appropriate service files:

141

142

**For Synchronous HTTP Clients:**

143

144

Create file: `src/main/resources/META-INF/services/software.amazon.awssdk.http.SdkHttpService`

145

146

Content:

147

```

148

com.example.MyHttpService

149

```

150

151

**For Asynchronous HTTP Clients:**

152

153

Create file: `src/main/resources/META-INF/services/software.amazon.awssdk.http.async.SdkAsyncHttpService`

154

155

Content:

156

```

157

com.example.MyAsyncHttpService

158

```

159

160

### Multiple Implementations

161

162

You can register multiple implementations in the same service file:

163

164

```

165

com.example.MyHttpService

166

com.example.MyAlternativeHttpService

167

com.example.MySpecializedHttpService

168

```

169

170

The AWS SDK will discover all registered implementations and may use implementation-specific logic to select the most appropriate one.

171

172

## Service Discovery Process

173

174

### Loading Services

175

176

The AWS SDK uses `java.util.ServiceLoader` to discover HTTP client implementations:

177

178

```java

179

// SDK internal code (example of how services are loaded)

180

ServiceLoader<SdkHttpService> httpServices = ServiceLoader.load(SdkHttpService.class);

181

for (SdkHttpService service : httpServices) {

182

SdkHttpClient.Builder builder = service.createHttpClientBuilder();

183

// Use builder to create client with appropriate defaults

184

}

185

```

186

187

### Priority and Selection

188

189

When multiple HTTP client implementations are available:

190

1. The SDK may use internal heuristics to select the "best" implementation

191

2. Implementations can be explicitly selected via configuration

192

3. The order in META-INF services files may influence selection

193

194

### Classpath Requirements

195

196

For service discovery to work:

197

1. Your HTTP client implementation JAR must be on the classpath

198

2. The META-INF/services file must be properly formatted

199

3. The service implementation class must have a public no-argument constructor

200

201

## Configuration Integration

202

203

### Service Defaults

204

205

HTTP client services receive service-specific defaults via `AttributeMap`:

206

207

```java { .api }

208

/**

209

* Configuration options that may be passed to HTTP client builders

210

*/

211

public final class SdkHttpConfigurationOption {

212

// Common configuration options (examples)

213

public static final AttributeMap.Key<Duration> CONNECTION_TIMEOUT;

214

public static final AttributeMap.Key<Duration> SOCKET_TIMEOUT;

215

public static final AttributeMap.Key<Integer> MAX_CONNECTIONS;

216

public static final AttributeMap.Key<Boolean> REAP_IDLE_CONNECTIONS;

217

public static final AttributeMap.Key<Duration> CONNECTION_TIME_TO_LIVE;

218

public static final AttributeMap.Key<Duration> CONNECTION_MAX_IDLE_TIMEOUT;

219

public static final AttributeMap.Key<Boolean> USE_IDLE_CONNECTION_REAPER;

220

public static final AttributeMap.Key<ProxyConfiguration> PROXY_CONFIGURATION;

221

public static final AttributeMap.Key<Boolean> TRUST_ALL_CERTIFICATES;

222

}

223

```

224

225

**Usage in Builder:**

226

227

```java

228

@Override

229

public SdkHttpClient buildWithDefaults(AttributeMap serviceDefaults) {

230

MyHttpClientConfig.Builder configBuilder = MyHttpClientConfig.builder();

231

232

// Apply service defaults

233

serviceDefaults.get(SdkHttpConfigurationOption.CONNECTION_TIMEOUT)

234

.ifPresent(configBuilder::connectionTimeout);

235

236

serviceDefaults.get(SdkHttpConfigurationOption.MAX_CONNECTIONS)

237

.ifPresent(configBuilder::maxConnections);

238

239

serviceDefaults.get(SdkHttpConfigurationOption.PROXY_CONFIGURATION)

240

.ifPresent(configBuilder::proxyConfiguration);

241

242

return new MyHttpClient(configBuilder.build());

243

}

244

```

245

246

## Best Practices

247

248

### Implementation Guidelines

249

250

1. **Thread Safety**: All service implementations must be thread-safe

251

2. **Stateless Design**: Service implementations should be stateless factories

252

3. **Resource Management**: Builders should defer resource allocation until `build()` is called

253

4. **Configuration Validation**: Validate configuration parameters in builders

254

5. **Graceful Degradation**: Handle missing optional configuration gracefully

255

256

### Error Handling

257

258

```java

259

public class RobustHttpService implements SdkHttpService {

260

@Override

261

public SdkHttpClient.Builder createHttpClientBuilder() {

262

try {

263

return new MyHttpClientBuilder();

264

} catch (Exception e) {

265

// Log error but don't fail service loading

266

Logger.getLogger(getClass()).log(Level.WARNING,

267

"Failed to create HTTP client builder", e);

268

throw e; // Re-throw to let ServiceLoader handle

269

}

270

}

271

}

272

```

273

274

### Testing Service Discovery

275

276

```java

277

@Test

278

public void testServiceDiscovery() {

279

ServiceLoader<SdkHttpService> services = ServiceLoader.load(SdkHttpService.class);

280

281

assertThat(services).isNotEmpty();

282

283

for (SdkHttpService service : services) {

284

SdkHttpClient.Builder builder = service.createHttpClientBuilder();

285

assertThat(builder).isNotNull();

286

287

SdkHttpClient client = builder.build();

288

assertThat(client).isNotNull();

289

290

client.close();

291

}

292

}

293

```