Skip to content

Commit 8e584ce

Browse files
authored
Merge pull request #385 from mirror-kt/feature/enhance-204
returns Unit when any successful response not exists
2 parents 3238070 + 2f0bea5 commit 8e584ce

File tree

5 files changed

+93
-10
lines changed

5 files changed

+93
-10
lines changed

src/main/kotlin/com/cjbooms/fabrikt/generators/GeneratorUtils.kt

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ object GeneratorUtils {
133133

134134
fun Operation.hasMultipleContentMediaTypes(): Boolean? = this.firstResponse()?.hasMultipleContentMediaTypes()
135135

136+
fun Operation.hasAnySuccessResponseSchemas(): Boolean = getBodySuccessResponses().isNotEmpty()
137+
136138
fun Operation.hasMultipleSuccessResponseSchemas(): Boolean =
137139
getBodySuccessResponses().flatMap { it.contentMediaTypes.values }.map { it.schema.name }.distinct().size > 1
138140

src/main/kotlin/com/cjbooms/fabrikt/generators/client/ClientGeneratorUtils.kt

+13-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.cjbooms.fabrikt.configurations.Packages
44
import com.cjbooms.fabrikt.generators.GeneratorUtils
55
import com.cjbooms.fabrikt.generators.GeneratorUtils.getPrimaryContentMediaType
66
import com.cjbooms.fabrikt.generators.GeneratorUtils.getPrimaryContentMediaTypeKey
7+
import com.cjbooms.fabrikt.generators.GeneratorUtils.hasAnySuccessResponseSchemas
78
import com.cjbooms.fabrikt.generators.GeneratorUtils.hasMultipleContentMediaTypes
89
import com.cjbooms.fabrikt.generators.GeneratorUtils.hasMultipleSuccessResponseSchemas
910
import com.cjbooms.fabrikt.generators.GeneratorUtils.toClassName
@@ -37,16 +38,18 @@ object ClientGeneratorUtils {
3738
* If no response body is found, Unit is returned.
3839
*/
3940
fun Operation.getReturnType(packages: Packages): TypeName {
40-
return if (hasMultipleSuccessResponseSchemas()) {
41-
JsonNode::class.asTypeName()
42-
} else {
43-
this.getPrimaryContentMediaType()?.let {
44-
toModelType(
45-
packages.base,
46-
KotlinTypeInfo.from(it.value.schema)
47-
)
48-
} ?: Unit::class.asTypeName()
49-
}
41+
return if(!hasAnySuccessResponseSchemas()){
42+
Unit::class.asTypeName()
43+
} else if (hasMultipleSuccessResponseSchemas()) {
44+
JsonNode::class.asTypeName()
45+
} else {
46+
this.getPrimaryContentMediaType()?.let {
47+
toModelType(
48+
packages.base,
49+
KotlinTypeInfo.from(it.value.schema)
50+
)
51+
} ?: Unit::class.asTypeName()
52+
}
5053
}
5154

5255
fun Operation.toClientReturnType(packages: Packages): TypeName {

src/test/resources/examples/okHttpClient/api.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ paths:
124124
204:
125125
description: "Operation successful"
126126

127+
/example-path-4/only-failure-response:
128+
post:
129+
summary: "POST example path 4"
130+
responses:
131+
204:
132+
description: "No Content"
133+
400:
134+
content:
135+
application/json:
136+
schema:
137+
$ref: '#/components/schemas/Failure'
138+
description: Bad Request
139+
127140
components:
128141
parameters:
129142
PathParam:

src/test/resources/examples/okHttpClient/client/ApiClient.kt

+35
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,38 @@ public class ExamplePath3SubresourceClient(
263263
return request.execute(client, objectMapper, jacksonTypeRef())
264264
}
265265
}
266+
267+
@Suppress("unused")
268+
public class ExamplePath4OnlyFailureResponseClient(
269+
private val objectMapper: ObjectMapper,
270+
private val baseUrl: String,
271+
private val client: OkHttpClient,
272+
) {
273+
/**
274+
* POST example path 4
275+
*/
276+
@Throws(ApiException::class)
277+
public fun postExamplePath4OnlyFailureResponse(
278+
additionalHeaders: Map<String, String> =
279+
emptyMap(),
280+
additionalQueryParameters: Map<String, String> = emptyMap(),
281+
): ApiResponse<Unit> {
282+
val httpUrl: HttpUrl = "$baseUrl/example-path-4/only-failure-response"
283+
.toHttpUrl()
284+
.newBuilder()
285+
.also { builder -> additionalQueryParameters.forEach { builder.queryParam(it.key, it.value) } }
286+
.build()
287+
288+
val headerBuilder = Headers.Builder()
289+
additionalHeaders.forEach { headerBuilder.header(it.key, it.value) }
290+
val httpHeaders: Headers = headerBuilder.build()
291+
292+
val request: Request = Request.Builder()
293+
.url(httpUrl)
294+
.headers(httpHeaders)
295+
.post(ByteArray(0).toRequestBody())
296+
.build()
297+
298+
return request.execute(client, objectMapper, jacksonTypeRef())
299+
}
300+
}

src/test/resources/examples/okHttpClient/client/ApiService.kt

+30
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,33 @@ public class ExamplePath3SubresourceService(
145145
apiClient.putExamplePath3PathParamSubresource(firstModel, pathParam, ifMatch, csvListQueryParam, additionalHeaders)
146146
}
147147
}
148+
149+
/**
150+
* The circuit breaker registry should have the proper configuration to correctly action on circuit
151+
* breaker transitions based on the client exceptions [ApiClientException], [ApiServerException] and
152+
* [IOException].
153+
*
154+
* @see ApiClientException
155+
* @see ApiServerException
156+
*/
157+
@Suppress("unused")
158+
public class ExamplePath4OnlyFailureResponseService(
159+
private val circuitBreakerRegistry: CircuitBreakerRegistry,
160+
objectMapper: ObjectMapper,
161+
baseUrl: String,
162+
client: OkHttpClient,
163+
) {
164+
public var circuitBreakerName: String = "examplePath4OnlyFailureResponseClient"
165+
166+
private val apiClient: ExamplePath4OnlyFailureResponseClient =
167+
ExamplePath4OnlyFailureResponseClient(objectMapper, baseUrl, client)
168+
169+
@Throws(ApiException::class)
170+
public fun postExamplePath4OnlyFailureResponse(
171+
additionalHeaders: Map<String, String> =
172+
emptyMap(),
173+
): ApiResponse<Unit> =
174+
withCircuitBreaker(circuitBreakerRegistry, circuitBreakerName) {
175+
apiClient.postExamplePath4OnlyFailureResponse(additionalHeaders)
176+
}
177+
}

0 commit comments

Comments
 (0)