![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.rest.annotation.RestOp Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * 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. *
// ***************************************************************************************************************************
package org.apache.juneau.rest.annotation;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
import java.nio.charset.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.converter.*;
import org.apache.juneau.rest.guard.*;
import org.apache.juneau.rest.httppart.*;
import org.apache.juneau.rest.matcher.*;
import org.apache.juneau.rest.servlet.*;
import org.apache.juneau.rest.swagger.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.http.remote.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.dto.swagger.*;
import org.apache.juneau.encoders.*;
/**
* Identifies a REST operation Java method on a {@link RestServlet} implementation class.
*
* See Also:
*/
@Target(METHOD)
@Retention(RUNTIME)
@Inherited
@ContextApply(RestOpAnnotation.RestOpContextApply.class)
@AnnotationGroup(RestOp.class)
public @interface RestOp {
/**
* Specifies whether this method can be called based on the client version.
*
*
* The client version is identified via the HTTP request header identified by
* {@link Rest#clientVersionHeader() @Rest(clientVersionHeader)} which by default is "Client-Version" .
*
*
* This is a specialized kind of {@link RestMatcher} that allows you to invoke different Java methods for the same
* method/path based on the client version.
*
*
* The format of the client version range is similar to that of OSGi versions.
*
*
* In the following example, the Java methods are mapped to the same HTTP method and URL "/foobar" .
*
* // Call this method if Client-Version is at least 2.0.
* // Note that this also matches 2.0.1.
* @RestOp (method=GET , path="/foobar" , clientVersion="2.0" )
* public Object method1() {...}
*
* // Call this method if Client-Version is at least 1.1, but less than 2.0.
* @RestOp (method=GET , path="/foobar" , clientVersion="[1.1,2.0)" )
* public Object method2() {...}
*
* // Call this method if Client-Version is less than 1.1.
* @RestOp (method=GET , path="/foobar" , clientVersion="[0,1.1)" )
* public Object method3() {...}
*
*
*
* It's common to combine the client version with transforms that will convert new POJOs into older POJOs for
* backwards compatibility.
*
* // Call this method if Client-Version is at least 2.0.
* @RestOp (method=GET , path="/foobar" , clientVersion="2.0" )
* public NewPojo newMethod() {...}
*
* // Call this method if X-Client-Version is at least 1.1, but less than 2.0.
* @RestOp (method=GET , path="/foobar" , clientVersion="[1.1,2.0)" )
* @BeanConfig(swaps=NewToOldSwap.class )
* public NewPojo oldMethod() {
* return newMethod();
* }
*
*
* Note that in the previous example, we're returning the exact same POJO, but using a transform to convert it into
* an older form.
* The old method could also just return back a completely different object.
* The range can be any of the following:
*
* "[0,1.0)" = Less than 1.0. 1.0 and 1.0.0 does not match.
* "[0,1.0]" = Less than or equal to 1.0. Note that 1.0.1 will match.
* "1.0" = At least 1.0. 1.0 and 2.0 will match.
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#clientVersionHeader(String)}
*
*
* @return The annotation value.
*/
String clientVersion() default "";
/**
* Supported content media types.
*
*
* Overrides the media types inferred from the parsers that identify what media types can be consumed by the resource.
*
*
Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#consumes(MediaType...)}
*
*
* @return The annotation value.
*/
String[] consumes() default {};
/**
* Class-level response converters.
*
*
* Associates one or more {@link RestConverter converters} with this method.
*
*
See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#converters()} - Registering converters with REST resources.
*
*
* @return The annotation value.
*/
Class extends RestConverter>[] converters() default {};
/**
* Enable debug mode.
*
*
* Enables the following:
*
* -
* HTTP request/response bodies are cached in memory for logging purposes.
*
-
* Request/response messages are automatically logged.
*
*
*
* "true" - Debug is enabled for all requests.
* "false" - Debug is disabled for all requests.
* "conditional" - Debug is enabled only for requests that have a Debug: true header.
* "" (or anything else) - Debug mode is inherited from class.
*
*
* Notes:
* -
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#debugEnablement()}
*
*
* @return The annotation value.
*/
String debug() default "";
/**
* Default Accept header.
*
*
* The default value for the Accept header if not specified on a request.
*
*
* This is a shortcut for using {@link #defaultRequestHeaders()} for just this specific header.
*
* @return The annotation value.
*/
String defaultAccept() default "";
/**
* Default character encoding.
*
*
* The default character encoding for the request and response if not specified on the request.
*
*
Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#defaultCharset(Charset)}
*
- {@link org.apache.juneau.rest.RestOpContext.Builder#defaultCharset(Charset)}
*
- {@link Rest#defaultCharset}
*
*
* @return The annotation value.
*/
String defaultCharset() default "";
/**
* Default Content-Type header.
*
*
* The default value for the Content-Type header if not specified on a request.
*
*
* This is a shortcut for using {@link #defaultRequestHeaders()} for just this specific header.
*
* @return The annotation value.
*/
String defaultContentType() default "";
/**
* Specifies default values for form-data parameters.
*
*
* Strings are of the format "name=value" .
*
*
* Affects values returned by {@link RestRequest#getFormParam(String)} when the parameter is not present on the
* request.
*
*
Example:
*
* @RestOp (method=POST , path="/*" , defaultRequestFormData={"foo=bar" })
* public String doPost(@FormData ("foo" ) String foo ) {...}
*
*
* Notes:
* -
* You can use either
':' or '=' as the key/value delimiter.
* -
* Key and value is trimmed of whitespace.
*
-
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* @return The annotation value.
*/
String[] defaultRequestFormData() default {};
/**
* Specifies default values for query parameters.
*
*
* Strings are of the format "name=value" .
*
*
* Affects values returned by {@link RestRequest#getQueryParam(String)} when the parameter is not present on the request.
*
*
Example:
*
* @RestOp (method=GET , path="/*" , defaultRequestQueryData={"foo=bar" })
* public String doGet(@Query ("foo" ) String foo ) {...}
*
*
* Notes:
* -
* You can use either
':' or '=' as the key/value delimiter.
* -
* Key and value is trimmed of whitespace.
*
-
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* @return The annotation value.
*/
String[] defaultRequestQueryData() default {};
/**
* Default request attributes.
*
*
* Specifies default values for request attributes if they're not already set on the request.
*
*
* Affects values returned by the following methods:
*
* - {@link RestRequest#getAttribute(String)}.
*
- {@link RestRequest#getAttributes()}.
*
*
* Example:
*
* // Defined via annotation resolving to a config file setting with default value.
* @Rest (defaultRequestAttributes={"Foo=bar" , "Baz: $C{REST/myAttributeValue}" })
* public class MyResource {
*
* // Override at the method level.
* @RestGet (defaultRequestAttributes={"Foo: bar" })
* public Object myMethod() {...}
* }
*
*
*
* Notes:
* -
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#defaultRequestAttributes(NamedAttribute...)}
*
- {@link Rest#defaultRequestAttributes()}
*
*
* @return The annotation value.
*/
String[] defaultRequestAttributes() default {};
/**
* Default request headers.
*
*
* Specifies default values for request headers if they're not passed in through the request.
*
*
Example:
*
* // Assume "text/json" Accept value when Accept not specified
* @RestOp (method=GET , path="/*" , defaultRequestHeaders={"Accept: text/json" })
* public String doGet() {...}
*
*
* Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#defaultRequestHeaders(org.apache.http.Header...)}
*
*
* @return The annotation value.
*/
String[] defaultRequestHeaders() default {};
/**
* Default response headers.
*
*
* Specifies default values for response headers if they're not overwritten during the request.
*
*
Example:
*
* // Assume "text/json" Accept value when Accept not specified
* @RestOp (method=GET , path="/*" , defaultResponseHeaders={"Content-Type: text/json" })
* public String doGet() {...}
*
*
* Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#defaultResponseHeaders(org.apache.http.Header...)}
*
*
* @return The annotation value.
*/
String[] defaultResponseHeaders() default {};
/**
* Optional description for the exposed API.
*
*
* This description is used in the following locations:
*
* -
* The value returned by {@link Operation#getDescription()} in the auto-generated swagger.
*
-
* The
"$RS{operationDescription}" variable.
* -
* The description of the method in the Swagger page.
*
*
* Notes:
* -
* Corresponds to the swagger field
/paths/{path}/{method}/description .
* -
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
*
*
* @return The annotation value.
*/
String[] description() default {};
/**
* Specifies the compression encoders for this method.
*
*
* Encoders are used to enable various kinds of compression (e.g. "gzip" ) on requests and responses.
*
*
* This value overrides encoders specified at the class level using {@link Rest#encoders()}.
* The {@link org.apache.juneau.encoders.EncoderSet.Inherit} class can be used to include values from the parent class.
*
*
Example:
*
* // Define a REST resource that handles GZIP compression.
* @Rest (
* encoders={
* GzipEncoder.class
* }
* )
* public class MyResource {
*
* // Define a REST method that can also use a custom encoder.
* @RestOp (
* method=GET ,
* encoders={
* EncoderSet.Inherit.class , MyEncoder.class
* }
* )
* public MyBean doGet() {
* ...
* }
* }
*
*
*
* The programmatic equivalent to this annotation is:
*
* RestOpContext.Builder builder = RestOpContext.create (method ,restContext );
* builder .getEncoders().set(classes );
*
*
* See Also:
* - Encoders
*
*
* @return The annotation value.
*/
Class extends Encoder>[] encoders() default {};
/**
* Method-level guards.
*
*
* Associates one or more {@link RestGuard RestGuards} with this method.
*
*
See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#guards()}
*
*
* @return The annotation value.
*/
Class extends RestGuard>[] guards() default {};
/**
* Method matchers.
*
*
* Associates one more more {@link RestMatcher RestMatchers} with this method.
*
*
* Matchers are used to allow multiple Java methods to handle requests assigned to the same URL path pattern, but
* differing based on some request attribute, such as a specific header value.
*
*
See Also:
* - {@link RestMatcher}
*
*
* @return The annotation value.
*/
Class extends RestMatcher>[] matchers() default {};
/**
* The maximum allowed input size (in bytes) on HTTP requests.
*
*
* Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting
* in out-of-memory errors which could affect system stability.
*
*
Example:
*
* @RestOp (
* maxInput="100M"
* )
*
*
* Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestContext.Builder#maxInput(String)}
*
- {@link org.apache.juneau.rest.RestOpContext.Builder#maxInput(String)}
*
- {@link Rest#maxInput}
*
*
* @return The annotation value.
*/
String maxInput() default "";
/**
* REST method name.
*
*
* Typically "GET" , "PUT" , "POST" , "DELETE" , or "OPTIONS" .
*
*
* Method names are case-insensitive (always folded to upper-case).
*
*
* Note that you can use {@link org.apache.juneau.http.HttpMethod} for constant values.
*
*
* Note that you can also use {@link #value()} to specify the method name and path in shortened form.
*
*
* Besides the standard HTTP method names, the following can also be specified:
*
* -
*
"*"
* - Denotes any method.
*
Use this if you want to capture any HTTP methods in a single Java method.
*
The {@link Method @Method} annotation and/or {@link RestRequest#getMethod()} method can be used to
* distinguish the actual HTTP method name.
* -
*
""
* - Auto-detect.
*
The method name is determined based on the Java method name.
*
For example, if the method is doPost(...) , then the method name is automatically detected
* as "POST" .
*
Otherwise, defaults to "GET" .
* -
*
"RRPC"
* - Remote-proxy interface.
*
This denotes a Java method that returns an object (usually an interface, often annotated with the
* {@link Remote @Remote} annotation) to be used as a remote proxy using
* RestClient.getRemoteInterface(Class<T> interfaceClass, String url) .
*
This allows you to construct client-side interface proxies using REST as a transport medium.
*
Conceptually, this is simply a fancy POST against the url "/{path}/{javaMethodName}"
* where the arguments are marshalled from the client to the server as an HTTP content containing an array of
* objects, passed to the method as arguments, and then the resulting object is marshalled back to the client.
* -
* Anything else
* - Overloaded non-HTTP-standard names that are passed in through a
&method=methodName URL
* parameter.
*
*
* @return The annotation value.
*/
String method() default "";
/**
* Dynamically apply this annotation to the specified methods.
*
* See Also:
*
* @return The annotation value.
*/
String[] on() default {};
/**
* Specifies the parsers for converting HTTP request bodies into POJOs for this method.
*
*
* Parsers are used to convert the content of HTTP requests into POJOs.
*
Any of the Juneau framework parsers can be used in this setting.
*
The parser selected is based on the request Content-Type header matched against the values returned by the following method
* using a best-match algorithm:
*
* - {@link Parser#getMediaTypes()}
*
*
*
* This value overrides parsers specified at the class level using {@link Rest#parsers()}.
* The {@link org.apache.juneau.parser.ParserSet.Inherit} class can be used to include values from the parent class.
*
*
Example:
*
* // Define a REST resource that can consume JSON and HTML.
* @Rest (
* parsers={
* JsonParser.class ,
* HtmlParser.class
* }
* )
* public class MyResource {
*
* // Define a REST method that can also consume XML.
* @RestOp (
* method=POST ,
* parsers={
* ParserSet.Inherit.class , XmlParser.class
* }
* )
* public void doPost(MyBean bean ) {
* ...
* }
* }
*
*
*
* The programmatic equivalent to this annotation is:
*
* RestOpContext.Builder builder = RestOpContext.create (method ,restContext );
* builder .getParsers().set(classes );
*
*
* See Also:
* - Marshalling
*
*
* @return The annotation value.
*/
Class>[] parsers() default {};
/**
* Optional path pattern for the specified method.
*
*
* Appending "/*" to the end of the path pattern will make it match any remainder too.
*
Not appending "/*" to the end of the pattern will cause a 404 (Not found) error to occur if the exact
* pattern is not found.
*
*
* The path can contain variables that get resolved to {@link org.apache.juneau.http.annotation.Path @Path} parameters.
*
*
Examples:
*
* @RestOp (method=GET , path="/myurl/{foo}/{bar}/{baz}/*" )
*
*
* @RestOp (method=GET , path="/myurl/{0}/{1}/{2}/*" )
*
*
*
* If you do not specify a path name, then the path name is inferred from the Java method name.
*
*
Example:
*
* // Path is assumed to be "/foo".
* @RestOp (method=GET )
* public void foo() {...}
*
*
*
* If you also do not specify the {@link #method()} and the Java method name starts with "get" , "put" , "post" , or "deleted" ,
* then the HTTP method name is stripped from the inferred path.
*
*
Examples:
*
* // Method is GET, path is "/foo".
* @RestOp
* public void getFoo() {...}
*
*
* // Method is DELETE, path is "/bar".
* @RestOp
* public void deleteBar() {...}
*
*
* // Method is GET, path is "/foobar".
* @RestOp
* public void foobar() {...}
*
*
* // Method is GET, path is "/".
* @RestOp
* public void get() {...}
*
*
*
* Note that you can also use {@link #value()} to specify the method name and path in shortened form.
*
*
See Also:
* - {@link org.apache.juneau.http.annotation.Path}
*
*
* @return The annotation value.
*/
String[] path() default {};
/**
* Supported accept media types.
*
*
* Overrides the media types inferred from the serializers that identify what media types can be produced by the resource.
*
*
Notes:
* -
* Supports SVL Variables
* (e.g.
"$S{mySystemProperty}" ).
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#produces(MediaType...)}
*
*
* @return The annotation value.
*/
String[] produces() default {};
/**
* Role guard.
*
*
* An expression defining if a user with the specified roles are allowed to access this method.
*
*
Example:
*
* public class MyResource extends BasicRestServlet {
*
* @RestOp (
* method=GET ,
* path="/foo" ,
* roleGuard="ROLE_ADMIN || (ROLE_READ_WRITE && ROLE_SPECIAL)"
* )
* public Object doGet() {
* }
* }
*
*
* Notes:
* -
* Supports any of the following expression constructs:
*
* "foo" - Single arguments.
* "foo,bar,baz" - Multiple OR'ed arguments.
* "foo | bar | baz" - Multiple OR'ed arguments, pipe syntax.
* "foo || bar || baz" - Multiple OR'ed arguments, Java-OR syntax.
* "fo*" - Patterns including '*' and '?' .
* "fo* & *oo" - Multiple AND'ed arguments, ampersand syntax.
* "fo* && *oo" - Multiple AND'ed arguments, Java-AND syntax.
* "fo* || (*oo || bar)" - Parenthesis.
*
* -
* AND operations take precedence over OR operations (as expected).
*
-
* Whitespace is ignored.
*
-
*
null or empty expressions always match as false .
* -
* If patterns are used, you must specify the list of declared roles using {@link #rolesDeclared()} or {@link org.apache.juneau.rest.RestOpContext.Builder#rolesDeclared(String...)}.
*
-
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
* -
* When defined on parent/child classes and methods, ALL guards within the hierarchy must pass.
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#roleGuard(String)}
*
*
* @return The annotation value.
*/
String roleGuard() default "";
/**
* Declared roles.
*
*
* A comma-delimited list of all possible user roles.
*
*
* Used in conjunction with {@link #roleGuard()} is used with patterns.
*
*
Example:
*
* public class MyResource extends BasicRestServlet {
*
* @RestOp (
* method=GET ,
* path="/foo" ,
* rolesDeclared="ROLE_ADMIN,ROLE_READ_WRITE,ROLE_READ_ONLY,ROLE_SPECIAL" ,
* roleGuard="ROLE_ADMIN || (ROLE_READ_WRITE && ROLE_SPECIAL)"
* )
* public Object doGet() {
* }
* }
*
*
* See Also:
* - {@link org.apache.juneau.rest.RestOpContext.Builder#rolesDeclared(String...)}
*
*
* @return The annotation value.
*/
String rolesDeclared() default "";
/**
* Specifies the serializers for marshalling POJOs into response bodies for this method.
*
*
* Serializer are used to convert POJOs to HTTP response bodies.
*
Any of the Juneau framework serializers can be used in this setting.
*
The serializer selected is based on the request Accept header matched against the values returned by the following method
* using a best-match algorithm:
*
* - {@link Serializer#getMediaTypeRanges()}
*
*
*
* This value overrides serializers specified at the class level using {@link Rest#serializers()}.
* The {@link org.apache.juneau.serializer.SerializerSet.Inherit} class can be used to include values from the parent class.
*
*
Example:
*
* // Define a REST resource that can produce JSON and HTML.
* @Rest (
* serializers={
* JsonParser.class ,
* HtmlParser.class
* }
* )
* public class MyResource {
*
* // Define a REST method that can also produce XML.
* @RestOp (
* method=POST ,
* parsers={
* SerializerSet.Inherit.class , XmlParser.class
* }
* )
* public void doPost(MyBean bean ) {
* ...
* }
* }
*
*
*
* The programmatic equivalent to this annotation is:
*
* RestOpContext.Builder builder = RestOpContext.create (method ,restContext );
* builder .getSerializers().set(classes );
*
*
* See Also:
* - Marshalling
*
*
* @return The annotation value.
*/
Class extends Serializer>[] serializers() default {};
/**
* Optional summary for the exposed API.
*
*
* This summary is used in the following locations:
*
* -
* The value returned by {@link Operation#getSummary()} in the auto-generated swagger.
*
-
* The
"$RS{operationSummary}" variable.
* -
* The summary of the method in the Swagger page.
*
*
* Notes:
* -
* Corresponds to the swagger field
/paths/{path}/{method}/summary .
* -
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
*
*
* @return The annotation value.
*/
String summary() default "";
/**
* Provides swagger-specific metadata on this method.
*
*
* Used to populate the auto-generated OPTIONS swagger documentation.
*
*
* The format of this annotation is JSON when all individual parts are concatenated.
*
The starting and ending '{' /'}' characters around the entire value are optional.
*
*
Example:
*
* @RestOp (
* method=PUT ,
* path="/{propertyName}" ,
*
* // Swagger info.
* swagger={
* "parameters:[" ,
* "{name:'propertyName',in:'path',description:'The system property name.'}," ,
* "{in:'body',description:'The new system property value.'}" ,
* "]," ,
* "responses:{" ,
* "302: {headers:{Location:{description:'The root URL of this resource.'}}}," ,
* "403: {description:'User is not an admin.'}" ,
* "}"
* }
* )
*
*
* Notes:
* -
* The format is Swagger.
*
Multiple lines are concatenated with newlines.
* -
* The starting and ending
'{' /'}' characters around the entire value are optional.
* -
* These values are superimposed on top of any Swagger JSON file present for the resource in the classpath.
*
-
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
*
*
* See Also:
* - {@link OpSwagger}
*
- {@link SwaggerProvider}
*
*
* @return The annotation value.
*/
OpSwagger swagger() default @OpSwagger;
/**
* REST method name and path.
*
*
* Can be used to provide a shortened combined form for the {@link #method()} and {@link #path()} values.
*
*
* The following examples are considered equivalent.
*
* // Normal form
* @RestOp (method=PUT , path="/{propertyName}" )
*
* // Shortened form
* @RestOp ("PUT /{propertyName}" )
*
*
* Notes:
* -
* The path portion is optional.
*
*
* @return The annotation value.
*/
String value() default "";
}