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><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 — 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 — 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 — 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 — 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 → interface → 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}