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.http.remote;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.io.*;
023import java.lang.annotation.*;
024
025import org.apache.juneau.commons.*;
026import org.apache.juneau.http.*;
027
028/**
029 * Annotation applied to Java methods on REST proxy interface classes.
030 *
031 * <p>
032 * Note that this annotation is optional if you do not need to override any of the values.
033 *
034 * <h5 class='section'>See Also:</h5><ul>
035 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a>
036 * </ul>
037 */
038@Documented
039@Target(METHOD)
040@Retention(RUNTIME)
041@Inherited
042@AnnotationGroup(RemoteOp.class)
043public @interface RemoteOp {
044
045   /**
046    * Defines the HTTP method to use for REST calls.
047    *
048    * <p>
049    * If not specified, then the method is inferred from the Java method name.
050    *
051    * <h5 class='figure'>Example:</h5>
052    * <p class='bjava'>
053    *    <ja>@RemotePost</ja>
054    *    <jk>public void</jk> postPet(...);
055    * </p>
056    *
057    * <br>If the method cannot be inferred, then the default is <js>"GET"</js>.
058    *
059    * <p>
060    * Note that you can also use {@link #value()} to specify the method name and path in shortened form.
061    *
062    * @return The annotation value.
063    */
064   String method() default "";
065
066   /**
067    * REST service path.
068    *
069    * <p>
070    * If you do not specify a path, then the path is inferred from the Java method name.
071    *
072    * <h5 class='figure'>Example:</h5>
073    * <p class='bjava'>
074    *    <ja>@RemotePost</ja>
075    *    <jk>public void</jk> postPet(...);
076    * </p>
077    *
078    * <p>
079    * Note that you can also use {@link #value()} to specify the method name and path in shortened form.
080    *
081    * <ul class='values'>
082    *    <li>An absolute URL.
083    *    <li>A relative URL interpreted as relative to the root URL defined on the <c>RestClient</c> and/or {@link Remote#path()}.
084    *    <li>No path.
085    * </ul>
086    *
087    * @return The annotation value.
088    */
089   String path() default "";
090
091   /**
092    * The value the remote method returns.
093    *
094    * <ul class='values'>
095    *    <li>
096    *       {@link RemoteReturn#BODY} (default) - The body of the HTTP response converted to a POJO.
097    *       <br>The return type on the Java method can be any of the following:
098    *       <ul class='spaced-list'>
099    *          <li>
100    *             <jk>void</jk> - Don't parse any response.  Note that the method will still throw an exception if an
101    *             error HTTP status is returned.
102    *          <li>
103    *             Any parsable POJO - The body of the response will be converted to the POJO using the parser defined
104    *             on the <c>RestClient</c>.
105    *          <li>
106    *             Any POJO annotated with the {@link Response @Response} annotation.
107    *             This allows for response beans to be used which also allows for OpenAPI-based parsing and validation.
108    *          <li>
109    *             <c>HttpResponse</c> - Returns the raw <c>HttpResponse</c> returned by the inner
110    *             <c>HttpClient</c>.
111    *          <li>
112    *             {@link Reader} - Returns access to the raw reader of the response.
113    *          <li>
114    *             {@link InputStream} - Returns access to the raw input stream of the response.
115    *       </ul>
116    *    <li>
117    *       {@link RemoteReturn#STATUS} - The HTTP status code on the response.
118    *       <br>The return type on the Java method can be any of the following:
119    *       <ul>
120    *          <li><jk>int</jk>/<c>Integer</c> - The HTTP response code.
121    *          <li><jk>boolean</jk>/<c>Boolean</c> - <jk>true</jk> if the response code is <c>&lt;400</c>
122    *       </ul>
123    * </ul>
124    *
125    * @return The annotation value.
126    */
127   RemoteReturn returns() default RemoteReturn.BODY;
128
129   /**
130    * REST method name and path.
131    *
132    * <p>
133    * Can be used to provide a shortened combined form for the {@link #method()} and {@link #path()} values.
134    *
135    * <p>
136    * The following examples are considered equivalent.
137    * <p class='bjava'>
138    *    <jc>// Normal form</jc>
139    *    <ja>@RemoteOp</ja>(method=<jsf>PUT</jsf>, path=<js>"/{propertyName}"</js>)
140    *
141    *    <jc>// Shortened form</jc>
142    *    <ja>@RemoteOp</ja>(<js>"PUT /{propertyName}"</js>)
143    * </p>
144    *
145    * <h5 class='section'>Notes:</h5><ul>
146    *    <li class='note'>
147    *       The path portion is optional.
148    * </ul>
149    *
150    * @return The annotation value.
151    */
152   String value() default "";
153
154   /**
155    * Base/host override applied to this method's request.
156    *
157    * <p>
158    * Replaces only the authority+root portion of the request URL while <i>preserving</i> the interface base path, this
159    * method's path, and any <c>{var}</c> templating.  For example, with <c>baseUrl=<js>"http://other-host"</js></c>, an
160    * interface path of <js>"/api"</js> and a method path of <js>"/users/{id}"</js>, the effective URL is
161    * <js>"http://other-host/api/users/{id}"</js>.
162    *
163    * <p>
164    * Precedence (most-specific first): an {@link Url @Url} parameter, then this method-level
165    * value, then the interface-level default ({@link Remote#baseUrl()}), then the client root URL.
166    *
167    * <h5 class='section'>Notes:</h5><ul>
168    *    <li class='note'>
169    *       Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a>
170    *       (e.g. <js>"$S{mySystemProperty}"</js>).
171    *    <li class='note'>
172    *       Only <c>http</c>/<c>https</c> schemes are permitted when the override yields an absolute URL; other schemes
173    *       are rejected (SSRF guardrail).
174    *    <li class='note'>
175    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
176    *       (<c>RestClient.getRemote(...)</c>), with the same http/https-only scheme guard on both.
177    * </ul>
178    *
179    * @return The annotation value.
180    */
181   String baseUrl() default "";
182
183   /**
184    * Selects the request body format (and the {@code Content-Type} header) for this method's request.
185    *
186    * <p>
187    * Names a media type (e.g. <js>"application/xml"</js>).  The next-generation engine selects the matching registered
188    * request serializer from the client's serializer set so the request body bytes are actually written in that
189    * format, and sets the {@code Content-Type} header to this media type &mdash; cleanly replacing the serializer's
190    * default content type (exactly one {@code Content-Type} header is sent).
191    *
192    * <p>
193    * If no registered serializer matches this media type, the client's default serializer is used to write the body
194    * but this media type is still sent as the {@code Content-Type} label (supporting vendor media types such as
195    * <js>"application/vnd.example.v2+json"</js> whose bytes are really the default format).
196    *
197    * <p>
198    * Precedence (most-specific first): this method-level value, then the interface-level default
199    * ({@link Remote#contentType()}).  This dedicated attribute takes precedence over a constant {@code Content-Type}
200    * declared via {@link #headers()} (since it also drives serializer selection); a genuinely caller-supplied
201    * {@code @Header("Content-Type")} parameter still takes effect.
202    *
203    * <h5 class='section'>Notes:</h5><ul>
204    *    <li class='note'>
205    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
206    *       (<c>RestClient.getRemote(...)</c>).
207    * </ul>
208    *
209    * @return The annotation value.
210    */
211   String contentType() default "";
212
213   /**
214    * Sets the {@code Accept} header (and the response parser fallback) for this method's request.
215    *
216    * <p>
217    * Names a media type (e.g. <js>"application/xml"</js>) sent as the request's {@code Accept} header.  Response
218    * parsing remains driven by the <i>response</i> {@code Content-Type} (the server is authoritative about what it
219    * actually sent); this media type is used as the fallback parser only when the response is unlabeled or its
220    * {@code Content-Type} matches no registered parser.
221    *
222    * <p>
223    * If no registered parser matches this media type, the client's default parser is used as the fallback.
224    *
225    * <p>
226    * Precedence (most-specific first): this method-level value, then the interface-level default
227    * ({@link Remote#accept()}).  This dedicated attribute takes precedence over a constant {@code Accept} declared via
228    * {@link #headers()}; a genuinely caller-supplied {@code @Header("Accept")} parameter still takes effect.  Exactly
229    * one {@code Accept} header is sent.
230    *
231    * <h5 class='section'>Notes:</h5><ul>
232    *    <li class='note'>
233    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
234    *       (<c>RestClient.getRemote(...)</c>).
235    * </ul>
236    *
237    * @return The annotation value.
238    */
239   String accept() default "";
240
241   /**
242    * Constant request headers applied to every invocation of this method.
243    *
244    * <p>
245    * Each entry uses the <js>"Name: value"</js> form (the first <js>':'</js> separates name from value), mirroring
246    * {@link Remote#headers()}.  The header is emitted unconditionally on every call &mdash; no corresponding method
247    * parameter is required.  A caller-supplied parameter value for the same name still composes with the constant
248    * (it is not suppressed), and this method-level value takes precedence over an interface-level
249    * {@link Remote#headers()} constant of the same name.
250    *
251    * <h5 class='section'>Notes:</h5><ul>
252    *    <li class='note'>
253    *       Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a>
254    *       (e.g. <js>"$S{mySystemProperty}"</js>).
255    *    <li class='note'>
256    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
257    *       (<c>RestClient.getRemote(...)</c>).
258    * </ul>
259    *
260    * @return The annotation value.
261    */
262   String[] headers() default {};
263
264   /**
265    * Constant request query parameters applied to every invocation of this method.
266    *
267    * <p>
268    * Each entry uses the <js>"name=value"</js> form (the first <js>'='</js> separates name from value).  The query
269    * parameter is emitted unconditionally on every call &mdash; no corresponding method parameter is required.  A
270    * caller-supplied parameter value for the same name still composes with the constant (it is not suppressed), and
271    * this method-level value takes precedence over an interface-level {@link Remote#queryData()} constant of the same
272    * name.
273    *
274    * <h5 class='section'>Notes:</h5><ul>
275    *    <li class='note'>
276    *       Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a>
277    *       (e.g. <js>"$S{mySystemProperty}"</js>).
278    *    <li class='note'>
279    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
280    *       (<c>RestClient.getRemote(...)</c>).
281    * </ul>
282    *
283    * @return The annotation value.
284    */
285   String[] queryData() default {};
286
287   /**
288    * Constant request form-data parameters applied to every invocation of this method.
289    *
290    * <p>
291    * Each entry uses the <js>"name=value"</js> form (the first <js>'='</js> separates name from value).  The form-data
292    * field is emitted unconditionally on every call &mdash; no corresponding method parameter is required.  A
293    * caller-supplied parameter value for the same name still composes with the constant (it is not suppressed), and
294    * this method-level value takes precedence over an interface-level {@link Remote#formData()} constant of the same
295    * name.
296    *
297    * <h5 class='section'>Notes:</h5><ul>
298    *    <li class='note'>
299    *       Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a>
300    *       (e.g. <js>"$S{mySystemProperty}"</js>).
301    *    <li class='note'>
302    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
303    *       (<c>RestClient.getRemote(...)</c>).
304    * </ul>
305    *
306    * @return The annotation value.
307    */
308   String[] formData() default {};
309
310   /**
311    * Lifecycle interceptors applied to every invocation of this method.
312    *
313    * <p>
314    * Each class must implement the next-generation <c>RestCallInterceptor</c> SPI and provide a public no-arg
315    * constructor.  Method-level interceptors run <i>after</i> (closest to the call) any interface-level
316    * ({@link Remote#interceptors()}) and builder-configured interceptors; the three sets are unioned in the order
317    * builder &rarr; interface &rarr; method.
318    *
319    * <h5 class='section'>Notes:</h5><ul>
320    *    <li class='note'>
321    *       The member type is {@code Class<?>[]} (not {@code Class<? extends RestCallInterceptor>[]}) because
322    *       <c>RestCallInterceptor</c> lives in the {@code juneau-rest-client} module, which this annotation's module
323    *       must not depend on; each element is resolved to a <c>RestCallInterceptor</c> at proxy-build time.
324    *    <li class='note'>
325    *       Honored by the next-generation engine (<c>RestClient.remote(...)</c>) only; the classic engine currently
326    *       ignores this attribute.
327    * </ul>
328    *
329    * @return The annotation value.
330    */
331   Class<?>[] interceptors() default {};
332
333   /**
334    * Per-call response/read timeout applied to this method's request.
335    *
336    * <p>
337    * Expressed as a duration string (e.g. <js>"30s"</js>, <js>"1500ms"</js>, <js>"1m"</js>) parsed by Juneau's
338    * duration parser, and wired to the underlying transport's response timeout.  Scalar precedence: this method-level
339    * value overrides the interface-level default ({@link Remote#timeout()}).  Connect timeouts remain a client-level
340    * setting.
341    *
342    * <h5 class='section'>Notes:</h5><ul>
343    *    <li class='note'>
344    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
345    *       (<c>RestClient.getRemote(...)</c>).
346    * </ul>
347    *
348    * @return The annotation value.
349    */
350   String timeout() default "";
351
352   /**
353    * Maximum number of automatic retry attempts for this method's request.
354    *
355    * <p>
356    * A value of {@code 0} (the default) disables retries.  Retries are attempted only on connection failures and on
357    * retryable HTTP statuses ({@code 429} and {@code 5xx}), with a short exponential backoff between attempts.
358    *
359    * <p>
360    * <b>Safety gating (hard rules):</b>
361    * <ul>
362    *    <li>Auto-retry applies only to idempotent verbs (<c>GET</c>/<c>PUT</c>/<c>DELETE</c>/<c>HEAD</c>); non-idempotent
363    *       verbs (<c>POST</c>/<c>PATCH</c>) are retried only when {@link #retryNonIdempotent()} is <jk>true</jk>.
364    *    <li>A request whose body is not repeatable (e.g. a streaming {@link InputStream}/{@link Reader}
365    *       body) is never retried.
366    *    <li>Retries are disabled for streaming return modes ({@link RemoteReturn#RESPONSE}, raw
367    *       {@link InputStream}/{@link Reader} returns, and streaming cursors) and for
368    *       {@link java.util.concurrent.Future}/{@link java.util.concurrent.CompletableFuture} returns.
369    * </ul>
370    *
371    * <p>
372    * Scalar precedence: a positive method-level value overrides the interface-level default ({@link Remote#retries()}).
373    *
374    * <h5 class='section'>Notes:</h5><ul>
375    *    <li class='note'>
376    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
377    *       (<c>RestClient.getRemote(...)</c>).
378    * </ul>
379    *
380    * @return The annotation value.
381    */
382   int retries() default 0;
383
384   /**
385    * Opts a non-idempotent verb (<c>POST</c>/<c>PATCH</c>) into automatic retries.
386    *
387    * <p>
388    * Has no effect unless {@link #retries()} (or {@link Remote#retries()}) is positive.  Even when enabled, a request
389    * with a non-repeatable body is never retried.  The effective value is the logical OR of this method-level value
390    * and the interface-level default ({@link Remote#retryNonIdempotent()}).
391    *
392    * <h5 class='section'>Notes:</h5><ul>
393    *    <li class='note'>
394    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
395    *       (<c>RestClient.getRemote(...)</c>).
396    * </ul>
397    *
398    * @return The annotation value.
399    */
400   boolean retryNonIdempotent() default false;
401
402   /**
403    * Throws a generic exception when the response status is an error ({@code >=400}) and no typed exception from the
404    * method's {@code throws} clause matched.
405    *
406    * <p>
407    * Composes with the typed-exception mapping: a declared exception type whose status code matches the response is
408    * still thrown in preference to the generic exception.  Respects the same return-mode gating as the typed mapping.
409    * The effective value is the logical OR of this method-level value and the interface-level default
410    * ({@link Remote#throwOnError()}).
411    *
412    * <h5 class='section'>Notes:</h5><ul>
413    *    <li class='note'>
414    *       Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine
415    *       (<c>RestClient.getRemote(...)</c>).
416    * </ul>
417    *
418    * @return The annotation value.
419    */
420   boolean throwOnError() default false;
421}