blob: 082e4e913e7ce7f168b96c4200f0329f1dc21ea5 [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
{updated} @Body
<p>
The {@link oaj.http.annotation.Body @Body} annotation is used to identify POJOs to be used as the body of an HTTP request.
</p>
<ul class='javatree'>
<li class='ja'>{@link oaj.http.annotation.Body}
<ul>
<li class='jf'>{@link oaj.http.annotation.Body#api() api} - Free-form Swagger JSON.
<li class='jf'>{@link oaj.http.annotation.Body#description() description} - Description.
<li class='jf'>{@link oaj.http.annotation.Body#example() example} - Serialized example.
<li class='jf'>{@link oaj.http.annotation.Body#examples() examples} - Serialized examples per media type.
<li class='jf'>{@link oaj.http.annotation.Body#required() required} - Input validation. Body must be present.
<li class='jf'>{@link oaj.http.annotation.Body#schema() schema} - Swagger schema.
<li class='jf'>{@link oaj.http.annotation.Body#value() value} - Free-form Swagger JSON.
</ul>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bpcode w800'>
<jc>// Defined on parameter</jc>
<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
<jk>public void</jk> addPet(<ja>@Body</ja> Pet pet) {...}
</p>
<p class='bpcode w800'>
<jc>// Defined on POJO class</jc>
<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
<jk>public void</jk> addPet(Pet pet) {...}
<ja>@Body</ja>
<jk>public class</jk> Pet {...}
</p>
<p>
This is functionally equivalent to the following code:
</p>
<p class='bpcode w800'>
<ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
<jk>public void</jk> addPet(RestRequest req) {
Person person = req.getBody().asType(Pet.<jk>class</jk>);
...
}
</p>
<p>
Any of the following types can be used for the parameter or POJO class (matched in the specified order):
</p>
<ol class='spaced-list'>
<li>
{@link java.io.Reader}
<br><ja>@Body</ja> annotation is optional.
<br><c>Content-Type</c> is ignored.
<li>
{@link java.io.InputStream}
<br><ja>@Body</ja> annotation is optional.
<br><c>Content-Type</c> is ignored.
<li>
Any {@doc PojoCategories Parsable POJO} type.
<br><c>Content-Type</c> is required to identify correct parser.
<li>
Objects convertible from {@link java.io.Reader} by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(Reader in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(Reader in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromReader</jsm>(Reader in) {...}</c>
</ul>
<c>Content-Type</c> must not be present or match an existing parser so that it's not parsed as a POJO.
<li>
Objects convertible from {@link java.io.InputStream} by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(InputStream in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(InputStream in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromInputStream</jsm>(InputStream in) {...}</c>
</ul>
<c>Content-Type</c> must not be present or match an existing parser so that it's not parsed as a POJO.
<li>
Objects convertible from {@link java.lang.String} by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromString</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>parse</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>parseString</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>forName</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>forString</jsm>(String in) {...}</c>
</ul>
Note that this also includes all enums.
</ol>
<p>
The {@link oaj.oapi.OpenApiSerializer} class can be used to serialize HTTP bodies to OpenAPI-based output.
</p>
<p>
For example, the following shows how a pipe-delimited list of comma-delimited numbers (e.g. <js>"1,2,3|4,5,6|7,8,9"</js>) can be converted to a 2-dimensional array of <c>Longs</c>:
</p>
<p class='bpcode w800'>
<jc>// Body is a pipe-delimited list of comma-delimited lists of longs.</jc>
<ja>@RestMethod</ja>(
method=<js>"POST"</js>,
path=<js>"/testBody"</js>,
serializers=OpenApiSerializers.<jk>class</jk>,
defaultAccept=<js>"text/openapi"</js>
)
<jk>public void</jk> testBody(
<ja>@Body</ja>(
schema=<ja>@Schema</ja>(
items=<ja>@Items</ja>(
collectionFormat=<js>"pipes"</js>,
items=<ja>@SubItems</ja>(
collectionFormat=<js>"csv"</js>,
type=<js>"integer"</js>,
format=<js>"int64"</js>,
minimum=<js>"0"</js>,
maximum=<js>"100"</js>
minLength=1,
maxLength=10
)
),
minLength=1,
maxLength=10
)
)
Long[][] body
) {...}
</p>
<p>
Input will be converted based on the types and formats defined in the schema definition.
Input validations such as <c>minLength/maxLength</c> that don't match the input will result in automatic <c>400 Bad Request</c> responses.
</p>
<p>
For more information about valid parameter types when using OpenAPI parsing, see {@doc juneau-marshall.OpenApiDetails.Parsers OpenAPI Parsers}
</p>
<p>
The <ja>@Body</ja> 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.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bpcode w800'>
<jc>// Normal</jc>
<ja>@Body</ja>(
description=<js>"Pet object to add to the store"</js>,
required=<jk>true</jk>,
example=<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js>
)
</p>
<p class='bpcode w800'>
<jc>// Free-form</jc>
<jc>// Note the extra field</jc>
<ja>@Body</ja>({
<js>"description: 'Pet object to add to the store',"</js>,
<js>"required: true,"</js>,
<js>"example: {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']},"</js>
<js>"x-extra: 'extra field'"</js>
})
</p>
<p>
{@doc DefaultRestSvlVariables} (e.g. "$L{my.localized.variable}")
are supported on annotation fields.
</p>
<h5 class='figure'>Example:</h5>
<p class='bpcode w800'>
<jc>// Localized</jc>
<ja>@Body</ja>(
description=<js>"$L{PetObjectDescription}"</js>
)
</p>
<ul class='notes'>
<li>
Annotation parameter values will be aggregated when used on POJO parent and child classes.
<br>Values on child classes override values on parent classes.
<li>
Annotation parameter values will be aggregated when used on both POJOs and REST methods.
<br>Values on methods override values on POJO classes.
</ul>
<div class='warn'>
If using this annotation on a Spring bean, note that you are likely to encounter issues when using on parameterized
types such as <code>List&lt;MyBean&gt;</code>. 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. <code>List</code>). Under these circumstances, you are likely to get <code>ClassCastExceptions</code>
when trying to access generalized <code>ObjectMaps</code> as beans. The best solution to this issue is to either
specify the parameter as a bean array (e.g. <code>MyBean[]</code>) or declare the method as final so that CGLIB
will not try to recompile it.
</div>
<ul class='seealso'>
<li class='jc'>{@link oajr.RequestBody}
<li class='link'>{@doc juneau-rest-server.OpenApiSchemaPartParsing}
</ul>