{8.1.0-updated} @Body

The {@link oaj.http.annotation.Body @Body} annotation is used to identify POJOs to be used as the body of an HTTP request.

Examples:

// Defined on parameter @RestMethod(name=POST) public void addPet(@Body Pet pet) {...}

// Defined on POJO class @RestMethod(name=POST) public void addPet(Pet pet) {...} @Body public class Pet {...}

This is functionally equivalent to the following code:

@RestMethod(name=POST) public void addPet(RestRequest req) { Person person = req.getBody().asType(Pet.class); ... }

Any of the following types can be used for the parameter or POJO class (matched in the specified order):

  1. {@link java.io.Reader}
    @Body annotation is optional.
    Content-Type is ignored.
  2. {@link java.io.InputStream}
    @Body annotation is optional.
    Content-Type is ignored.
  3. Any {@doc PojoCategories Parsable POJO} type.
    Content-Type is required to identify correct parser.
  4. Objects convertible from {@link java.io.Reader} by having one of the following non-deprecated methods: Content-Type must not be present or match an existing parser so that it's not parsed as a POJO.
  5. Objects convertible from {@link java.io.InputStream} by having one of the following non-deprecated methods: Content-Type must not be present or match an existing parser so that it's not parsed as a POJO.
  6. Objects convertible from {@link java.lang.String} by having one of the following non-deprecated methods: Note that this also includes all enums.
  7. Any {@link java.util.Optional} of anything on this list.

The {@link oaj.oapi.OpenApiSerializer} class can be used to serialize HTTP bodies to OpenAPI-based output.

For example, the following shows how a pipe-delimited list of comma-delimited numbers (e.g. "1,2,3|4,5,6|7,8,9") can be converted to a 2-dimensional array of Longs:

// Body is a pipe-delimited list of comma-delimited lists of longs. @RestMethod( method="POST", path="/testBody", serializers=OpenApiSerializers.class, defaultAccept="text/openapi" ) public void testBody( @Body( schema=@Schema( items=@Items( collectionFormat="pipes", items=@SubItems( collectionFormat="csv", type="integer", format="int64", minimum="0", maximum="100" minLength=1, maxLength=10 ) ), minLength=1, maxLength=10 ) ) Long[][] body ) {...}

Input will be converted based on the types and formats defined in the schema definition. Input validations such as minLength/maxLength that don't match the input will result in automatic 400 Bad Request responses.

For more information about valid parameter types when using OpenAPI parsing, see {@doc juneau-marshall.OpenApiDetails.Parsers OpenAPI Parsers}

The @Body annotation is also used for supplying swagger information about the body of the request. This information is used to populate the auto-generated Swagger documentation and UI.

Examples:

// Normal @Body( description="Pet object to add to the store", required=true, example="{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}" )

// Free-form // Note the extra field @Body({ "description: 'Pet object to add to the store',", "required: true,", "example: {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}," "x-extra: 'extra field'" })

{@doc DefaultRestSvlVariables} (e.g. "$L{my.localized.variable}") are supported on annotation fields.

Example:

// Localized @Body( description="$L{PetObjectDescription}" )

If using this annotation on a Spring bean, note that you are likely to encounter issues when using on parameterized types such as List<MyBean>. This is due to the fact that Spring uses CGLIB to recompile classes at runtime, and CGLIB was written before generics were introduced into Java and is a virtually-unsupported library. Therefore, parameterized types will often be stripped from class definitions and replaced with unparameterized types (e.g. List). Under these circumstances, you are likely to get ClassCastExceptions when trying to access generalized ObjectMaps as beans. The best solution to this issue is to either specify the parameter as a bean array (e.g. MyBean[]) or declare the method as final so that CGLIB will not try to recompile it.