blob: 58c1ef036ebe7a777cea1b8374305df7bfc9dccb [file] [log] [blame] [view] [edit]
**Design:** Convention, **Status:** [Accepted](README.md)
## Client Configuration
This page describes the structure and conventions used for client configuration objects. Client configuration objects are any objects used to configure an AWS client builder.
#### Example
This section walks through an example configuration class structure and describes each of its components at a high level.
```Java
/**
* Configuration Description // (1)
*/
@Immutable
@ThreadSafe // (2)
public final class SdkConfiguration // (3)
implements ToCopyableBuilder<SdkConfiguration.Builder, SdkConfiguration> { // (4)
private final String option; // (5)
/**
* @see #builder() // (6)
*/
private SdkClientConfiguration(DefaultSdkConfigurationBuilder builder) {
this.option = builder.option;
}
public static Builder builder() {
return new DefaultSdkConfigurationBuilder();
}
/**
* @see #Builder#option(String) // (7)
*/
public String option() {
return this.option;
}
@Override
public ClientHttpConfiguration.Builder toBuilder() {
return builder().option(option);
}
@NotThreadSafe
public interface Builder extends CopyableBuilder<Builder, SdkConfiguration> { // (8)
/**
* Configuration Option Description // (9)
*/
Builder option(String option);
}
private static final class DefaultSdkConfigurationBuilder implements Builder { // (10)
private String option;
@Override
public Builder option(String option) { // (11)
this.option = option;
return this;
}
public void setOption(String option) { // (12)
this.option = option;
}
@Override
public SdkConfiguration build() {
return new SdkConfiguration(this);
}
}
}
```
1. A detailed description should be given of what types of options the user might find in this object.
2. Configuration objects should be `@Immutable`, and therefore `@ThreadSafe`.
3. Configuration classes should be defined as `final` to prevent extension.
4. Configuration classes should extend `ToCopyableBuilder` to ensure they can be converted back to a builder object.
5. All configuration fields should be defined as `private final` to prevent reassignment.
6. Configuration constructors should be `private` to enforce creation by the `Builder` and refer curious eyes to the `builder()` method for creating the object.
7. One "get" method should be created for each configuration field. This method's name should exactly match the name of the field it is retrieving.
8. Each builder should have its own interface. This allows hiding certain public methods from auto-complete (see below).
9. A detailed description of each option should be given, including what it does, and **why** a user could want to change its default value.
10. A `private static final` implementation of the `Builder` interface should be created that is not exposed outside of the scope of the configuration class.
11. One "set" method should be created for each option to mutate the value in this builder. This method's name should exactly match the name of the field it is setting.
12. Each option should have a bean-style setter to allow configuring the object reflectively using `Inspector`-based frameworks, like spring XML.
#### Configuration Fields
This section details the semantics of configuration fields.
1. Configuration fields must be **immutable**.
1. Fields must be marked as `final`.
2. Mutable types, like `List` and `Set` should be wrapped in a type that prevents their modification (eg. `Collections.unmodifiableList`) when referenced through the "get" method.
3. Mutable types, like `List` and `Set` should be copied in the "set" method to prevent their modification by mutating the original object.
2. Configuration fields must be **reference types**. Primitive types like `boolean` or `int` should not be used because they can not convey the absence of configuration.
3. Configuration field names should **not start with a verb** (eg. `config.enableRedirect()` should instead be `config.redirectEnabled()`). This is to avoid confusing their "get" methods for a mutating action.
Special notes for collection types, like `List`, `Set`, and `Map`:
1. Collection type field names must be plural.
2. There should be two methods provided to modify the collection.
- method with plural field name which permits adding a collection. It should override any values currently configured in the builder.
- method that permits adding one item to the collection.
- If the collection is a list, the method name should use `add` prefix, eg: `addApiName`
- If the collection is a map, the method name should use `put` prefix, eg: `putHeader`
```Java
public interface Builder {
/**
* Sets options.
*
* <p>
* This overrides any option values already configured in the builder.
*/
Builder options(List<String> options);
/**
* Add a single option to the collection.
*/
Builder addOption(String option);
/**
* Sets headers to be set on the HTTP request.
*
* <p>
* This overrides any header values already configured in the builder.
*/
Builder headers(Map<String, String> headers);
/**
* Add a single header to be set on the HTTP request.
*
* <p>
* This overrides any values already configured with this header name in the builder.
*/
Builder putHeader(String key, String value);
}
```