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