Search code examples
springspring-rest

RequestBody and camel case request parameters


I have an endpoint with a request body:

 @PostMapping("/v1/message")
  @PreAuthorize("#oauth2.isAnyClientId(@authorizeConfig.getIds())")
  public void receive(
      @RequestBody @NotNull @Valid final Message message,
      @RequestHeader final HttpHeaders headers) {
    ...
  }

The Message class has several parameters:

@Builder
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@JsonPropertyOrder(alphabetic = true)
public class Message {

  @NotBlank(message = "tenant is empty")
  private String tenant;

  @NotBlank(message = "messageId is empty")
  private String messageId;

  @NotBlank(message = "payload is empty")
  private String payload;

  @NotNull(message = "messageType is empty")
  private MessageType messageType;

  private String xSchemaVersion;
}

When I perform a request to that endpoint:

{
   "tenant":"client1",
   "messageId":"670f13e15d554b2bba56f6d76d33b79c",
   "payload":"",
   "messageType":"MessageType.Email",
   "xSchemaVersion":"2.7.3"
}

I get the following error:

{
    "status": 400,
    "date": "2022-07-18T08:21:21.430+0000",
    "exception": "missing parameter: xSchemaVersion",
    "description": "uri=/v1/message"
}

But if I do the following instead:

{
   "tenant":"client1",
   "messageId":"670f13e15d554b2bba56f6d76d33b79c",
   "payload":"",
   "messageType":"MessageType.Email",
   "xschemaVersion":"2.7.3"
}

I get 200 OK.

Notice that the only thing I changed is the lowercase s in xschemaVersion instead of xSchemaVersion.

Why is this necessary?


Solution

  • This is happening because you are using lomboks getter & setter for your Message entity.

    If you check, lombok will generate get & set for your xSchemaVersion as getXSchemaVersion() & setXSchemaVersion(..), which is quite different than what any IDE would automatically generate for us.

    If I use eclipse for generating getters & setters for xSchemaVersion it would be getxSchemaVersion() & setxSchemaVersion(..); and this is what spring is also looking for as valid getter & setter for field xSchemaVersion (based on reflaction).

    Because lombok is making your x & s as an upper case, spring is unable to map your xSchemaVersion with input if you use xSchemaVersion.

    The reason it works with xschemaVersion because, spring is able to map field as it does lowecase conversion for words after get & set( getXSchemaVersion() & setXSchemaVersion(..).)

    Workaround -- create separate getter & setter in your Message for xSchemaVersion as getxSchemaVersion & setxSchemaVersion(..) which acts as overriding methods of default generated getter /setter of lombok.

    Once you do this, you can successfully able to use xSchemaVersoin in your input.