001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.http.annotation; 014 015import static java.lang.annotation.ElementType.*; 016import static java.lang.annotation.RetentionPolicy.*; 017 018import java.lang.annotation.*; 019 020import org.apache.juneau.jsonschema.annotation.Schema; 021import org.apache.juneau.*; 022import org.apache.juneau.annotation.*; 023import org.apache.juneau.httppart.*; 024import org.apache.juneau.json.*; 025import org.apache.juneau.jsonschema.*; 026 027/** 028 * REST request body annotation. 029 * 030 * <p> 031 * Identifies a POJO to be used as the body of an HTTP request. 032 * 033 * <p> 034 * Can be used in the following locations: 035 * <ul> 036 * <li>Arguments and argument-types of server-side <ja>@RestMethod</ja>-annotated methods. 037 * <li>Arguments and argument-types of client-side <ja>@RemoteMethod</ja>-annotated interfaces. 038 * <li>Methods and return types of server-side and client-side <ja>@Request</ja>-annotated interfaces. 039 * </ul> 040 * 041 * <h5 class='topic'>Arguments and argument-types of server-side @RestMethod-annotated methods</h5> 042 * 043 * <p> 044 * On server-side REST, this annotation can be applied to method parameters or parameter classes to identify them as the body of an HTTP request. 045 * 046 * <h5 class='section'>Examples:</h5> 047 * <p class='bcode w800'> 048 * <jc>// Used on parameter</jc> 049 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>,path=<js>"/pets"</js>) 050 * <jk>public void</jk> addPet(<ja>@Body</ja> Pet pet) {...} 051 * </p> 052 * <p class='bcode w800'> 053 * <jc>// Used on class</jc> 054 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>,path=<js>"/pets"</js>) 055 * <jk>public void</jk> addPet(Pet pet) {...} 056 * 057 * <ja>@Body</ja> 058 * <jk>public class</jk> Pet {...} 059 * </p> 060 * 061 * <p> 062 * This is functionally equivalent to the following code... 063 * <p class='bcode w800'> 064 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>,path=<js>"/pets"</js>) 065 * <jk>public void</jk> addPet(RestRequest req) { 066 * Pet pet = req.getBody().asType(Pet.<jk>class</jk>); 067 * ... 068 * } 069 * </p> 070 * 071 * <p> 072 * Also used to populate the auto-generated Swagger documentation. 073 * 074 * <h5 class='section'>Examples:</h5> 075 * <p class='bcode w800'> 076 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>,path=<js>"/pets"</js>) 077 * <jk>public void</jk> addPet(Pet pet) {...} 078 * 079 * <ja>@Body</ja>( 080 * description=<js>"Pet object to add to the store"</js>, 081 * required=<jk>true</jk>, 082 * example=<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 083 * ) 084 * <jk>public class</jk> Pet {...} 085 * </p> 086 * 087 * <p> 088 * Swagger documentation values are coalesced from multiple sources in the following order of precedence: 089 * <ol> 090 * <li><ja>@Body</ja> annotation on parameter. 091 * <li><ja>@Body</ja> annotation on parameter class. 092 * <li><ja>@Body</ja> annotation on parent classes and interfaces. 093 * <li><ja>@MethodSwagger(value)</ja> annotation. 094 * <li>Localized resource bundle property <js>"[method-name].produces"</js>. 095 * <li><ja>@ResourceSwagger(value)</ja> annotation. 096 * <li>Localized classpath resource file <js>"[enclosing-class].[simple-class-name]_[locale].json"</js> (if it's an inner or member class). 097 * <li>Default classpath resource file <js>"[enclosing-class].[simple-class-name].json"</js> (if it's an inner or member class). 098 * <li>Localized classpath resource file <js>"[simple-class-name]_[locale].json"</js>. 099 * <li>Default classpath resource file <js>"[simple-class-name].json"</js>. 100 * </ol> 101 * 102 * <ul class='seealso'> 103 * <li class='link'>{@doc juneau-rest-server.HttpPartAnnotations.Body} 104 * <li class='link'>{@doc juneau-rest-server.Swagger} 105 * <li class='extlink'>{@doc SwaggerParameterObject} 106 * </ul> 107 * 108 * <h5 class='topic'>Arguments and argument-types of client-side @RemoteResource-annotated interfaces</h5> 109 * 110 * <ul class='seealso'> 111 * <li class='link'>{@doc juneau-rest-client.RestProxies.Body} 112 * </ul> 113 * 114 * <h5 class='topic'>Methods and return types of server-side and client-side @Request-annotated interfaces</h5> 115 * 116 * <ul class='seealso'> 117 * <li class='link'>{@doc juneau-rest-server.HttpPartAnnotations.Request} 118 * <li class='link'>{@doc juneau-rest-client.RestProxies.Request} 119 * </ul> 120 * 121 * <div class='warn'> 122 * If using this annotation on a Spring bean, note that you are likely to encounter issues when using on parameterized 123 * types such as <code>List<MyBean></code>. This is due to the fact that Spring uses CGLIB to recompile classes 124 * at runtime, and CGLIB was written before generics were introduced into Java and is a virtually-unsupported library. 125 * Therefore, parameterized types will often be stripped from class definitions and replaced with unparameterized types 126 * (e.g. <code>List</code>). Under these circumstances, you are likely to get <code>ClassCastExceptions</code> 127 * when trying to access generalized <code>ObjectMaps</code> as beans. The best solution to this issue is to either 128 * specify the parameter as a bean array (e.g. <code>MyBean[]</code>) or declare the method as final so that CGLIB 129 * will not try to recompile it. 130 * </div> 131 */ 132@Documented 133@Target({PARAMETER,FIELD,METHOD,TYPE}) 134@Retention(RUNTIME) 135@Inherited 136public @interface Body { 137 138 //================================================================================================================= 139 // Attributes common to all Swagger Parameter objects 140 //================================================================================================================= 141 142 /** 143 * <mk>description</mk> field of the {@doc SwaggerParameterObject}. 144 * 145 * <p> 146 * A brief description of the body. This could contain examples of use. 147 * 148 * <h5 class='section'>Examples:</h5> 149 * <p class='bcode w800'> 150 * <jc>// Used on parameter</jc> 151 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 152 * <jk>public void</jk> addPet( 153 * <ja>@Body</ja>(description=<js>"Pet object to add to the store"</js>) Pet input 154 * ) {...} 155 * </p> 156 * <p class='bcode w800'> 157 * <jc>// Used on class</jc> 158 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 159 * <jk>public void</jk> addPet(Pet input) {...} 160 * 161 * <ja>@Body</ja>(description=<js>"Pet object to add to the store"</js>) 162 * <jk>public class</jk> Pet {...} 163 * </p> 164 * 165 * <h5 class='section'>Used for:</h5> 166 * <ul class='spaced-list'> 167 * <li> 168 * Server-side generated Swagger documentation. 169 * </ul> 170 * 171 * <ul class='notes'> 172 * <li> 173 * The format is plain text. 174 * <br>Multiple lines are concatenated with newlines. 175 * <li> 176 * Supports {@doc DefaultRestSvlVariables} 177 * (e.g. <js>"$L{my.localized.variable}"</js>). 178 * </ul> 179 */ 180 String[] description() default {}; 181 182 /** 183 * <mk>required</mk> field of the {@doc SwaggerParameterObject}. 184 * 185 * <p> 186 * Determines whether the body is mandatory. 187 * 188 * <p> 189 * If validation fails during serialization or parsing, the part serializer/parser will throw a {@link SchemaValidationException}. 190 * <br>On the client-side, this gets converted to a <c>RestCallException</c> which is thrown before the connection is made. 191 * <br>On the server-side, this gets converted to a <c>BadRequest</c> (400). 192 * 193 * <h5 class='section'>Examples:</h5> 194 * <p class='bcode w800'> 195 * <jc>// Used on parameter</jc> 196 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 197 * <jk>public void</jk> addPet( 198 * <ja>@Body</ja>(required=<jk>true</jk>) Pet input 199 * ) {...} 200 * </p> 201 * <p class='bcode w800'> 202 * <jc>// Used on class</jc> 203 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 204 * <jk>public void</jk> addPet(Pet input) {...} 205 * 206 * <ja>@Body</ja>(required=<jk>true</jk>) 207 * <jk>public class</jk> Pet {...} 208 * </p> 209 * 210 * <h5 class='section'>Used for:</h5> 211 * <ul class='spaced-list'> 212 * <li> 213 * Server-side schema-based parsing validation. 214 * <li> 215 * Server-side generated Swagger documentation. 216 * <li> 217 * Client-side schema-based serializing validation. 218 * </ul> 219 * 220 * <ul class='notes'> 221 * <li> 222 * Supports {@doc DefaultRestSvlVariables} 223 * (e.g. <js>"$L{my.localized.variable}"</js>). 224 * </ul> 225 */ 226 boolean required() default false; 227 228 //================================================================================================================= 229 // Attributes specific to in=body 230 //================================================================================================================= 231 232 /** 233 * <mk>schema</mk> field of the {@doc SwaggerParameterObject}. 234 * 235 * <p> 236 * The schema defining the type used for the body parameter. 237 * 238 * <p> 239 * This is a required attribute per the swagger definition. 240 * However, if not explicitly specified, the value will be auto-generated using {@link JsonSchemaSerializer}. 241 * 242 * <h5 class='section'>Used for:</h5> 243 * <ul class='spaced-list'> 244 * <li> 245 * Server-side schema-based parsing and parsing validation. 246 * <li> 247 * Server-side generated Swagger documentation. 248 * <li> 249 * Client-side schema-based serializing and serializing validation. 250 * </ul> 251 * 252 * <ul class='notes'> 253 * <li> 254 * Supports {@doc DefaultRestSvlVariables} 255 * (e.g. <js>"$L{my.localized.variable}"</js>). 256 * </ul> 257 */ 258 Schema schema() default @Schema; 259 260 //================================================================================================================= 261 // Other 262 //================================================================================================================= 263 264 /** 265 * A serialized example of the body of a request. 266 * 267 * <p> 268 * This is the {@doc SimpleJson} of an example of the body. 269 * 270 * <p> 271 * This value is converted to a POJO and then serialized to all the registered serializers on the REST method to produce examples for all 272 * supported language types. 273 * <br>These values are then used to automatically populate the {@link #examples} field. 274 * 275 * <h5 class='section'>Example:</h5> 276 * <p class='bcode w800'> 277 * <jc>// A JSON representation of a PetCreate object.</jc> 278 * <ja>@Body</ja>( 279 * example=<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 280 * ) 281 * </p> 282 * <p> 283 * <img class='bordered' src='doc-files/Body_Example.png' style='width:860px'> 284 * 285 * <p> 286 * There are several other options for defining this example: 287 * <ul class='spaced-list'> 288 * <li> 289 * Defining an <js>"x-example"</js> field in the inherited Swagger JSON body field (classpath file or <code><ja>@ResourceSwagger</ja>(value)</code>/<code><ja>@MethodSwagger</ja>(value)</code>). 290 * <li> 291 * Defining an <js>"x-example"</js> field in the Swagger Schema Object for the body (including referenced <js>"$ref"</js> schemas). 292 * <li> 293 * Allowing Juneau to auto-generate a code example. 294 * </ul> 295 * 296 * <p> 297 * The latter is important because Juneau also supports auto-generation of JSON-Schema from POJO classes using {@link JsonSchemaSerializer} which has several of it's own 298 * options for auto-detecting and calculation POJO examples. 299 * 300 * <p> 301 * In particular, examples can be defined via static methods, fields, and annotations on the classes themselves. 302 * 303 * <p class='bcode w800'> 304 * <jc>// Annotation on class.</jc> 305 * <ja>@Example</ja>(<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js>) 306 * <jk>public class</jk> PetCreate { 307 * ... 308 * } 309 * </p> 310 * <p class='bcode w800'> 311 * <jc>// Annotation on static method.</jc> 312 * <jk>public class</jk> PetCreate { 313 * 314 * <ja>@Example</ja> 315 * <jk>public static</jk> PetCreate <jsm>sample</jsm>() { 316 * <jk>return new</jk> PetCreate(<js>"Doggie"</js>, 9.99f, <js>"Dog"</js>, <jk>new</jk> String[] {<js>"friendly"</js>,<js>"cute"</js>}); 317 * } 318 * } 319 * </p> 320 * <p class='bcode w800'> 321 * <jc>// Static method with specific name 'example'.</jc> 322 * <jk>public class</jk> PetCreate { 323 * 324 * <jk>public static</jk> PetCreate <jsm>example</jsm>() { 325 * <jk>return new</jk> PetCreate(<js>"Doggie"</js>, 9.99f, <js>"Dog"</js>, <jk>new</jk> String[] {<js>"friendly"</js>,<js>"cute"</js>}); 326 * } 327 * } 328 * </p> 329 * <p class='bcode w800'> 330 * <jc>// Static field.</jc> 331 * <jk>public class</jk> PetCreate { 332 * 333 * <ja>@Example</ja> 334 * <jk>public static</jk> PetCreate <jsf>EXAMPLE</jsf> = <jk>new</jk> PetCreate(<js>"Doggie"</js>, 9.99f, <js>"Dog"</js>, <jk>new</jk> String[] {<js>"friendly"</js>,<js>"cute"</js>}); 335 * } 336 * </p> 337 * 338 * <p> 339 * Examples can also be specified via generic properties as well using the {@link BeanContext#BEAN_examples} property at either the class or method level. 340 * <p class='bcode w800'> 341 * <jc>// Examples defined at class level.</jc> 342 * <ja>@RestResource</ja>( 343 * properties={ 344 * <ja>@Property</ja>( 345 * name=<jsf>BEAN_examples</jsf>, 346 * value=<js>"{'org.apache.juneau.examples.rest.petstore.PetCreate': {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}}"</js> 347 * ) 348 * } 349 * ) 350 * </p> 351 * 352 * <h5 class='section'>Used for:</h5> 353 * <ul class='spaced-list'> 354 * <li> 355 * Server-side generated Swagger documentation. 356 * </ul> 357 * 358 * <ul class='seealso'> 359 * <li class='ja'>{@link Example} 360 * <li class='jc'>{@link BeanContext} 361 * <ul> 362 * <li class='jf'>{@link BeanContext#BEAN_examples BEAN_examples} 363 * </ul> 364 * <li class='jc'>{@link JsonSchemaSerializer} 365 * <ul> 366 * <li class='jf'>{@link JsonSchemaGenerator#JSONSCHEMA_addExamplesTo JSONSCHEMA_addExamplesTo} 367 * <li class='jf'>{@link JsonSchemaGenerator#JSONSCHEMA_allowNestedExamples JSONSCHEMA_allowNestedExamples} 368 * </ul> 369 * </ul> 370 * 371 * <ul class='notes'> 372 * <li> 373 * The format is any {@doc SimpleJson} if the object can be converted to a POJO using {@link JsonParser#DEFAULT} or a simple String if the object 374 * has a schema associated with it meancan be converted from a String. 375 * <br>Multiple lines are concatenated with newlines. 376 * <li> 377 * The format of this object can also be a simple String if the body has a schema associated with it, meaning it's meant to be treated as an HTTP part. 378 * <li> 379 * Supports {@doc DefaultRestSvlVariables} 380 * (e.g. <js>"$L{my.localized.variable}"</js>). 381 * </ul> 382 */ 383 String[] example() default {}; 384 385 /** 386 * Serialized examples of the body of a request. 387 * 388 * <p> 389 * This is a {@doc SimpleJson} object whose keys are media types and values are string representations of that value. 390 * 391 * <p> 392 * In general you won't need to populate this value directly since it will automatically be calculated based on the value provided in the {@link #example()} field. 393 * <br>However, this field allows you to override the behavior and show examples for only specified media types or different examples for different media types. 394 * 395 * <p class='bcode w800'> 396 * <jc>// A JSON representation of a PetCreate object.</jc> 397 * <ja>@Body</ja>( 398 * examples={ 399 * <js>"'application/json':'{name:\\'Doggie\\',species:\\'Dog\\'}',"</js>, 400 * <js>"'text/uon':'(name:Doggie,species=Dog)'"</js> 401 * } 402 * ) 403 * </p> 404 * 405 * <h5 class='section'>Used for:</h5> 406 * <ul class='spaced-list'> 407 * <li> 408 * Server-side generated Swagger documentation. 409 * </ul> 410 * 411 * <ul class='notes'> 412 * <li> 413 * The format is a {@doc SimpleJson} object with string keys (media type) and string values (example for that media type) . 414 * <li> 415 * The leading/trailing <c>{ }</c> characters are optional. 416 * <li> 417 * Multiple lines are concatenated with newlines so that you can format the value to be readable: 418 * <li> 419 * Supports {@doc DefaultRestSvlVariables} 420 * (e.g. <js>"$L{my.localized.variable}"</js>). 421 * <li> 422 * Resolution of variables is delayed until request time and occurs before parsing. 423 * <br>This allows you to, for example, pull in a JSON construct from a properties file based on the locale of the HTTP request. 424 * </ul> 425 */ 426 String[] examples() default {}; 427 428 /** 429 * Free-form value for the {@doc SwaggerParameterObject}. 430 * 431 * <p> 432 * This is a {@doc SimpleJson} object that makes up the swagger information for this parameter-info. 433 * 434 * <p> 435 * The following are completely equivalent ways of defining the swagger description of the body: 436 * <p class='bcode w800'> 437 * <jc>// Normal</jc> 438 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 439 * <jk>public void</jk> addPet( 440 * <ja>@Body</ja>( 441 * description=<js>"Pet object to add to the store"</js>, 442 * required=<jk>true</jk>, 443 * example=<js>"{name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 444 * ) Pet input 445 * ) {...} 446 * </p> 447 * <p class='bcode w800'> 448 * <jc>// Free-form</jc> 449 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 450 * <jk>public void</jk> addPet( 451 * <ja>@Body</ja>({ 452 * <js>"description: 'Pet object to add to the store',"</js>, 453 * <js>"required: true,"</js>, 454 * <js>"example: {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 455 * }) Pet input 456 * ) {...} 457 * </p> 458 * <p class='bcode w800'> 459 * <jc>// Free-form with variables</jc> 460 * <ja>@RestMethod</ja>(name=<jsf>POST</jsf>) 461 * <jk>public void</jk> addPet( 462 * <ja>@Body</ja>(<js>"$L{petObjectSwagger}"</js>) Pet input 463 * ) {...} 464 * </p> 465 * <p class='bcode w800'> 466 * <mc>// Contents of MyResource.properties</mc> 467 * <mk>petObjectSwagger</mk> = <mv>{ description: "Pet object to add to the store", required: true, example: {name:"Doggie",price:9.99,species:"Dog",tags:["friendly","cute"]} }</mv> 468 * </p> 469 * 470 * <p> 471 * The reasons why you may want to use this field include: 472 * <ul> 473 * <li>You want to pull in the entire Swagger JSON definition for this body from an external source such as a properties file. 474 * <li>You want to add extra fields to the Swagger documentation that are not officially part of the Swagger specification. 475 * </ul> 476 * 477 * <h5 class='section'>Used for:</h5> 478 * <ul class='spaced-list'> 479 * <li> 480 * Server-side generated Swagger documentation. 481 * </ul> 482 * 483 * <ul class='notes'> 484 * <li> 485 * The format is a {@doc SimpleJson} object. 486 * <li> 487 * Schema-based serialization is NOT affected by values defined in this annotation. 488 * <br>It only affects the generated Swagger documentation. 489 * <li> 490 * The leading/trailing <c>{ }</c> characters are optional. 491 * <br>The following two example are considered equivalent: 492 * <p class='bcode w800'> 493 * <ja>@Body</ja>(<js>"{description: 'Pet object to add to the store'}"</js>) 494 * </p> 495 * <p class='bcode w800'> 496 * <ja>@Body</ja>(<js>"description: 'Pet object to add to the store'"</js>) 497 * </p> 498 * <li> 499 * Multiple lines are concatenated with newlines so that you can format the value to be readable. 500 * <li> 501 * Supports {@doc DefaultRestSvlVariables} 502 * (e.g. <js>"$L{my.localized.variable}"</js>). 503 * <li> 504 * Values defined in this field supersede values pulled from the Swagger JSON file and are superseded by individual values defined on this annotation. 505 * </ul> 506 */ 507 String[] value() default {}; 508 509 /** 510 * Equivalent to {@link #value()}. 511 * 512 * <p> 513 * The following are entirely equivalent: 514 * 515 * <p class='bcode w800'> 516 * <ja>@Body</ja>({ 517 * <js>"description: 'Pet object to add to the store',"</js>, 518 * <js>"required: true,"</js>, 519 * <js>"example: {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 520 * }) 521 * </p> 522 * <p class='bcode w800'> 523 * <ja>@Body</ja>(api={ 524 * <js>"description: 'Pet object to add to the store',"</js>, 525 * <js>"required: true,"</js>, 526 * <js>"example: {name:'Doggie',price:9.99,species:'Dog',tags:['friendly','cute']}"</js> 527 * }) 528 * </p> 529 * 530 * <h5 class='section'>Used for:</h5> 531 * <ul class='spaced-list'> 532 * <li> 533 * Server-side generated Swagger documentation. 534 * </ul> 535 * 536 * <ul class='notes'> 537 * <li> 538 * If you specify both {@link #value()} and {@link #api()}, {@link #value()} will be ignored. 539 * </ul> 540 */ 541 String[] api() default {}; 542}