1*8a52c783SCole Faust**Design:** Convention, **Status:** [Accepted](README.md) 2*8a52c783SCole Faust 3*8a52c783SCole Faust## Client Configuration 4*8a52c783SCole Faust 5*8a52c783SCole FaustThis page describes the structure and conventions used for client configuration objects. Client configuration objects are any objects used to configure an AWS client builder. 6*8a52c783SCole Faust 7*8a52c783SCole Faust#### Example 8*8a52c783SCole Faust 9*8a52c783SCole FaustThis section walks through an example configuration class structure and describes each of its components at a high level. 10*8a52c783SCole Faust 11*8a52c783SCole Faust```Java 12*8a52c783SCole Faust/** 13*8a52c783SCole Faust * Configuration Description // (1) 14*8a52c783SCole Faust */ 15*8a52c783SCole Faust@Immutable 16*8a52c783SCole Faust@ThreadSafe // (2) 17*8a52c783SCole Faustpublic final class SdkConfiguration // (3) 18*8a52c783SCole Faust implements ToCopyableBuilder<SdkConfiguration.Builder, SdkConfiguration> { // (4) 19*8a52c783SCole Faust private final String option; // (5) 20*8a52c783SCole Faust 21*8a52c783SCole Faust /** 22*8a52c783SCole Faust * @see #builder() // (6) 23*8a52c783SCole Faust */ 24*8a52c783SCole Faust private SdkClientConfiguration(DefaultSdkConfigurationBuilder builder) { 25*8a52c783SCole Faust this.option = builder.option; 26*8a52c783SCole Faust } 27*8a52c783SCole Faust 28*8a52c783SCole Faust public static Builder builder() { 29*8a52c783SCole Faust return new DefaultSdkConfigurationBuilder(); 30*8a52c783SCole Faust } 31*8a52c783SCole Faust 32*8a52c783SCole Faust /** 33*8a52c783SCole Faust * @see #Builder#option(String) // (7) 34*8a52c783SCole Faust */ 35*8a52c783SCole Faust public String option() { 36*8a52c783SCole Faust return this.option; 37*8a52c783SCole Faust } 38*8a52c783SCole Faust 39*8a52c783SCole Faust @Override 40*8a52c783SCole Faust public ClientHttpConfiguration.Builder toBuilder() { 41*8a52c783SCole Faust return builder().option(option); 42*8a52c783SCole Faust } 43*8a52c783SCole Faust 44*8a52c783SCole Faust @NotThreadSafe 45*8a52c783SCole Faust public interface Builder extends CopyableBuilder<Builder, SdkConfiguration> { // (8) 46*8a52c783SCole Faust /** 47*8a52c783SCole Faust * Configuration Option Description // (9) 48*8a52c783SCole Faust */ 49*8a52c783SCole Faust Builder option(String option); 50*8a52c783SCole Faust } 51*8a52c783SCole Faust 52*8a52c783SCole Faust private static final class DefaultSdkConfigurationBuilder implements Builder { // (10) 53*8a52c783SCole Faust private String option; 54*8a52c783SCole Faust 55*8a52c783SCole Faust @Override 56*8a52c783SCole Faust public Builder option(String option) { // (11) 57*8a52c783SCole Faust this.option = option; 58*8a52c783SCole Faust return this; 59*8a52c783SCole Faust } 60*8a52c783SCole Faust 61*8a52c783SCole Faust public void setOption(String option) { // (12) 62*8a52c783SCole Faust this.option = option; 63*8a52c783SCole Faust } 64*8a52c783SCole Faust 65*8a52c783SCole Faust @Override 66*8a52c783SCole Faust public SdkConfiguration build() { 67*8a52c783SCole Faust return new SdkConfiguration(this); 68*8a52c783SCole Faust } 69*8a52c783SCole Faust } 70*8a52c783SCole Faust} 71*8a52c783SCole Faust``` 72*8a52c783SCole Faust 73*8a52c783SCole Faust1. A detailed description should be given of what types of options the user might find in this object. 74*8a52c783SCole Faust2. Configuration objects should be `@Immutable`, and therefore `@ThreadSafe`. 75*8a52c783SCole Faust3. Configuration classes should be defined as `final` to prevent extension. 76*8a52c783SCole Faust4. Configuration classes should extend `ToCopyableBuilder` to ensure they can be converted back to a builder object. 77*8a52c783SCole Faust5. All configuration fields should be defined as `private final` to prevent reassignment. 78*8a52c783SCole Faust6. Configuration constructors should be `private` to enforce creation by the `Builder` and refer curious eyes to the `builder()` method for creating the object. 79*8a52c783SCole Faust7. 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. 80*8a52c783SCole Faust8. Each builder should have its own interface. This allows hiding certain public methods from auto-complete (see below). 81*8a52c783SCole Faust9. A detailed description of each option should be given, including what it does, and **why** a user could want to change its default value. 82*8a52c783SCole Faust10. A `private static final` implementation of the `Builder` interface should be created that is not exposed outside of the scope of the configuration class. 83*8a52c783SCole Faust11. 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. 84*8a52c783SCole Faust12. Each option should have a bean-style setter to allow configuring the object reflectively using `Inspector`-based frameworks, like spring XML. 85*8a52c783SCole Faust 86*8a52c783SCole Faust#### Configuration Fields 87*8a52c783SCole Faust 88*8a52c783SCole FaustThis section details the semantics of configuration fields. 89*8a52c783SCole Faust 90*8a52c783SCole Faust1. Configuration fields must be **immutable**. 91*8a52c783SCole Faust 1. Fields must be marked as `final`. 92*8a52c783SCole Faust 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. 93*8a52c783SCole Faust 3. Mutable types, like `List` and `Set` should be copied in the "set" method to prevent their modification by mutating the original object. 94*8a52c783SCole Faust2. 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. 95*8a52c783SCole Faust3. 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. 96*8a52c783SCole Faust 97*8a52c783SCole FaustSpecial notes for collection types, like `List`, `Set`, and `Map`: 98*8a52c783SCole Faust 99*8a52c783SCole Faust1. Collection type field names must be plural. 100*8a52c783SCole Faust2. There should be two methods provided to modify the collection. 101*8a52c783SCole Faust - method with plural field name which permits adding a collection. It should override any values currently configured in the builder. 102*8a52c783SCole Faust - method that permits adding one item to the collection. 103*8a52c783SCole Faust - If the collection is a list, the method name should use `add` prefix, eg: `addApiName` 104*8a52c783SCole Faust - If the collection is a map, the method name should use `put` prefix, eg: `putHeader` 105*8a52c783SCole Faust 106*8a52c783SCole Faust```Java 107*8a52c783SCole Faustpublic interface Builder { 108*8a52c783SCole Faust 109*8a52c783SCole Faust /** 110*8a52c783SCole Faust * Sets options. 111*8a52c783SCole Faust * 112*8a52c783SCole Faust * <p> 113*8a52c783SCole Faust * This overrides any option values already configured in the builder. 114*8a52c783SCole Faust */ 115*8a52c783SCole Faust Builder options(List<String> options); 116*8a52c783SCole Faust 117*8a52c783SCole Faust /** 118*8a52c783SCole Faust * Add a single option to the collection. 119*8a52c783SCole Faust */ 120*8a52c783SCole Faust Builder addOption(String option); 121*8a52c783SCole Faust 122*8a52c783SCole Faust /** 123*8a52c783SCole Faust * Sets headers to be set on the HTTP request. 124*8a52c783SCole Faust * 125*8a52c783SCole Faust * <p> 126*8a52c783SCole Faust * This overrides any header values already configured in the builder. 127*8a52c783SCole Faust */ 128*8a52c783SCole Faust Builder headers(Map<String, String> headers); 129*8a52c783SCole Faust 130*8a52c783SCole Faust /** 131*8a52c783SCole Faust * Add a single header to be set on the HTTP request. 132*8a52c783SCole Faust * 133*8a52c783SCole Faust * <p> 134*8a52c783SCole Faust * This overrides any values already configured with this header name in the builder. 135*8a52c783SCole Faust */ 136*8a52c783SCole Faust Builder putHeader(String key, String value); 137*8a52c783SCole Faust} 138*8a52c783SCole Faust``` 139