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 RemoteGet { 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>// POST /pet</jc> 054 * <ja>@RemoteGet</ja> 055 * <jk>public</jk> Pet getPet(...); 056 * </p> 057 * 058 * <p> 059 * Note that you can also use {@link #value()} to specify the method name and 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><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>@RemoteGet</ja>(path=<js>"/{propertyName}"</js>) 120 * 121 * <jc>// Shortened form</jc> 122 * <ja>@RemoteGet</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 — 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 — 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 — 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 — 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 → interface → 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}