@Remote
The @Remote annotation is used on your interface class to identify it as a REST proxy interface.
The @Remote annotation is optional but often included for code readability.
@Remote(path)
The @Remote(path) annotation is used to define the HTTP path of the REST service.
The path can be an absolute path to your REST service.
@Remote(path="http://localhost:10000/petstore")
public interface PetStore {...}
PetStore store = client.getRemote(PetStore.class);
VarResolver.DEFAULT can also be used in the path.
// URL is specified via a system property.
@Remote(path="$S{PetStoreUrl}")
public interface PetStore {...}
When a relative path is specified, it's relative to the root-url defined on the RestClient used to instantiate the
interface.
@Remote(path="/petstore")
public interface PetStore {...}
RestClient client = RestClient
.create()
.json()
.rootUrl("http://localhost:10000")
.build();
PetStore store = client.getRemote(PetStore.class);
When no path is specified, the root-url defined on the RestClient is used.
@Remote
public interface PetStore {...}
RestClient client = RestClient
.create()
.json()
.rootUrl("http://localhost:10000/petstore")
.build();
PetStore store = client.getRemote(PetStore.class);
@Remote(headers/headerList)
The @Remote(headers) and @Remote(headerList) annotations are used to add headers on all requests.
@Remote(
path="/petstore",
headers={
"Foo: bar",
"Baz: $S{bazProperty}"
},
headerList=MyHeaderList.class
)
public interface PetStore {...}
// Our dynamic supplier.
public class MyHeaderList extends HeaderList {
...
}
headerList is honored only by the classic proxy engine (RestClient.getRemote(...)). Its value type is the
classic Apache-HttpClient HeaderList, which is transport-specific, so the next-generation engine cannot honor it and
emits a one-time build-time warning if it is set. Use headers for transport-agnostic constant headers that work on
both engines.
@Remote(version/versionHeader)
The @Remote(version) and @Remote(versionHeader) annotations are used to specify the client-side version of this interface that can be used on the server side to perform version-specific handling.
@Remote(
path="/petstore",
version="1.2.3" // Adds "Client-Version: 1.2.3" header to all requests.
)
public interface PetStore {...}
This can be used in conjunction with the server-side client-versioning support.
// Call this method if Client-Version is at least 2.0.
// Note that this also matches 2.0.1.
@RestGet(clientVersion="2.0")
public Object foo() {...}
// Call this method if Client-Version is at least 1.1 but less than 2.0.
@RestGet(clientVersion="[1.1,2.0)")
public Object foo() {...}
// Call this method if Client-Version is less than 1.1.
@RestGet(clientVersion="[0,1.1)")
public Object foo() {...}
Request-policy members
@Remote also supports a set of interface-level request-policy members. As of 10.0.0 these are honored by both
the classic (RestClient.getRemote(...)) and next-generation proxy engines — previously several of them were silently
ignored by the classic engine.
| Member | Purpose |
|---|---|
| baseUrl | A base/host override applied to every operation (in place of the client root URL). Must use the http/https scheme. |
| accept | Default Accept header (and response-parser fallback) for every operation. |
| contentType | Default Content-Type header (and request-serializer selector) for every operation. |
| queryData | Constant "name=value" query parameters added to every request. |
| formData | Constant "name=value" form-data parameters added to every request. |
| timeout | Per-call read/socket timeout as a duration string (e.g. "30s", "500ms"). |
| retries | Max automatic retry attempts for safe (idempotent) operations on transport failures and retryable statuses (429/5xx). |
| retryNonIdempotent | Opt non-idempotent verbs (POST/PATCH) into automatic retries. |
| throwOnError | Controls error handling for >= 400 responses (see below). |
Every one of these can also be set per-operation on @RemoteOp (and the
@RemoteGet/@RemotePost/... variants). The method-level value overrides the interface-level value, and the constant
headers/queryData/formData entries are merged (method-level entries win on a name collision).
@Remote(
path="/petstore",
accept="application/json",
timeout="30s",
retries=3,
queryData="apiKey=$S{petstore.apiKey}"
)
public interface PetStore {...}
throwOnError
By default (throwOnError=false) a proxy call lets an HTTP error response (status >= 400) flow through:
- If the method declares a matching HTTP-response exception in its
throwsclause (e.g.throws NotFoundfor a404), that typed exception is thrown. - Otherwise the error body is returned/parsed as the normal return value.
Setting throwOnError=true additionally throws a generic
BasicHttpException
for any unmatched >= 400 response.
Methods returning void (or @RemoteOp(returns=STATUS)) never throw on an error status — a void method discards
the response entirely and a STATUS method reports the code as its return value.
Engine parity
As of 10.0.0 every @Remote/@RemoteOp member is honored by both proxy engines, except for two members that are
genuinely engine-specific. Rather than silently ignore them, the proxy emits a one-time build-time warning when the
member is set on the engine that cannot honor it:
| Member | Honored by | On the other engine |
|---|---|---|
| interceptors | next-generation | The classic engine emits a build-time warning — the classic and next-generation RestCallInterceptor SPI types are nominally incompatible (a single class cannot implement both). |
| headerList | classic | The next-generation engine emits a build-time warning — its value type is the classic transport-specific HeaderList. Use headers for transport-agnostic constant headers. |