You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/languages/java/methodology-java.mdx
+92-70Lines changed: 92 additions & 70 deletions
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ The Speakeasy Java SDK is designed to be easy to use and debug. This includes ge
14
14
The core features of the SDK include:
15
15
16
16
-**Type-safety**: Strong typing is used extensively so that problems are seen at compile time, not runtime.
17
-
-**Null-safety**: Primitive types are used where possible, improving **compile-time** null safety. For non-required and nullable fields, the `java.util.Optional` and `JSONNullable` classes are used. Passing Java `null` arguments will provoke an exception.
17
+
-**Null-safety**: Primitive types are used where possible, improving **compile-time** null safety. For non-required and nullable fields, the `java.util.Optional` and `JSONNullable` classes are used. Passing Java `null` arguments will provoke an exception.
18
18
-**Builders and method chaining for all SDK objects.** For example, to create a `Person` object:
19
19
20
20
```java
@@ -28,19 +28,19 @@ Person person = Person.builder()
28
28
- All-field constructors are available for most SDK objects, so a user can get a compile-time indication of changes to the OpenAPI document if required.
29
29
-**Readability**: Appropriately formatted method chaining is more understandable and maintainable.
30
30
-**Discoverability**: Method chaining and favorable naming strategies make life easier. For example, to build a `Person` object, you call `Person.builder()` and **not**`new Builders.PersonFactory()`.
31
-
-**Convenient overloads in builders.** For example, a `long` can be passed directly when the underlying field is `Optional<Long>`.
31
+
-**Convenient overloads in builders.** For example, a `long` can be passed directly when the underlying field is `Optional<Long>`.
32
32
- The `java.util.Optional` class is used for non-required arguments.
33
-
- The `JsonNullable` class is used for nullable arguments.
34
-
- The Java platform `OffsetDateTime` and `LocalDate` types are used for `date-time` and `date`.
33
+
- The `JsonNullable` class is used for nullable arguments.
34
+
- The Java platform `OffsetDateTime` and `LocalDate` types are used for `date-time` and `date`.
35
35
- A `utils` package provides shared code used by generated classes, making the generated code easier to follow.
36
36
- Authentication support for OAuth flows and other standard security mechanisms.
37
37
- Custom enum types using string or integer values.
38
-
- Pagination support, including the option to return `java.util.Stream` so that paging is auto-handled.
38
+
- Pagination support, including the option to return `java.util.Stream` so that paging is auto-handled.
39
39
- Well-formatted source code to make debugging easier.
40
40
41
41
The SDK includes minimal dependencies. It requires:
42
42
43
-
-[Jackson Library](https://github.com/FasterXML/jackson) to serialize and deserialize data over the wire.
43
+
-[Jackson Library](https://github.com/FasterXML/jackson) to serialize and deserialize data over the wire.
44
44
-[Apache HttpClient](https://hc.apache.org/httpcomponents-client-4.5.x/index.html) to make HTTP requests.
45
45
-[Jayway JsonPath](https://github.com/json-path/JsonPath) to support JSON path expressions in Speakeasy metadata fields in OpenAPI documents.
46
46
@@ -61,7 +61,7 @@ The SDK includes minimal dependencies. It requires:
61
61
| | | └-- ...
62
62
| | └-- shared # package for shared component models
63
63
| | └-- ...
64
-
| └-- utils # package for shared utility classes
64
+
| └-- utils # package for shared utility classes
65
65
| └-- ...
66
66
|-- docs # Markdown files for the SDK's documentation
67
67
|-- gradlew # Gradle shellscript to build/install the SDK
@@ -71,6 +71,7 @@ The SDK includes minimal dependencies. It requires:
71
71
| └-- ... # other Gradle-related files
72
72
└-- ...
73
73
```
74
+
74
75
## Build customization
75
76
76
77
The `build.gradle` file should not be edited because generation updates will overwrite changes. However, customization of `build.gradle` is possible:
@@ -82,34 +83,33 @@ The `build.gradle` file should not be edited because generation updates will ove
82
83
java:
83
84
version: 0.2.0
84
85
artifactID: openapi
85
-
...
86
-
additionalPlugins:
87
-
- 'id("java")'
86
+
---
87
+
additionalPlugins:
88
+
- 'id("java")'
88
89
```
89
90
90
91
Dependencies can be customized in two ways:
91
92
92
93
- You can add a `dependencies` block to `build-extras.gradle`. Note that with standard Gradle techniques, you can exclude dependencies, exclude transitive dependencies, and modify dependencies in `build-extras.gradle`.
93
94
94
-
- You can use the `additionalDependencies` property in `gen.yaml`. For example, the fragment below overrides the `jackson-databind` and adds `commons-compress`:
95
+
- You can use the `additionalDependencies` property in `gen.yaml`. For example, the fragment below overrides the `jackson-databind` and adds `commons-compress`:
@@ -126,7 +126,7 @@ This gives developers using your Java SDK the flexibility to set up proxies, coo
126
126
127
127
## Serialization and deserialization
128
128
129
-
Low-level customizations like request and response hooks or `HTTPClient`-based interceptions may require the serialization and deserialization of generated objects to and from JSON.
129
+
Low-level customizations like request and response hooks or `HTTPClient`-based interceptions may require the serialization and deserialization of generated objects to and from JSON.
130
130
131
131
You **must** use the generated custom Jackson `ObjectMapper` for these actions. The `ObjectMapper` is available as a Singleton in the generated `utils` package via `JSON.getMapper()`.
132
132
@@ -147,47 +147,47 @@ Where possible, the Java SDK uses native types from the language and uses primit
147
147
- `double`(or `java.lang.Double`)
148
148
- `boolean`(or `java.lang.Boolean`)
149
149
150
-
151
150
### Unlimited-precision numerics
152
151
153
152
Using high-precision decimal or integer types is crucial in certain applications, such as in code that manipulates monetary amounts and in situations where overflow, underflow, or truncation caused by precision loss can lead to significant incidents.
154
153
155
154
To mark a field as an unlimited-precision integer, you can use either an integer:
156
155
157
156
```yaml
158
-
type: integer
159
-
format: bigint
160
-
```
157
+
type: integer
158
+
format: bigint
159
+
```
161
160
162
161
Or a string:
163
162
164
163
```yaml
165
-
type: string
166
-
format: bigint
164
+
type: string
165
+
format: bigint
167
166
```
168
167
169
168
The above types are mapped to `java.math.BigInteger` in the generated SDK. Object builders have convenient overloads that allow for passing integer values directly without wrapping them in `BigInteger`.
170
169
171
170
Similarly, for an unlimited-precision decimal, you can use either a number:
172
171
173
172
```yaml
174
-
type: number
175
-
format: decimal
173
+
type: number
174
+
format: decimal
176
175
```
177
176
178
-
Or a string:
177
+
Or a string:
179
178
180
179
```yaml
181
-
type: string
182
-
format: decimal
180
+
type: string
181
+
format: decimal
183
182
```
183
+
184
184
The above types are mapped to `java.math.BigDecimal` in the generated SDK and object builders have convenient overloads that allow passing float and double values directly without wrapping them in `BigDecimal`.
185
185
186
186
**Note:** SDKs in other languages may choose to map to native high-precision types rather than unlimited-precision types. Check the documentation of the language you are interested in.
187
187
188
188
### Union types
189
189
190
-
Support for polymorphic types is critical to most production applications. In OpenAPI, these types are defined using the `oneOf` keyword.
190
+
Support for polymorphic types is critical to most production applications. In OpenAPI, these types are defined using the `oneOf` keyword.
191
191
192
192
#### Non-discriminated `oneOf`
193
193
@@ -196,10 +196,10 @@ The subtypes of a non-discriminated `oneOf` type may be objects or primitives, s
196
196
Consider this OpenAPI fragment:
197
197
198
198
```yaml
199
-
Pet:
200
-
oneOf:
201
-
- $ref: "#/components/schemas/Cat"
202
-
- $ref: "#/components/schemas/Dog"
199
+
Pet:
200
+
oneOf:
201
+
- $ref: "#/components/schemas/Cat"
202
+
- $ref: "#/components/schemas/Dog"
203
203
```
204
204
205
205
Here's how a `Pet` is created in Java code:
@@ -209,8 +209,8 @@ Cat cat = ...;
209
209
Dog dog = ...;
210
210
211
211
// Pet.of only accepts Cat or Dog types, and throws if passed null.
212
-
Pet pet = Pet.of(cat);
213
-
```
212
+
Pet pet = Pet.of(cat);
213
+
```
214
214
215
215
Here is how a `Pet` is inspected:
216
216
@@ -245,19 +245,19 @@ if (pet.value() instanceof Cat cat) {
245
245
In some circumstances, the `of` static factory method of a `oneOf` class may need to be differentiated by a suffix to avoid type erasure. For example, you would need to use a suffix to differentiate the two array subtypes in the following fragment:
246
246
247
247
```yaml
248
-
Info:
249
-
oneOf:
250
-
- type: array
251
-
items:
252
-
type: integer
253
-
x-speakeasy-name-override: counts
254
-
- type: array
255
-
items:
256
-
type: string
257
-
x-speakeasy-name-override: descriptions
248
+
Info:
249
+
oneOf:
250
+
- type: array
251
+
items:
252
+
type: integer
253
+
x-speakeasy-name-override: counts
254
+
- type: array
255
+
items:
256
+
type: string
257
+
x-speakeasy-name-override: descriptions
258
258
```
259
259
260
-
Without accounting for this scenario, the static factory methods `Info.of(List<Long>)` and `Info.of(List<String>)` would conflict due to generic type erasure by the Java compiler and cause a compile error in the generated code. Code generation detects this scenario and adds an `of` method suffix. For the fragment above, the generated static factory methods are the following:
260
+
Without accounting for this scenario, the static factory methods `Info.of(List<Long>)` and `Info.of(List<String>)` would conflict due to generic type erasure by the Java compiler and cause a compile error in the generated code. Code generation detects this scenario and adds an `of` method suffix. For the fragment above, the generated static factory methods are the following:
261
261
262
262
- `ofCounts(List<Long>)`
263
263
- `ofDescriptions(List<String>)`
@@ -276,15 +276,15 @@ The subtypes of a discriminated `oneOf` type must be objects, so an interface-ba
276
276
Consider this OpenAPI fragment:
277
277
278
278
```yaml
279
-
Pet:
280
-
oneOf:
281
-
- $ref: "#/components/schemas/Cat"
282
-
- $ref: "#/components/schemas/Dog"
283
-
discriminator:
284
-
propertyName: petType
285
-
mapping:
286
-
cat: '#/components/schemas/Cat'
287
-
dog: '#/components/schemas/Dog'
279
+
Pet:
280
+
oneOf:
281
+
- $ref: "#/components/schemas/Cat"
282
+
- $ref: "#/components/schemas/Dog"
283
+
discriminator:
284
+
propertyName: petType
285
+
mapping:
286
+
cat: "#/components/schemas/Cat"
287
+
dog: "#/components/schemas/Dog"
288
288
```
289
289
290
290
Here's how a `Pet` is created in Java code:
@@ -294,7 +294,7 @@ Pet cat = Cat.builder().name("Moggie").build();
294
294
Pet dog = Dog.builder().name("Fido").build();
295
295
```
296
296
297
-
`Pet`is a Java interface with a single `petType()` method, and `Cat` and `Dog` both implement that interface.
297
+
`Pet`is a Java interface with a single `petType()` method, and `Cat` and `Dog` both implement that interface.
298
298
299
299
The `discriminator` property should be marked as required in the `oneOf` subtypes. Considering the discriminator has a constant value in each `oneOf` subtype, it also makes sense to use a Singleton `enum` or a `const` for the `discriminator` property type.
300
300
@@ -390,15 +390,15 @@ Be aware that migrating a closed enum to an open enum may bring about compile er
390
390
391
391
## Parameters
392
392
393
-
If parameters are defined in the OpenAPI document, Speakeasy will generate methods with parameters as part of the method call itself rather than as part of a separate request object.
393
+
If parameters are defined in the OpenAPI document, Speakeasy will generate methods with parameters as part of the method call itself rather than as part of a separate request object.
394
394
395
395
The number of parameters defined should not exceed the `maxMethodParams` value configured in the `gen.yaml` file. If they do or the `maxMethodParams` value is absent or set to `0`, all generated methods require a single request object that contains all the parameters that may be used to call an endpoint in the API.
396
396
397
397
## Default values
398
398
399
-
The `default` keyword in the OpenAPI specification allows a user to omit a field or parameter and it will be set with a given default value.
399
+
The `default` keyword in the OpenAPI specification allows a user to omit a field or parameter and it will be set with a given default value.
400
400
401
-
Default values are represented in the Java SDK with `java.util.Optional` wrappers. Passing `Optional.empty()`, or if you're using a builder, not setting the field or parameter, will mean that the default value in the OpenAPI document is used.
401
+
Default values are represented in the Java SDK with `java.util.Optional` wrappers. Passing `Optional.empty()`, or if you're using a builder, not setting the field or parameter, will mean that the default value in the OpenAPI document is used.
402
402
403
403
Bear in mind that it's lazy-loaded (only loaded once) and that if the default value is not valid for the given type, an `IllegalArgumentException` will be thrown. For example, if `default: abc` is specified for `type: integer`, the exception is thrown.
404
404
@@ -416,21 +416,45 @@ The `const` keyword in the OpenAPI specification ensures that a field is essenti
416
416
To handle errors in the Java SDK, you need to check the status code of the response. If it is an error response, the `error` field of the response will contain the decoded error value.
417
417
418
418
<Callout title="Coming Soon" type="info">
419
-
Support for throwing unsuccessful status codes as exceptions is coming soon.
419
+
Support for throwing unsuccessful status codes as exceptions is coming soon.
420
420
</Callout>
421
421
422
422
## Pagination and `java.util.Stream`
423
423
424
-
Enabling pagination for an operation in your API is described [here](/docs/customize/runtime/pagination).
424
+
Enabling pagination for an operation in your API is described [here](/docs/customize/runtime/pagination).
425
425
426
-
If pagination is enabled for an operation, you have the option to run `.call()`, `.callAsStream()`, or `.callAsStreamUnwrapped()` when using the operation builder.
426
+
If pagination is enabled for an operation, you have the option to run `.call()`, `.callAsIterable()`, `.callAsStream()`, or `.callAsStreamUnwrapped()` when using the operation builder.
427
427
428
-
- The `.call()` method will return the first page, and you will have to repeatedly check for the existence of another page and retrieve it.
428
+
- The `.call()` method will return the first page, and you will have to repeatedly check for the existence of another page and retrieve it.
429
+
- The `.callAsIterable()` method returns an `Iterable<>` that can be used with for-each iteration style. Page retrieval is handled automatically as the iteration progresses.
429
430
- The `callAsStream()` method returns a `java.util.Stream` of the pages, allowing you to use the convenient `java.util.Stream` API. Retrieving more pages when required and available is handled automatically.
430
431
- The `callAsStreamUnwrapped()` method returns a `java.util.Stream` of the concatenated items in the lists on each page. Concatenation and page retrieval are handled automatically.
The `callAsStream` and `callAsStreamUnwrapped` methods throw an exception if a response page has a status code of 300 or higher. If you require a different behavior, use the `call` method to manually retrieve each page.
468
-
469
491
## Server-sent events
470
492
471
-
General Speakeasy support for server-sent events (SSE) is described [here](/docs/customize-sdks/server-sent-events).
493
+
General Speakeasy support for server-sent events (SSE) is described [here](/docs/customize-sdks/server-sent-events).
472
494
473
495
When an operation response has a content type of `text/event-stream`, the generated response class will have an `events()` method.
The Java SDK will include a [user agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) string in all requests that can be used to track SDK usage among broader API usage. The format is as follows:
528
+
The Java SDK will include a [user agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) string in all requests that can be used to track SDK usage among broader API usage. The format is as follows:
0 commit comments