xref: /aosp_15_r20/external/aws-sdk-java-v2/docs/design/ClientConfiguration.md (revision 8a52c7834d808308836a99fc2a6e0ed8db339086)
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