Skip to content

LendingClub/breeze-http-client

Repository files navigation

breeze-http-client

BreezeHttpClient is a fluent HTTP/REST client interface with plugglable implementions. It is designed to be super easy to use, extensible, and easy to configure.

BreezeHttpClient itself is simply a Java interface for all the common HTTP verbs: GET, PUT, POST, PATCH, and a generic execute method; think java.util.logging but for HTTP. You write your client code around the interface and you can change implementations without touching a line of code. Breeze doesn't introduce any new dependencies on your code, as the core module is pure Java without additional libraries; in fact dependency madness (the tangled mess of conflicting dependencies created when you import multiple large, complex libraries) is the reason it was created. If your implementation doesn't suit you, just import a new implementation, and use a client instance constructed from that implementation. The rest of your code stays the same.

Using BreezeHttpClient

Construction

First, pick an implementation: Spring RestTemplate or JAX-RS Jersey. (You can write your own for say Apache HttpClient in a couple hours.) We'll use RestTemplate; the constructor is the only thing that changes throughout these examples. Note that the RestTemplate implementation comes with a very handy BreezeHttpRestTemplateClientBuilder with lots of flexibility in building your client instance.

BreezeHttpClient client = new BreezeHttpRestTemplateClient();

Basic HTTP commands

Here's how you do a GET; note that by default all requests have JSON content type unless you specify otherwise:

Person person = client.request(url).get(Person.class);

Or POST/PUT:

person = client.request(url).post(Person.class, person);
person.setName("Fred");
client.request(url).put(person);

Headers, path parameters and query string:

Person person = client.request("https://api.persons.com/persons/get/{id}")
    .pathVariable("id", person.getId())
    .queryVariable("foo", "bar")
    .queryVariable("other", "value")
    .header("X-MAGIC-HEADER", magic)
    .get(Person.class);

Generic types such as Lists or Maps, using BreezeHttpType, the equivalent of Gson's TypeToken or Spring's ParameterizedTypeReference:

List<Person> persons = client.request("https://api.persons.com/persons/find/firstName/{firstName}")
    .pathVariable("firstName", person.getFirstName())
    .get(new BreezeHttpType<List<Person>>() {});

Here's how to get a response class that has headers, status code, and response entity:

BreezeHttpResponse<Person> response = client.request("https://api.persons.com/persons/get/{id}")
    .pathVariable("id", person.getId())
    .method(BreezeHttpRequest.GET)
    .execute(Person.class, null);
int httpStatusCode = response.getHttpStatusCode();
Map<String, List<String>> headers = response.getHeaders();
Person person = response.getBody();

How to submit a web form; you can use the fluent style or create an explict BreezeHttpForm object (which is also fluent) and post it directly if your parameter list is dynamic:

Person person = client.request("https://api.persons.com/persons/create")
    .form()
    .param("name", "Fred")
    .param("city", "San Francisco")
    .post(Person.class);

Error Handling

By default, HTTP 4xx/5xx responses result in an exception that includes the response, with the body available as a string; but this is configurable and you can specify the error response body Java class it should try to convert it to:

try {
    Person person = client.request(url).get(Person.class);
} catch (BreezeHttpResponseException e) {
    logger.severe("error getting person, response body: " + e.getResponse().getBody(), e);
}

Generally, Breeze will throw BreezeHttpResponseException if the client received an HTTP response with status code other than 2xx; or BreezeHttpException for any other error executing the request.

Logging

Breeze logs all requests by default, though you can configure it to use a given Logger class, or to not log at all. It's relatively smart about logging; it includes the timing, response code, whether it was a network error (true if there was an IOException somewhere inside the stack trace), and the request object. The logged request includes the names, but not the values, of all the path/query variables and the HTTP headers.

Extending Breeze

Breeze is easy to extend. It's just an interface with an abstract implementation that lets you worry about implementing only the generic execute method. AbstractBreezeHttpClient is designed to be overridden, as are the current existing implementations, so you can easily customize them.

Breeze also has the concept of filters and decorators.

Filters

Filters are executed before the request executes and allow you to configure request defaults or do anything else; see the BreezeHttpFilter interface and UserAgentRequestFilter, which sets "BreezeHttp" as the User-Agent, as an example.

Decorators

Decorators are powerful; they are a full decorator pattern that allow you to decorate your client instance any way you want. You can nest decorators; at Lending Club we use nested decorators to provide Graphite metrics, automatic retries, and Hystrix integration.

Here's an example of decorating an existing BreezeHttpClient instance to retry 100ms, 250ms, then 500ms before giving up and throwing an exception:

BreezeHttpClient retryClient = new RetryDecorator(100, 250, 500).decorate(client);

Notice there are two classes involved in writing the decorator:

  1. The decorated BreezeHttpClient class, which will subclass AbstractDecoratedClient and must implement the decorate method; this is what RetryDecorator.decorate returns
  2. A decorator class that takes an existing BreezeHttpClient instance, and decorates it with its given parameters

In our example, RetryDecorator(100, 250, 500) returns a decorator instance (not a client instance) that can decorate other clients. The result of calling decorate returns a client instance that does whatever the decorator wants first (in this case, try/catch/retry), and delegates anything else to the original client instance it decorated.

Also see EndpointDecorator, which is used to set default URLs.

License

BreezeHttpClient is released under the Apache 2.0 license.

Copyright (C) 2018 Lending Club, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages