nickotinus
nickotinus

Reputation: 323

Swagger-generated Spring controller recievs NULLs in the body parameter of POST

My API-first swagger client/server transfers POST request body parameter object incorrectly. Spring (4.3.14.RELEASE) server receives nulls in the @RequestBody parameter of the POST request.

The key difference between requests passed over SwaggerUI and over generated typescript client is that SwaggerUI passes object fields as query parameters (Spring handles well), but the generated typescript client over json body (Spring handles nulls).

It seems like autogenerated client sends parameter over body, but the autogenerated server expects parameters in the query.

The swagger fragment:

/project:
    post:
      security:
      - Bearer: []
      tags:
      - Project
      summary: Create new project
      operationId: createProject
      consumes:
      - "application/json"
      - "text/json"
      parameters:
        - name: project
          in: body
          description: project value
          schema:
            $ref: '#/definitions/ProjectRequestDTO'
      responses:
          '200':
              description: Successful response
              schema:
                $ref: '#/definitions/ProjectDTO'
          default:
            description: Bad requst

The resulting Spring MVC method:

ApiOperation(value = "Create new project", nickname = "createHachathon", notes = "", response = ProjectDTO.class, authorizations = {
    @Authorization(value = "Bearer")
}, tags={ "Project", })
@ApiResponses(value = { 
    @ApiResponse(code = 200, message = "Successful response", response = ProjectDTO.class),
    @ApiResponse(code = 200, message = "Bad requst") })
@RequestMapping(value = "/project",
    consumes = { "application/json", "text/json" },
    method = RequestMethod.POST)
default ResponseEntity<ProjectDTO> createHachathon(@ApiParam(value = "project value"  )  @Valid @RequestBody ProjectRequestDTO project) {

I'm sending request from typescript over manually hacked client (title parameter added as demonstration that this parameter will be unmarshalled well):

return this.httpClient.post<ProjectDTO>(`${this.basePath}/project?title=hello`,

The resulting request in the Chrome console: enter image description here

Unfortunatelly Spring receives only the value which were passed over query parameter but not over request body:

enter image description here

Plese help me to make my swagger-codegen-maven-plugin 2.3.1 produce client/server swagger API which will transfer data transparently.

Upvotes: 4

Views: 4140

Answers (3)

IphoneVore
IphoneVore

Reputation: 13

Sometimes, it seems stupid but I had issue with my request body, it was null into the controller. What I changed, the import, I was using the swagger.requestBody package instead of the springframeWork.request import.

Upvotes: -1

Sunil Kumar
Sunil Kumar

Reputation: 320

Sorry, may be late answer. maybe helps someone. I was hitting same issue while using spring boot+Swagger2. My REST API with POST method :

public void getAllNames(@ApiParam(name = "Get All names Request",
            value = "Request to get all names",
            required = true) @RequestBody BasicCredentialsJsonObject requestJson)

I had to introduce Json annotations(JsonPropertyOrder, JsonProperty) on below class to get going. I was hitting issue till I made this changes.

BasicCredentialsJsonObject :

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
    "password",
    "username"
})
public class BasicCredentialsJsonObject {

    @JsonProperty("username")
    private String username;

    @JsonProperty("password")
    private String password;
}

Upvotes: 0

nickotinus
nickotinus

Reputation: 323

The root cause is that Spring ignores method parameter annotations of the implemented Interface, so the @RequestBody was ignored in my Controller implementation.

The <delegatePattern>true</delegatePattern> parameter inside <configOptions> section of swagger-codegen-maven-plugin resolved this problem.

This parameter makes Swagger generate invocation of delegate method inside default implementation of API Interface methods. My Controller implements this method and overrides this delegate mathods, so the source method annotations are in safe.

Upvotes: 3

Related Questions