001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.server; 018 019import static java.lang.annotation.ElementType.*; 020import static java.lang.annotation.RetentionPolicy.*; 021 022import java.lang.annotation.*; 023 024import org.apache.juneau.bean.swagger.*; 025import org.apache.juneau.commons.*; 026import org.apache.juneau.commons.inject.*; 027import org.apache.juneau.http.remote.*; 028import org.apache.juneau.marshall.encoders.*; 029import org.apache.juneau.marshall.parser.*; 030import org.apache.juneau.marshall.serializer.*; 031import org.apache.juneau.rest.server.converter.*; 032import org.apache.juneau.rest.server.guard.*; 033import org.apache.juneau.rest.server.matcher.*; 034import org.apache.juneau.rest.server.metrics.*; 035import org.apache.juneau.rest.server.servlet.*; 036import org.apache.juneau.rest.server.swagger.*; 037 038/** 039 * Identifies a REST operation Java method on a {@link RestServlet} implementation class. 040 * 041 * <h5 class='section'>See Also:</h5><ul> 042 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestOpAnnotatedMethods">@RestOp-Annotated Method</a> 043 044 * </ul> 045 */ 046@Target(METHOD) 047@Retention(RUNTIME) 048@Inherited 049@AnnotationGroup(RestOp.class) 050public @interface RestOp { 051 052 /** 053 * Specifies whether this method can be called based on the client version. 054 * 055 * <p> 056 * The client version is identified via the HTTP request header identified by 057 * {@link Rest#clientVersionHeader() @Rest(clientVersionHeader)} which by default is <js>"Client-Version"</js>. 058 * 059 * <p> 060 * This is a specialized kind of {@link RestMatcher} that allows you to invoke different Java methods for the same 061 * method/path based on the client version. 062 * 063 * <p> 064 * The format of the client version range is similar to that of OSGi versions. 065 * 066 * <p> 067 * In the following example, the Java methods are mapped to the same HTTP method and URL <js>"/foobar"</js>. 068 * <p class='bjava'> 069 * <jc>// Call this method if Client-Version is at least 2.0. 070 * // Note that this also matches 2.0.1.</jc> 071 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>) 072 * <jk>public</jk> Object method1() {...} 073 * 074 * <jc>// Call this method if Client-Version is at least 1.1, but less than 2.0.</jc> 075 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>) 076 * <jk>public</jk> Object method2() {...} 077 * 078 * <jc>// Call this method if Client-Version is less than 1.1.</jc> 079 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"[0,1.1)"</js>) 080 * <jk>public</jk> Object method3() {...} 081 * </p> 082 * 083 * <p> 084 * It's common to combine the client version with transforms that will convert new POJOs into older POJOs for 085 * backwards compatibility. 086 * <p class='bjava'> 087 * <jc>// Call this method if Client-Version is at least 2.0.</jc> 088 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>) 089 * <jk>public</jk> NewPojo newMethod() {...} 090 * 091 * <jc>// Call this method if X-Client-Version is at least 1.1, but less than 2.0.</jc> 092 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>) 093 * <ja>@MarshalledConfig(swaps=NewToOldSwap.<jk>class</jk>) 094 * <jk>public</jk> NewPojo oldMethod() { 095 * <jk>return</jk> newMethod(); 096 * } 097 * 098 * <p> 099 * Note that in the previous example, we're returning the exact same POJO, but using a transform to convert it into 100 * an older form. 101 * The old method could also just return back a completely different object. 102 * The range can be any of the following: 103 * <ul> 104 * <li><js>"[0,1.0)"</js> = Less than 1.0. 1.0 and 1.0.0 does not match. 105 * <li><js>"[0,1.0]"</js> = Less than or equal to 1.0. Note that 1.0.1 will match. 106 * <li><js>"1.0"</js> = At least 1.0. 1.0 and 2.0 will match. 107 * </ul> 108 * 109 * <h5 class='section'>See Also:</h5><ul> 110 * <li class='ja'>{@link Rest#clientVersionHeader()} 111 * </ul> 112 * 113 * @return The annotation value. 114 */ 115 String clientVersion() default ""; 116 117 /** 118 * Supported content media types. 119 * 120 * <p> 121 * Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource. 122 * 123 * <h5 class='section'>Notes:</h5><ul> 124 * <li class='note'> 125 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 126 * (e.g. <js>"$S{mySystemProperty}"</js>). 127 * </ul> 128 * 129 * <h5 class='section'>See Also:</h5><ul> 130 * <li class='jm'>{@link RestOpContext#getSupportedContentTypes()} 131 * </ul> 132 * 133 * @return The annotation value. 134 */ 135 String[] consumes() default {}; 136 137 /** 138 * Class-level response converters. 139 * 140 * <p> 141 * Associates one or more {@link RestConverter converters} with this method. 142 * 143 * @return The annotation value. 144 */ 145 Class<? extends RestConverter>[] converters() default {}; 146 147 /** 148 * Default <c>Accept</c> header. 149 * 150 * <p> 151 * The default value for the <c>Accept</c> header if not specified on a request. 152 * 153 * <p> 154 * This is a shortcut for using {@link #defaultRequestHeaders()} for just this specific header. 155 * 156 * @return The annotation value. 157 */ 158 String defaultAccept() default ""; 159 160 /** 161 * Default character encoding. 162 * 163 * <p> 164 * The default character encoding for the request and response if not specified on the request. 165 * 166 * <h5 class='section'>Notes:</h5><ul> 167 * <li class='note'> 168 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 169 * (e.g. <js>"$S{mySystemProperty}"</js>). 170 * </ul> 171 * 172 * <h5 class='section'>See Also:</h5><ul> 173 * <li class='ja'>{@link Rest#defaultCharset} 174 * </ul> 175 * 176 * @return The annotation value. 177 */ 178 String defaultCharset() default ""; 179 180 /** 181 * Default <c>Content-Type</c> header. 182 * 183 * <p> 184 * The default value for the <c>Content-Type</c> header if not specified on a request. 185 * 186 * <p> 187 * This is a shortcut for using {@link #defaultRequestHeaders()} for just this specific header. 188 * 189 * @return The annotation value. 190 */ 191 String defaultContentType() default ""; 192 193 /** 194 * Default request attributes. 195 * 196 * <p> 197 * Specifies default values for request attributes if they're not already set on the request. 198 * 199 * <p> 200 * Affects values returned by the following methods: 201 * <ul> 202 * <li class='jm'>{@link RestRequest#getAttribute(String)}. 203 * <li class='jm'>{@link RestRequest#getAttributes()}. 204 * </ul> 205 * 206 * <h5 class='section'>Example:</h5> 207 * <p class='bjava'> 208 * <jc>// Defined via annotation resolving to a config file setting with default value.</jc> 209 * <ja>@Rest</ja>(defaultRequestAttributes={<js>"Foo=bar"</js>, <js>"Baz: $C{REST/myAttributeValue}"</js>}) 210 * <jk>public class</jk> MyResource { 211 * 212 * <jc>// Override at the method level.</jc> 213 * <ja>@RestGet</ja>(defaultRequestAttributes={<js>"Foo: bar"</js>}) 214 * <jk>public</jk> Object myMethod() {...} 215 * } 216 * </p> 217 * 218 * </ul> 219 * <h5 class='section'>Notes:</h5><ul> 220 * <li class='note'> 221 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 222 * (e.g. <js>"$L{my.localized.variable}"</js>). 223 * </ul> 224 * 225 * <h5 class='section'>See Also:</h5><ul> 226 * <li class='ja'>{@link Rest#defaultRequestAttributes()} 227 * </ul> 228 * 229 * @return The annotation value. 230 */ 231 String[] defaultRequestAttributes() default {}; 232 233 /** 234 * Specifies default values for form-data parameters. 235 * 236 * <p> 237 * Strings are of the format <js>"name=value"</js>. 238 * 239 * <p> 240 * Affects values returned by {@link RestRequest#getFormParam(String)} when the parameter is not present on the 241 * request. 242 * 243 * <h5 class='section'>Example:</h5> 244 * <p class='bjava'> 245 * <ja>@RestOp</ja>(method=<jsf>POST</jsf>, path=<js>"/*"</js>, defaultRequestFormData={<js>"foo=bar"</js>}) 246 * <jk>public</jk> String doPost(<ja>@FormData</ja>(<js>"foo"</js>) String <jv>foo</jv>) {...} 247 * </p> 248 * 249 * <h5 class='section'>Notes:</h5><ul> 250 * <li class='note'> 251 * You can use either <js>':'</js> or <js>'='</js> as the key/value delimiter. 252 * <li class='note'> 253 * Key and value is trimmed of whitespace. 254 * <li class='note'> 255 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 256 * (e.g. <js>"$S{mySystemProperty}"</js>). 257 * </ul> 258 * 259 * @return The annotation value. 260 */ 261 String[] defaultRequestFormData() default {}; 262 263 /** 264 * Default request headers. 265 * 266 * <p> 267 * Specifies default values for request headers if they're not passed in through the request. 268 * 269 * <h5 class='section'>Example:</h5> 270 * <p class='bjava'> 271 * <jc>// Assume "text/json" Accept value when Accept not specified</jc> 272 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/*"</js>, defaultRequestHeaders={<js>"Accept: text/json"</js>}) 273 * <jk>public</jk> String doGet() {...} 274 * </p> 275 * 276 * <h5 class='section'>Notes:</h5><ul> 277 * <li class='note'> 278 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 279 * (e.g. <js>"$S{mySystemProperty}"</js>). 280 * </ul> 281 * 282 * @return The annotation value. 283 */ 284 String[] defaultRequestHeaders() default {}; 285 286 /** 287 * Specifies default values for query parameters. 288 * 289 * <p> 290 * Strings are of the format <js>"name=value"</js>. 291 * 292 * <p> 293 * Affects values returned by {@link RestRequest#getQueryParam(String)} when the parameter is not present on the request. 294 * 295 * <h5 class='section'>Example:</h5> 296 * <p class='bjava'> 297 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/*"</js>, defaultRequestQueryData={<js>"foo=bar"</js>}) 298 * <jk>public</jk> String doGet(<ja>@Query</ja>(<js>"foo"</js>) String <jv>foo</jv>) {...} 299 * </p> 300 * 301 * <h5 class='section'>Notes:</h5><ul> 302 * <li class='note'> 303 * You can use either <js>':'</js> or <js>'='</js> as the key/value delimiter. 304 * <li class='note'> 305 * Key and value is trimmed of whitespace. 306 * <li class='note'> 307 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 308 * (e.g. <js>"$S{mySystemProperty}"</js>). 309 * </ul> 310 * 311 * @return The annotation value. 312 */ 313 String[] defaultRequestQueryData() default {}; 314 315 /** 316 * Default response headers. 317 * 318 * <p> 319 * Specifies default values for response headers if they're not overwritten during the request. 320 * 321 * <h5 class='section'>Example:</h5> 322 * <p class='bjava'> 323 * <jc>// Assume "text/json" Accept value when Accept not specified</jc> 324 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/*"</js>, defaultResponseHeaders={<js>"Content-Type: text/json"</js>}) 325 * <jk>public</jk> String doGet() {...} 326 * </p> 327 * 328 * <h5 class='section'>Notes:</h5><ul> 329 * <li class='note'> 330 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 331 * (e.g. <js>"$S{mySystemProperty}"</js>). 332 * </ul> 333 * 334 * @return The annotation value. 335 */ 336 String[] defaultResponseHeaders() default {}; 337 338 /** 339 * Optional description for the exposed API. 340 * 341 * <p> 342 * This description is used in the following locations: 343 * <ul class='spaced-list'> 344 * <li> 345 * The value returned by {@link Operation#getDescription()} in the auto-generated swagger. 346 * <li> 347 * The <js>"$RS{operationDescription}"</js> variable. 348 * <li> 349 * The description of the method in the Swagger page. 350 * </ul> 351 * 352 * <h5 class='section'>Notes:</h5><ul> 353 * <li class='note'> 354 * Corresponds to the swagger field <c>/paths/{path}/{method}/description</c>. 355 * <li class='note'> 356 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 357 * (e.g. <js>"$L{my.localized.variable}"</js>). 358 * </ul> 359 * 360 * @return The annotation value. 361 */ 362 String[] description() default {}; 363 364 /** 365 * Specifies the compression encoders for this method. 366 * 367 * <p> 368 * Encoders are used to enable various kinds of compression (e.g. <js>"gzip"</js>) on requests and responses. 369 * 370 * <p> 371 * This value overrides encoders specified at the class level using {@link Rest#encoders()}. 372 * The {@link org.apache.juneau.marshall.encoders.EncoderSet.Inherit EncoderSet.Inherit} class can be used to include values from the parent class. 373 * 374 * <h5 class='section'>Example:</h5> 375 * <p class='bjava'> 376 * <jc>// Define a REST resource that handles GZIP compression.</jc> 377 * <ja>@Rest</ja>( 378 * encoders={ 379 * GzipEncoder.<jk>class</jk> 380 * } 381 * ) 382 * <jk>public class</jk> MyResource { 383 * 384 * <jc>// Define a REST method that can also use a custom encoder.</jc> 385 * <ja>@RestOp</ja>( 386 * method=<jsf>GET</jsf>, 387 * encoders={ 388 * EncoderSet.Inherit.<jk>class</jk>, MyEncoder.<jk>class</jk> 389 * } 390 * ) 391 * <jk>public</jk> MyBean doGet() { 392 * ... 393 * } 394 * } 395 * </p> 396 * 397 * <p> 398 * For programmatic equivalents, contribute a {@link EncoderSet} bean via 399 * {@link Bean @Bean(name="encoders")} (use methodScope to scope to specific operation methods). 400 * 401 * <h5 class='section'>See Also:</h5><ul> 402 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerEncoders">Encoders in REST servers</a> 403 * </ul> 404 * 405 * @return The annotation value. 406 */ 407 Class<? extends Encoder>[] encoders() default {}; 408 409 /** 410 * Method-level guards. 411 * 412 * <p> 413 * Associates one or more {@link RestGuard RestGuards} with this method. 414 * 415 * @return The annotation value. 416 */ 417 Class<? extends RestGuard>[] guards() default {}; 418 419 /** 420 * Method matchers. 421 * 422 * <p> 423 * Associates one more more {@link RestMatcher RestMatchers} with this method. 424 * 425 * <p> 426 * Matchers are used to allow multiple Java methods to handle requests assigned to the same URL path pattern, but 427 * differing based on some request attribute, such as a specific header value. 428 * 429 * <h5 class='section'>See Also:</h5><ul> 430 * <li class='jac'>{@link RestMatcher} 431 * </ul> 432 * 433 * @return The annotation value. 434 */ 435 Class<? extends RestMatcher>[] matchers() default {}; 436 437 /** 438 * The maximum allowed input size (in bytes) on HTTP requests. 439 * 440 * <p> 441 * Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting 442 * in out-of-memory errors which could affect system stability. 443 * 444 * <h5 class='section'>Example:</h5> 445 * <p class='bjava'> 446 * <ja>@RestOp</ja>( 447 * maxInput=<js>"100M"</js> 448 * ) 449 * </p> 450 * 451 * <h5 class='section'>Notes:</h5><ul> 452 * <li> 453 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 454 * (e.g. <js>"$S{mySystemProperty}"</js>). 455 * </ul> 456 * 457 * <h5 class='section'>See Also:</h5><ul> 458 * <li class='ja'>{@link Rest#maxInput} 459 * </ul> 460 * 461 * @return The annotation value. 462 */ 463 String maxInput() default ""; 464 465 /** 466 * REST method name. 467 * 468 * <p> 469 * Typically <js>"GET"</js>, <js>"PUT"</js>, <js>"POST"</js>, <js>"DELETE"</js>, or <js>"OPTIONS"</js>. 470 * 471 * <p> 472 * Method names are case-insensitive (always folded to upper-case). 473 * 474 * <p> 475 * Note that you can use {@link org.apache.juneau.http.HttpMethod} for constant values. 476 * 477 * <p> 478 * Note that you can also use {@link #value()} to specify the method name and path in shortened form. 479 * 480 * <p> 481 * Besides the standard HTTP method names, the following can also be specified: 482 * <ul class='spaced-list'> 483 * <li> 484 * <js>"*"</js> 485 * - Denotes any method. 486 * <br>Use this if you want to capture any HTTP methods in a single Java method. 487 * <br>The {@link Method @Method} annotation and/or {@link RestRequest#getMethod()} method can be used to 488 * distinguish the actual HTTP method name. 489 * <li> 490 * <js>""</js> 491 * - Auto-detect. 492 * <br>The method name is determined based on the Java method name. 493 * <br>For example, if the method is <c>doPost(...)</c>, then the method name is automatically detected 494 * as <js>"POST"</js>. 495 * <br>Otherwise, defaults to <js>"GET"</js>. 496 * <li> 497 * <js>"RRPC"</js> 498 * - Remote-proxy interface. 499 * <br>This denotes a Java method that returns an object (usually an interface, often annotated with the 500 * {@link Remote @Remote} annotation) to be used as a remote proxy using 501 * <c>RestClient.getRemoteInterface(Class<T> interfaceClass, String url)</c>. 502 * <br>This allows you to construct client-side interface proxies using REST as a transport medium. 503 * <br>Conceptually, this is simply a fancy <c>POST</c> against the url <js>"/{path}/{javaMethodName}"</js> 504 * where the arguments are marshalled from the client to the server as an HTTP content containing an array of 505 * objects, passed to the method as arguments, and then the resulting object is marshalled back to the client. 506 * <li> 507 * Anything else 508 * - Overloaded non-HTTP-standard names that are passed in through a <c>&method=methodName</c> URL 509 * parameter. 510 * <br>On a safe request (<c>GET</c>, <c>HEAD</c>, <c>OPTIONS</c>, <c>TRACE</c>), only when the operation is 511 * declared {@link #read() read=true}. 512 * </ul> 513 * 514 * @return The annotation value. 515 */ 516 String method() default ""; 517 518 /** 519 * Specifies the parsers for converting HTTP request bodies into POJOs for this method. 520 * 521 * <p> 522 * Parsers are used to convert the content of HTTP requests into POJOs. 523 * <br>Any of the Juneau framework parsers can be used in this setting. 524 * <br>The parser selected is based on the request <c>Content-Type</c> header matched against the values returned by the following method 525 * using a best-match algorithm: 526 * <ul class='javatree'> 527 * <li class='jm'>{@link Parser#getMediaTypes()} 528 * </ul> 529 * 530 * <p> 531 * This value overrides parsers specified at the class level using {@link Rest#parsers()}. 532 * The {@link org.apache.juneau.marshall.parser.ParserSet.Inherit ParserSet.Inherit} class can be used to include values from the parent class. 533 * 534 * <h5 class='section'>Example:</h5> 535 * <p class='bjava'> 536 * <jc>// Define a REST resource that can consume JSON and HTML.</jc> 537 * <ja>@Rest</ja>( 538 * parsers={ 539 * JsonParser.<jk>class</jk>, 540 * HtmlParser.<jk>class</jk> 541 * } 542 * ) 543 * <jk>public class</jk> MyResource { 544 * 545 * <jc>// Define a REST method that can also consume XML.</jc> 546 * <ja>@RestOp</ja>( 547 * method=<jsf>POST</jsf>, 548 * parsers={ 549 * ParserSet.Inherit.<jk>class</jk>, XmlParser.<jk>class</jk> 550 * } 551 * ) 552 * <jk>public void</jk> doPost(MyBean <jv>bean</jv>) { 553 * ... 554 * } 555 * } 556 * </p> 557 * 558 * <p> 559 * For programmatic equivalents, contribute a {@link ParserSet} bean via 560 * {@link Bean @Bean(name="parsers")} (use methodScope to scope to specific operation methods). 561 * 562 * <h5 class='section'>See Also:</h5><ul> 563 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a> 564 * </ul> 565 * 566 * @return The annotation value. 567 */ 568 Class<?>[] parsers() default {}; 569 570 /** 571 * Optional path pattern for the specified method. 572 * 573 * <p> 574 * Appending <js>"/*"</js> to the end of the path pattern will make it match any remainder too. 575 * <br>Not appending <js>"/*"</js> to the end of the pattern will cause a 404 (Not found) error to occur if the exact 576 * pattern is not found. 577 * 578 * <p> 579 * The path can contain variables that get resolved to {@link org.apache.juneau.http.Path @Path} parameters. 580 * 581 * <h5 class='figure'>Examples:</h5> 582 * <p class='bjava'> 583 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/myurl/{foo}/{bar}/{baz}/*"</js>) 584 * </p> 585 * <p class='bjava'> 586 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/myurl/{0}/{1}/{2}/*"</js>) 587 * </p> 588 * 589 * <p> 590 * If you do not specify a path name, then the path name is inferred from the Java method name. 591 * 592 * <h5 class='figure'>Example:</h5> 593 * <p class='bjava'> 594 * <jc>// Path is assumed to be "/foo".</jc> 595 * <ja>@RestOp</ja>(method=<jsf>GET</jsf>) 596 * <jk>public void</jk> foo() {...} 597 * </p> 598 * 599 * <p> 600 * If you also do not specify the {@link #method()} and the Java method name starts with <js>"get"</js>, <js>"put"</js>, <js>"post"</js>, or <js>"delete"</js>, 601 * then the HTTP method name is stripped from the inferred path. 602 * 603 * <h5 class='figure'>Examples:</h5> 604 * <p class='bjava'> 605 * <jc>// Method is GET, path is "/foo".</jc> 606 * <ja>@RestOp</ja> 607 * <jk>public void</jk> getFoo() {...} 608 * </p> 609 * <p class='bjava'> 610 * <jc>// Method is DELETE, path is "/bar".</jc> 611 * <ja>@RestOp</ja> 612 * <jk>public void</jk> deleteBar() {...} 613 * </p> 614 * <p class='bjava'> 615 * <jc>// Method is GET, path is "/foobar".</jc> 616 * <ja>@RestOp</ja> 617 * <jk>public void</jk> foobar() {...} 618 * </p> 619 * <p class='bjava'> 620 * <jc>// Method is GET, path is "/".</jc> 621 * <ja>@RestOp</ja> 622 * <jk>public void</jk> get() {...} 623 * </p> 624 * 625 * <p> 626 * Note that you can also use {@link #value()} to specify the method name and path in shortened form. 627 * 628 * <h5 class='section'>See Also:</h5><ul> 629 * <li class='ja'>{@link org.apache.juneau.http.Path} 630 * </ul> 631 * 632 * @return The annotation value. 633 */ 634 String[] path() default {}; 635 636 /** 637 * Per-operation override for {@link Rest#problemDetails() @Rest(problemDetails)}. 638 * 639 * <p> 640 * When set on a {@code @RestOp} method, this value takes precedence over the resource-level 641 * {@code @Rest(problemDetails)} attribute for this operation. Tri-state semantics: 642 * 643 * <ul class='values'> 644 * <li><js>"true"</js> — enable problem-details responses for this operation. 645 * <li><js>"false"</js> — disable problem-details responses for this operation (overrides an 646 * opted-in resource). 647 * <li><js>""</js> (default) — inherit from {@link Rest#problemDetails()}. 648 * </ul> 649 * 650 * <h5 class='section'>Notes:</h5><ul> 651 * <li class='note'> 652 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 653 * (e.g. <js>"$L{my.localized.variable}"</js>). 654 * </ul> 655 * 656 * <h5 class='section'>See Also:</h5><ul> 657 * <li class='ja'>{@link Rest#problemDetails()} 658 * </ul> 659 * 660 * @return The annotation value. 661 */ 662 String problemDetails() default ""; 663 664 /** 665 * Per-operation override for {@link Rest#debugMarshalling() @Rest(debugMarshalling)}. 666 * 667 * <p> 668 * When set on a {@code @RestOp} method, this value takes precedence over the resource-level 669 * {@code @Rest(debugMarshalling)} attribute for this operation. Tri-state semantics: 670 * 671 * <ul class='values'> 672 * <li><js>"true"</js> — enable marshalling debug for this operation. 673 * <li><js>"false"</js> — disable marshalling debug for this operation (overrides an opted-in resource). 674 * <li><js>""</js> (default) — inherit from {@link Rest#debugMarshalling()}. 675 * </ul> 676 * 677 * <h5 class='section'>Notes:</h5><ul> 678 * <li class='note'> 679 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a>. 680 * </ul> 681 * 682 * <h5 class='section'>See Also:</h5><ul> 683 * <li class='ja'>{@link Rest#debugMarshalling()} 684 * </ul> 685 * 686 * @return The annotation value. 687 */ 688 String debugMarshalling() default ""; 689 690 /** 691 * Per-operation override for {@link Rest#virtualThreads() @Rest(virtualThreads)}. 692 * 693 * <p> 694 * When set, this value takes precedence over the resource-level setting for this operation. Tri-state 695 * semantics: 696 * 697 * <ul class='values'> 698 * <li><js>"true"</js> — enable virtual-thread dispatch for this operation (Java 21+ only; 699 * gracefully ignored on older JVMs). 700 * <li><js>"false"</js> — disable virtual-thread dispatch for this operation (overrides an 701 * opted-in resource). 702 * <li><js>""</js> (default) — inherit from {@link Rest#virtualThreads()}. 703 * </ul> 704 * 705 * <h5 class='section'>Notes:</h5><ul> 706 * <li class='note'> 707 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 708 * (e.g. <js>"$E{ENABLE_VT,false}"</js>). 709 * </ul> 710 * 711 * <h5 class='section'>See Also:</h5><ul> 712 * <li class='ja'>{@link Rest#virtualThreads()} 713 * </ul> 714 * 715 * @return The annotation value. 716 */ 717 String virtualThreads() default ""; 718 719 /** 720 * Per-operation observability opt-in / opt-out control. 721 * 722 * <p> 723 * Overrides the resource-level {@link Rest#observability()} setting for this specific operation. 724 * Controls whether the observability block ({@link MetricsRecorder} / 725 * {@link org.apache.juneau.rest.server.tracing.TracerHook}) fires for this operation. 726 * 727 * <ul class='values'> 728 * <li><js>"true"</js> — strict opt-in: this operation <em>requires</em> a wired observability backend. 729 * If neither a {@code @Bean MetricsRecorder} nor a {@code @Bean TracerHook} is registered when the 730 * {@link RestContext} is built, construction fails with a precise error. 731 * <li><js>"false"</js> — explicit opt-out: the observability block is short-circuited for this operation, 732 * even when a wired backend is present. Also suppresses 733 * {@link org.apache.juneau.rest.server.tracing.TraceContextResponseProcessor} header injection. 734 * <li><js>""</js> (default) — inherits the resource-level {@link Rest#observability()} setting. 735 * If the resource-level setting is also empty, uses the existing behavior: the observability block 736 * runs per-op, but a missing backend silently falls back to the NoOp singleton. 737 * </ul> 738 * 739 * <h5 class='section'>Notes:</h5><ul> 740 * <li class='note'> 741 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 742 * (e.g. <js>"$E{ENABLE_OP_OBSERVABILITY,false}"</js>). 743 * <li class='note'> 744 * This per-operation setting takes full precedence over {@link Rest#observability()}. 745 * </ul> 746 * 747 * <h5 class='section'>See Also:</h5><ul> 748 * <li class='ja'>{@link Rest#observability()} 749 * <li class='jc'>{@link MetricsRecorder} 750 * <li class='jc'>{@link org.apache.juneau.rest.server.tracing.TracerHook} 751 * </ul> 752 * 753 * @return The annotation value. 754 * @since 10.0.0 755 */ 756 String observability() default ""; 757 758 /** 759 * Per-operation metric name override. 760 * 761 * <p> 762 * Overrides the metric name passed to {@link MetricsRecorder#record(String, String, String, int, java.time.Duration, Throwable, String, String) record()} 763 * for this operation. When empty (default), the recorder uses its own default name derivation (typically the 764 * fully-qualified operation name). 765 * 766 * <h5 class='section'>Notes:</h5><ul> 767 * <li class='note'> 768 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a>. 769 * <li class='note'> 770 * Has no effect when observability is disabled for this operation. 771 * </ul> 772 * 773 * @return The annotation value. 774 * @since 10.0.0 775 */ 776 String metricName() default ""; 777 778 /** 779 * Per-operation metric tags. 780 * 781 * <p> 782 * Additional metric tags to pass to {@link MetricsRecorder#record(String, String, String, int, java.time.Duration, Throwable, String, String) record()}. 783 * Format: comma-separated {@code key=value} pairs, e.g. {@code "team=payments,region=us-east"}. 784 * When empty (default), no additional tags are passed. 785 * 786 * <h5 class='section'>Notes:</h5><ul> 787 * <li class='note'> 788 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a>. 789 * <li class='note'> 790 * The recorder implementation is responsible for parsing the comma-separated {@code key=value} string. 791 * <li class='note'> 792 * Has no effect when observability is disabled for this operation. 793 * </ul> 794 * 795 * @return The annotation value. 796 * @since 10.0.0 797 */ 798 String metricTags() default ""; 799 800 /** 801 * Per-operation override for {@link Rest#asyncTimeoutMillis() @Rest(asyncTimeoutMillis)}. 802 * 803 * <p> 804 * Configurable timeout (milliseconds) applied to {@link java.util.concurrent.CompletableFuture}-returning 805 * handlers. Default is 30,000 ms inherited from the resource. Set to {@code "0"} to disable the timeout. 806 * 807 * <h5 class='section'>Notes:</h5><ul> 808 * <li class='note'> 809 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a>. 810 * </ul> 811 * 812 * <h5 class='section'>See Also:</h5><ul> 813 * <li class='ja'>{@link Rest#asyncTimeoutMillis()} 814 * </ul> 815 * 816 * @return The annotation value. 817 */ 818 String asyncTimeoutMillis() default ""; 819 820 /** 821 * Per-operation override for {@link Rest#asyncCompletionExecutor() @Rest(asyncCompletionExecutor)}. 822 * 823 * <p> 824 * Names the {@link java.util.concurrent.Executor} bean used to route completion callbacks for this 825 * specific operation through a dedicated thread pool. Empty string (default) inherits from 826 * {@link Rest#asyncCompletionExecutor()}. 827 * 828 * <h5 class='section'>See Also:</h5><ul> 829 * <li class='ja'>{@link Rest#asyncCompletionExecutor()} 830 * </ul> 831 * 832 * @return The annotation value. 833 * @since 10.0.0 834 */ 835 String asyncCompletionExecutor() default ""; 836 837 /** 838 * Supported accept media types. 839 * 840 * <p> 841 * Overrides the media types inferred from the serializers that identify what media types can be produced by the resource. 842 * 843 * <h5 class='section'>Notes:</h5><ul> 844 * <li class='note'> 845 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 846 * (e.g. <js>"$S{mySystemProperty}"</js>). 847 * </ul> 848 * 849 * <h5 class='section'>See Also:</h5><ul> 850 * <li class='jm'>{@link RestOpContext#getSupportedAcceptTypes()} 851 * </ul> 852 * 853 * @return The annotation value. 854 */ 855 String[] produces() default {}; 856 857 /** 858 * Allowed serializer session option keys for this operation (ordered merge, prefix {@code -key} removes a key). 859 * 860 * <p> 861 * Comma-delimited list of session property keys that clients may send via the <js>"X-Juneau-Serializer-Options"</js> 862 * header or <js>"juneauSerializerOptions"</js> query parameter. 863 * Merged on top of resource-level {@link Rest#allowedSerializerOptions()} values. 864 * Use {@link #noInherit()} to replace rather than extend the resource-level list. 865 * 866 * <h5 class='section'>See Also:</h5><ul> 867 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SessionOptions#safe-properties">Safe Properties</a> 868 * </ul> 869 * 870 * @return The annotation value. 871 */ 872 String[] allowedSerializerOptions() default {}; 873 874 /** 875 * Allowed parser session option keys for this operation (ordered merge, prefix {@code -key} removes a key). 876 * 877 * <p> 878 * Comma-delimited list of session property keys that clients may send via the <js>"X-Juneau-Parser-Options"</js> 879 * header or <js>"juneauParserOptions"</js> query parameter. 880 * Merged on top of resource-level {@link Rest#allowedParserOptions()} values. 881 * Use {@link #noInherit()} to replace rather than extend the resource-level list. 882 * 883 * <h5 class='section'>See Also:</h5><ul> 884 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SessionOptions#safe-properties">Safe Properties</a> 885 * </ul> 886 * 887 * @return The annotation value. 888 */ 889 String[] allowedParserOptions() default {}; 890 891 /** 892 * Property names for which less-derived contributions are NOT inherited. 893 * 894 * <p> 895 * Accepted values: {@code "allowedSerializerOptions"}, {@code "allowedParserOptions"}, 896 * {@code "problemDetails"}, {@code "debugMarshalling"}. 897 * Prevents the named property from inheriting values from the enclosing {@code @Rest} annotation. 898 * The {@code noInherit} attribute itself is never inherited. 899 * 900 * <h5 class='section'>See Also:</h5><ul> 901 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SessionOptions">Session Options via HTTP</a> 902 * </ul> 903 * 904 * @return The annotation value. 905 */ 906 String[] noInherit() default {}; 907 908 /** 909 * Declares that this operation's custom method is a read. 910 * 911 * <p> 912 * A request whose request line is safe (<c>GET</c>, <c>HEAD</c>, <c>OPTIONS</c> or <c>TRACE</c>) may be overridden 913 * (through the {@code method} query parameter or an override header, see {@link Rest#allowedMethodParams()} and 914 * {@link Rest#allowedMethodHeaders()}) only to another safe method, or to the method of an operation declared 915 * <c>read=<jk>true</jk></c>. Any other override of a safe request is refused with <c>405 Method Not Allowed</c>, 916 * so a link, a crawler or a prefetcher following a plain <c>GET</c> can never reach an operation that changes state. 917 * 918 * <h5 class='section'>Example:</h5> 919 * <p class='bjava'> 920 * <jc>// Reachable as GET /files/foo.txt?method=VIEW, as well as VIEW /files/foo.txt.</jc> 921 * <ja>@RestOp</ja>(method=<js>"VIEW"</js>, path=<js>"/files/*"</js>, read=<jk>true</jk>) 922 * <jk>public</jk> Reader view(...) {...} 923 * </p> 924 * 925 * <p> 926 * The declaration is the developer's promise that the operation does not change state, exactly as <c>GET</c> 927 * promises. Nothing can verify it. {@link Mutating @Mutating} is the opposite promise. 928 * 929 * <h5 class='section'>Notes:</h5><ul> 930 * <li class='note'> 931 * The attribute is read from the annotation that supplies the operation's method (or, when the method is 932 * inferred from the Java method name, from the nearest <ja>@RestOp</ja>). A subclass that re-declares the method 933 * therefore also re-declares whether it is a read: <c>read=<jk>true</jk></c> on an overridden annotation that 934 * names its own method is replaced along with that method. <c>read=<jk>true</jk></c> on another 935 * <ja>@RestOp</ja> in the chain that names no method would be silently ignored, so it fails the resource when 936 * its operations are assembled. 937 * <li class='note'> 938 * <c>read=<jk>true</jk></c> fails the resource when the method is <c>POST</c>, <c>PUT</c>, <c>PATCH</c>, 939 * <c>DELETE</c>, <c>CONNECT</c>, <js>"*"</js> or <js>"RRPC"</js>, or when the Java method is also 940 * {@link Mutating @Mutating}. On a safe method it is redundant and has no effect. 941 * <li class='note'> 942 * A CSRF or loopback boundary filter still judges a request on the method it claims, so behind a boundary a 943 * <c>GET ?method=VIEW</c> is treated as a write. Prefer path-based links (<c>/view/{file}</c>) for reads. 944 * </ul> 945 * 946 * <h5 class='section'>See Also:</h5><ul> 947 * <li class='ja'>{@link Mutating} 948 * <li class='jm'>{@link MethodSafety#check(java.util.List)} 949 * </ul> 950 * 951 * @return The annotation value. 952 * @since 10.0.0 953 */ 954 boolean read() default false; 955 956 /** 957 * Role guard. 958 * 959 * <p> 960 * An expression defining if a user with the specified roles are allowed to access this method. 961 * 962 * <h5 class='section'>Example:</h5> 963 * <p class='bjava'> 964 * <jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet { 965 * 966 * <ja>@RestOp</ja>( 967 * method=<jsf>GET</jsf>, 968 * path=<js>"/foo"</js>, 969 * roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE && ROLE_SPECIAL)"</js> 970 * ) 971 * <jk>public</jk> Object doGet() { 972 * } 973 * } 974 * </p> 975 * 976 * <h5 class='section'>Notes:</h5><ul> 977 * <li class='note'> 978 * Supports any of the following expression constructs: 979 * <ul> 980 * <li><js>"foo"</js> - Single arguments. 981 * <li><js>"foo,bar,baz"</js> - Multiple OR'ed arguments. 982 * <li><js>"foo | bar | baz"</js> - Multiple OR'ed arguments, pipe syntax. 983 * <li><js>"foo || bar || baz"</js> - Multiple OR'ed arguments, Java-OR syntax. 984 * <li><js>"fo*"</js> - Patterns including <js>'*'</js> and <js>'?'</js>. 985 * <li><js>"fo* & *oo"</js> - Multiple AND'ed arguments, ampersand syntax. 986 * <li><js>"fo* && *oo"</js> - Multiple AND'ed arguments, Java-AND syntax. 987 * <li><js>"fo* || (*oo || bar)"</js> - Parenthesis. 988 * </ul> 989 * <li class='note'> 990 * AND operations take precedence over OR operations (as expected). 991 * <li class='note'> 992 * Whitespace is ignored. 993 * <li class='note'> 994 * <jk>null</jk> or empty expressions always match as <jk>false</jk>. 995 * <li class='note'> 996 * If patterns are used, you must specify the list of declared roles using {@link #rolesDeclared()}. 997 * <li class='note'> 998 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 999 * (e.g. <js>"$L{my.localized.variable}"</js>). 1000 * <li class='note'> 1001 * When defined on parent/child classes and methods, ALL guards within the hierarchy must pass. 1002 * </ul> 1003 * 1004 * @return The annotation value. 1005 */ 1006 String roleGuard() default ""; 1007 1008 /** 1009 * Declared roles. 1010 * 1011 * <p> 1012 * A comma-delimited list of all possible user roles. 1013 * 1014 * <p> 1015 * Used in conjunction with {@link #roleGuard()} is used with patterns. 1016 * 1017 * <h5 class='section'>Example:</h5> 1018 * <p class='bjava'> 1019 * <jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet { 1020 * 1021 * <ja>@RestOp</ja>( 1022 * method=<jsf>GET</jsf>, 1023 * path=<js>"/foo"</js>, 1024 * rolesDeclared=<js>"ROLE_ADMIN,ROLE_READ_WRITE,ROLE_READ_ONLY,ROLE_SPECIAL"</js>, 1025 * roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE && ROLE_SPECIAL)"</js> 1026 * ) 1027 * <jk>public</jk> Object doGet() { 1028 * } 1029 * } 1030 * </p> 1031 * 1032 * @return The annotation value. 1033 */ 1034 String rolesDeclared() default ""; 1035 1036 /** 1037 * Specifies the serializers for marshalling POJOs into response bodies for this method. 1038 * 1039 * <p> 1040 * Serializer are used to convert POJOs to HTTP response bodies. 1041 * <br>Any of the Juneau framework serializers can be used in this setting. 1042 * <br>The serializer selected is based on the request <c>Accept</c> header matched against the values returned by the following method 1043 * using a best-match algorithm: 1044 * <ul class='javatree'> 1045 * <li class='jm'>{@link Serializer#getMediaTypeRanges()} 1046 * </ul> 1047 * 1048 * <p> 1049 * This value overrides serializers specified at the class level using {@link Rest#serializers()}. 1050 * The {@link org.apache.juneau.marshall.serializer.SerializerSet.Inherit SerializerSet.Inherit} class can be used to include values from the parent class. 1051 * 1052 * <h5 class='section'>Example:</h5> 1053 * <p class='bjava'> 1054 * <jc>// Define a REST resource that can produce JSON and HTML.</jc> 1055 * <ja>@Rest</ja>( 1056 * serializers={ 1057 * JsonParser.<jk>class</jk>, 1058 * HtmlParser.<jk>class</jk> 1059 * } 1060 * ) 1061 * <jk>public class</jk> MyResource { 1062 * 1063 * <jc>// Define a REST method that can also produce XML.</jc> 1064 * <ja>@RestOp</ja>( 1065 * method=<jsf>POST</jsf>, 1066 * parsers={ 1067 * SerializerSet.Inherit.<jk>class</jk>, XmlParser.<jk>class</jk> 1068 * } 1069 * ) 1070 * <jk>public void</jk> doPost(MyBean <jv>bean</jv>) { 1071 * ... 1072 * } 1073 * } 1074 * </p> 1075 * 1076 * <p> 1077 * For programmatic equivalents, contribute a {@link SerializerSet} bean via 1078 * {@link Bean @Bean(name="serializers")} (use methodScope to scope to specific operation methods). 1079 * 1080 * <h5 class='section'>See Also:</h5><ul> 1081 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshalling">Marshalling</a> 1082 * </ul> 1083 * 1084 * @return The annotation value. 1085 */ 1086 Class<? extends Serializer>[] serializers() default {}; 1087 1088 /** 1089 * Optional summary for the exposed API. 1090 * 1091 * <p> 1092 * This summary is used in the following locations: 1093 * <ul class='spaced-list'> 1094 * <li> 1095 * The value returned by {@link Operation#getSummary()} in the auto-generated swagger. 1096 * <li> 1097 * The <js>"$RS{operationSummary}"</js> variable. 1098 * <li> 1099 * The summary of the method in the Swagger page. 1100 * </ul> 1101 * 1102 * <h5 class='section'>Notes:</h5><ul> 1103 * <li class='note'> 1104 * Corresponds to the swagger field <c>/paths/{path}/{method}/summary</c>. 1105 * <li class='note'> 1106 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 1107 * (e.g. <js>"$L{my.localized.variable}"</js>). 1108 * </ul> 1109 * 1110 * @return The annotation value. 1111 */ 1112 String summary() default ""; 1113 1114 /** 1115 * Provides swagger-specific metadata on this method. 1116 * 1117 * <p> 1118 * Used to populate the auto-generated OPTIONS swagger documentation. 1119 * 1120 * <p> 1121 * The format of this annotation is JSON when all individual parts are concatenated. 1122 * <br>The starting and ending <js>'{'</js>/<js>'}'</js> characters around the entire value are optional. 1123 * 1124 * <h5 class='section'>Example:</h5> 1125 * <p class='bjava'> 1126 * <ja>@RestOp</ja>( 1127 * method=<jsf>PUT</jsf>, 1128 * path=<js>"/{propertyName}"</js>, 1129 * 1130 * <jc>// Swagger info.</jc> 1131 * swagger={ 1132 * <js>"parameters:["</js>, 1133 * <js>"{name:'propertyName',in:'path',description:'The system property name.'},"</js>, 1134 * <js>"{in:'body',description:'The new system property value.'}"</js>, 1135 * <js>"],"</js>, 1136 * <js>"responses:{"</js>, 1137 * <js>"302: {headers:{Location:{description:'The root URL of this resource.'}}},"</js>, 1138 * <js>"403: {description:'User is not an admin.'}"</js>, 1139 * <js>"}"</js> 1140 * } 1141 * ) 1142 * </p> 1143 * 1144 * <h5 class='section'>Notes:</h5><ul> 1145 * <li class='note'> 1146 * The format is <a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>. 1147 * <br>Multiple lines are concatenated with newlines. 1148 * <li class='note'> 1149 * The starting and ending <js>'{'</js>/<js>'}'</js> characters around the entire value are optional. 1150 * <li class='note'> 1151 * These values are superimposed on top of any Swagger JSON file present for the resource in the classpath. 1152 * <li class='note'> 1153 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerSvlVariables">REST Server SVL Variables</a> 1154 * (e.g. <js>"$L{my.localized.variable}"</js>). 1155 * </ul> 1156 * 1157 * <h5 class='section'>See Also:</h5><ul> 1158 * <li class='ja'>{@link OpSwagger} 1159 * <li class='jc'>{@link SwaggerProvider} 1160 * </ul> 1161 * 1162 * @return The annotation value. 1163 */ 1164 OpSwagger swagger() default @OpSwagger; 1165 1166 /** 1167 * REST method name and path. 1168 * 1169 * <p> 1170 * Can be used to provide a shortened combined form for the {@link #method()} and {@link #path()} values. 1171 * 1172 * <p> 1173 * The following examples are considered equivalent. 1174 * <p class='bjava'> 1175 * <jc>// Normal form</jc> 1176 * <ja>@RestOp</ja>(method=<jsf>PUT</jsf>, path=<js>"/{propertyName}"</js>) 1177 * 1178 * <jc>// Shortened form</jc> 1179 * <ja>@RestOp</ja>(<js>"PUT /{propertyName}"</js>) 1180 * </p> 1181 * 1182 * <h5 class='section'>Notes:</h5><ul> 1183 * <li class='note'> 1184 * The path portion is optional. 1185 * </ul> 1186 * 1187 * @return The annotation value. 1188 */ 1189 String value() default ""; 1190}