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