Skip to content

Commit

Permalink
Merge pull request #1933 from altro3/fix-request-bean
Browse files Browse the repository at this point in the history
Fixed procesing methods with `@RequestBean` and `@Body` parmeters together
  • Loading branch information
altro3 authored Jan 10, 2025
2 parents 145ade8 + 7fe3ea4 commit a0db1ac
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 27 deletions.
2 changes: 1 addition & 1 deletion docs-examples/example-kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ dependencies {
testImplementation(mn.micronaut.http)
testImplementation(mn.reactor)
testImplementation(mnValidation.validation)
testImplementation(mn.kotlin.stdlib.jdk8)
testImplementation(mn.kotlin.stdlib.asProvider())
testImplementation(mn.kotlin.reflect)

testRuntimeOnly(mnTest.junit.jupiter.engine)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
import static io.micronaut.openapi.visitor.SchemaDefinitionUtils.toValueMap;
import static io.micronaut.openapi.visitor.SchemaUtils.COMPONENTS_CALLBACKS_PREFIX;
import static io.micronaut.openapi.visitor.SchemaUtils.TYPE_OBJECT;
import static io.micronaut.openapi.visitor.SchemaUtils.TYPE_STRING;
import static io.micronaut.openapi.visitor.SchemaUtils.appendSchema;
import static io.micronaut.openapi.visitor.SchemaUtils.getOperationOnPathItem;
import static io.micronaut.openapi.visitor.SchemaUtils.isIgnoredHeader;
Expand Down Expand Up @@ -609,9 +610,13 @@ private void processExtraBodyParameters(VisitorContext context, HttpMethod httpM
if (requestBody != null && requestBody.getContent() != null && !extraBodyParameters.isEmpty()) {
requestBody.getContent().forEach((mediaTypeName, mediaType) -> {
var schema = mediaType.getSchema();
if (schema == null) {
schema = setSpecVersion(new Schema<>());
mediaType.setSchema(schema);
if (schema == null || TYPE_STRING.equals(schema.getType())) {
var newSchema = setSpecVersion(new Schema<>());
if (schema != null) {
newSchema.setNullable(schema.getNullable());
}
mediaType.setSchema(newSchema);
schema = newSchema;
}
if (schema.get$ref() != null) {
if (isRequestBodySchemaSet) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2667,4 +2667,86 @@ class MyBean {}
paths."/path/to/controller/user/get2".get.parameters[0].schema
paths."/path/to/controller/user/get2".get.parameters[0].schema.type == "string"
}

void "test @RequestBean and @Body together"() {

buildBeanDefinition('test.MyBean', '''
package test;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.QueryValue;
import io.micronaut.http.annotation.RequestBean;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import jakarta.inject.Singleton;
import java.util.Map;
@Controller
class ControllerExternal {
@Post(value = "/example/{beverageId}/{teaId}{?reqId,maxResultCount}", processes = "application/json;charset=UTF-8")
public HttpResponse<?> bulkCheck(@RequestBean ExampleRequestBean bean, @Nullable @Body String content) {
return HttpResponse.ok();
}
}
@Introspected
@Nullable
class ExampleRequestBean {
@Parameter(hidden = true)
public String path;
@Parameter(hidden = true)
public String method;
@PathVariable
public String beverageId;
@PathVariable
public String teaId;
@Nullable
@QueryValue(defaultValue = "0")
public Integer maxResultCount;
@Nullable
@QueryValue(defaultValue = "1")
public String resultMode;
@Nullable
@QueryValue
public String reqId;
@Nullable
@Parameter(in = ParameterIn.QUERY, description = "defines a map of input fields", required = false)
public Map<String, String> params;
public String payload = null;
}
@Singleton
class MyBean {}
''')
when:
OpenAPI openAPI = Utils.testReference
def op = openAPI.paths."/example/{beverageId}/{teaId}".post

then:
op
op.requestBody
op.requestBody.content."application/json;charset=UTF-8"
op.requestBody.content."application/json;charset=UTF-8".schema
!op.requestBody.content."application/json;charset=UTF-8".schema.type
op.requestBody.content."application/json;charset=UTF-8".schema.nullable
op.requestBody.content."application/json;charset=UTF-8".schema.properties
op.requestBody.content."application/json;charset=UTF-8".schema.properties.payload
op.requestBody.content."application/json;charset=UTF-8".schema.properties.payload.type == 'string'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ package io.micronaut.openapi.visitor

import io.micronaut.openapi.AbstractOpenApiTypeElementSpec
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.Operation
import io.swagger.v3.oas.models.media.ComposedSchema
import io.swagger.v3.oas.models.media.MapSchema
import io.swagger.v3.oas.models.media.Schema
import io.swagger.v3.oas.models.media.StringSchema

class OpenApiMapSchemaSpec extends AbstractOpenApiTypeElementSpec {

Expand All @@ -16,30 +13,16 @@ class OpenApiMapSchemaSpec extends AbstractOpenApiTypeElementSpec {
buildBeanDefinition('test.MyBean', '''
package test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import io.reactivex.Single;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.micronaut.core.annotation.Nullable;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Min;
import java.util.HashMap;
import java.util.Map;
/**
Expand Down Expand Up @@ -112,7 +95,8 @@ class PetController {

then:
map.type == 'object'
map.additionalProperties instanceof StringSchema
map.additionalProperties instanceof Schema
((Schema) map.additionalProperties).type == "string"
complexMap.type == 'object'
complexMap.additionalProperties instanceof Schema
complexMap.additionalProperties['$ref'].contains("Pet")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
interface MyOps {
@Post("/")
String save(@MyAnn java.util.UUID uuid);
String save(@Body @MyAnn java.util.UUID uuid);
}
@Documented
Expand Down
2 changes: 1 addition & 1 deletion test-suite-kotlin-kapt-client-generator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
implementation(mn.jakarta.annotation.api)
implementation(mnValidation.micronaut.validation)
implementation(mnReactor.micronaut.reactor)
implementation(mn.kotlin.stdlib.jdk8)
implementation(mn.kotlin.stdlib.asProvider())
implementation(mn.kotlin.reflect)
// Required when using useAuth=true
implementation(mnSecurity.micronaut.security.oauth2)
Expand Down
2 changes: 1 addition & 1 deletion test-suite-kotlin-kapt-server-generator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies {
implementation(mnValidation.micronaut.validation)
implementation(mnReactor.micronaut.reactor)
implementation(mnData.micronaut.data.runtime)
implementation(mn.kotlin.stdlib.jdk8)
implementation(mn.kotlin.stdlib.asProvider())
implementation(mn.kotlin.reflect)
// Required when using useAuth=true
implementation(mnSecurity.micronaut.security.oauth2)
Expand Down
2 changes: 1 addition & 1 deletion test-suite-kotlin-ksp-client-generator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
implementation(mn.jakarta.annotation.api)
implementation(mnValidation.micronaut.validation)
implementation(mnReactor.micronaut.reactor)
implementation(mn.kotlin.stdlib.jdk8)
implementation(mn.kotlin.stdlib.asProvider())
implementation(mn.kotlin.reflect)
// Required when using useAuth=true
implementation(mnSecurity.micronaut.security.oauth2)
Expand Down
2 changes: 1 addition & 1 deletion test-suite-kotlin-ksp-server-generator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies {
implementation(mnValidation.micronaut.validation)
implementation(mnReactor.micronaut.reactor)
implementation(mnData.micronaut.data.runtime)
implementation(mn.kotlin.stdlib.jdk8)
implementation(mn.kotlin.stdlib.asProvider())
implementation(mn.kotlin.reflect)

runtimeOnly(mnLogging.logback.classic)
Expand Down

0 comments on commit a0db1ac

Please sign in to comment.