Name: java-restclient
Owner: MercadoLibre
Description: A lightweight REST client implementation for Java 1.7+.
Created: 2017-05-22 20:38:58.0
Updated: 2018-04-20 17:32:13.0
Pushed: 2017-07-01 02:17:48.0
Size: 858
Language: Java
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Lightweight REST client implementation for Java 1.7+.
For questions and support please contact services@mercadolibre.com
You must define the repository resolver
ository>
<id>java-restclient-mvn-repo</id>
<url>https://raw.github.com/mercadolibre/java-restclient/mvn-repo/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
pository>
and the dependency itself
endency>
<groupId>com.mercadolibre.restclient</groupId>
<artifactId>restclient-default</artifactId>
<version>0.0.10</version>
pendency>
A RestClient instance uses a collection of RESTPool
to route its requests.
So, first you have to build as many instances of RESTPool
as you need using its builder. Please take also a moment to read about RESTPool
concept.
Pool aPool = RESTPool.builder()
.withName("my_pool")
.build();
Once you have built all of your pool instances, you can build your RestClient
instance.
Every RestClient
instance also contains a default RESTPool
implementation, with typical parameters. Itīll be used when no pool is defined in a request.
Client restClient = RestClient.builder()
.withPool(aPool, bPool)
.build();
This instance is thread safe and it should be shared across resources in your application.
For typical uses, youd only need just one instance of RestClient
in your entire application.
A RESTPool
is a collection of HTTP resource definitions, itīs not just a connection pool.
You can think of it as a separate client, intended to handle some group of resources and that is part of a RestClient
, which instead is intended to bind many RESTPool
instances and abstract HTTP calls.
It groups together connection pool definitions (max connections, socket timeout, etc) with high level features such as proxy, basic authentication, interceptors and so on.
For every request you make you must explicitly specify which RESTPool
should be used, in case you donīt want your request to be handled by the provided default RESTPool
.
Some typical uses are
RESTPool
instance for each one, the former with short timeouts and the latter with longer ones.RESTPool
with no proxy for internal usage and another with a proxy for the rest.RESTPool
with a larger number of connections to handle them.RESTPool
with a more aggressive RetryStrategy
.You can use your RestClient
instance right away, by routing requests through its default pool.
onse response = restClient.get("http://yourdomain.com/resource");
In a similar way, you can add custom headers to your request
ers headers = new Headers().add("Content-Type", "text/plain");
onse response = restClient.get("http://yourdomain.com/resource", headers);
In case you want to send a request with body, you should do it as a byte array.
[] body = "{\"text\":\"hello\"}".getBytes();
onse response = restClient.post("http://yourdomain.com/resource", body);
Headers are allowed in a similar way
ers headers = new Headers().add("Content-Type", "text/plain");
[] body = "hello".getBytes();
onse response = restClient.post("http://yourdomain.com/resource", headers, body);
A Response
object provides methods to get HTTP response data
onse response = restClient.get("http://yourdomain.com/resource");
status = response.getStatus();
headers = response.getHeaders();
[] body = response.getBytes();
Also, if you have a Serializer
registered for current Content-Type, you can get its marshaled data as Object
or as another you provide.
onse response = restClient.get("http://yourdomain.com/get_item");
ct body = response.getData();
body = response.getData(Item.class);
In case you would like to route your requests only through the default pool, you could use the provided RestClient
default implementation.
onse response = RestClient.getDefault().get("http://yourdomain.com/resource");
When you use a default implementation the following features apply
It's possible to specify many request scoped features for sync and async calls. Many of then can also be specified poolwise.
onse response = restClient.withPool(aPool).get("http://yourdomain.com/resource");
onse response = restClient.withProxy("http://proxy",80).get("http://yourdomain.com/resource");
onse response = restClient.withAuthentication("http://auth", 80, "user", "pass").get("http://yourdomain.com/resource");
An interceptor applies over a request, just before sending it; or over a response, right after receiving it. In both cases, they are stored in a deque, so you can easily manage the order in which they are applied.
To intercept a request, just implement a RequestInterceptor
, or maybe one of the provided may help.
onse response = restClient.withInterceptorFirst(new YourRequestInterceptor()).get("http://yourdomain.com/resource");
ava
onse response = restClient.withInterceptorLast(new YourRequestInterceptor()).get("http://yourdomain.com/resource");
As for response interceptors, provide your own by implementing ResponseInterceptor
.
onse response = restClient.withInterceptorFirst(new YourResponseInterceptor()).get("http://yourdomain.com/resource");
ava
onse response = restClient.withInterceptorLast(new YourResponseInterceptor()).get("http://yourdomain.com/resource");
You can provide an OutputStream
where you want your data to be streamed. Notice that trying to also fetch data from associated response will be null.
Remember to close stream upon completion.
onse response = restClient.get("http://yourdomain.com/resource", yourOutputStream);
To upload multipart data, just add parts and make your request.
onse response = restClient
.withPart(aPart)
.withPart(bPart)
.post("http://yourdomain.com/resource");
You may define a retry strategy that specifies when a response is to be considered a failure, and an action thatll be run on each retry call.
We provide two basic strategies
Itll just retry for a fixed number of times and wait for a fixed interval between runs
onse response = restClient
.withRetryStrategy(new SimpleRetryStrategy(MAX_RETRIES, WAIT_MS))
.get("http://yourdomain.com/resource");
Itīll increase wait time between retries between a min and a max value, growing exponentially between runs
onse response = restClient
.withRetryStrategy(new ExponentialBackoffRetryStrategy(MIN_MS, MAX_MS))
.get("http://yourdomain.com/resource");
We provide local and memcached cache implementations, thatll cache requests based on their Cache-Control header info.
All cache implementations can be chained, to be made multilevel. Every constructor has a version with the next level as the last argument.
For more information about Cache-Control you can take a look here and here.
Cache cache = new RESTLocalCache("my_cache", MAX_ELEMENTS);
onse response = restClient
.withCache(cache)
.get("http://yourdomain.com/resource");
In this case, you must provide a wrapper over your Memcached client
MemcachedClient client = new MyRESTMemcachedClient();
Cache cache = new RESTMemcachedCache("my_cache", client);
onse response = restClient
.withCache(cache)
.get("http://yourdomain.com/resource");
Asynchronous calls are handled similar to their synchronous counterpart, we just return a Future<Response>
as a promise of call completion.
A RestException
is raised if request could not be built up, but every other exception will be wrapped around Futureīs ExecutionException
upon get.
Caching and retries are handled under the hood. Both of them, as well as call themselves, are handled in a non blocking way.
As an example, an async GET could be made as
re<Response> response = restClient.asyncGet("http://yourdomain.com/resource");
status = response.get().getStatus();
There's also the possibility to specify an instance of Callback<Response>
as a completion callback for current requst, instead of getting a Future
instance.
Client.asyncGet("http://yourdomain.com/resource", myCallback);
When you obtain a Response
, you can get its raw data as a byte array by calling its getBytes()
method. Also you can parse its content according to received Content-Type header, if you previously had registered a serializer capable of handling it.
alizers.register(ContentType.APPLICATION_JSON, mySerializer);
A Jackson based JSON parser is shipped with restclient-default
package, as well as parsers for usual contents. You can override them by registering a custom Serializer
as shown.
We use slf4j as a common interface for different logging implementations. If you want to collect Rest Client logs, first you must add the binding for your current logging implementation.
For example, if you use log4j 1.2.x, you should add
endency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
pendency>
Then you should specify which level you want to apply to restClientLogger
logger.
We provide a mock server for testing, which is immediately available in test environment. You can specify which response should be given for a specific request, or if the client should fail instead.
You can forget about mock and cache cleanup after each test, if you make your tests extend from RestClientTestBase
.
endency>
<groupId>com.mercadolibre.restclient</groupId>
<artifactId>restclient-core</artifactId>
<version>0.0.10</version>
<classifier>tests</classifier>
<scope>test</scope>
pendency>
In this simple example, we add a response with status code 200 and a plain text response body for any GET to “http://localhost/endpoint””
Response.builder()
.withURL("http://localhost/endpoint")
.withMethod(GET)
.withStatusCode(200)
.withResponseHeader(ContentType.HEADER_NAME, ContentType.TEXT_PLAIN.toString())
.withResponseHeader("Cache-Control", "max-age=3600")
.withResponseBody("ok")
.build();
A simple in-memory cache is also available for testing purposes.