Fork me on GitHub

REST Client Enhancements

Soabase augments the standard Dropwizard HttpClient and Jersey Client with a number of features useful in an SOA environment.

Service Discovery integration with retries

With the REST Client Enhancements, you can call APIs for services and have Service Discovery choose which service instance to use. Simply use the Soabase hostname format for the url passed to the REST client:

//0.service-name/path/to/api

You can also use the utility ClientUtils.serviceNameToUriForm(). When the enhanced REST clients see this hostname format, they call Discovery.getInstance() using the service name and substituting the returned instance's host and port. If the request needs to be retried (due to errors, etc.) a new instance is retrieved and substituted.

Request ID

In an SOA, multiple services are usually involved in handling an end-user request. For tracking and auditing, it's useful to have a way to correlate all of them to the initiating end-user request. Soabase enables this via the Request ID. Via the ClientFilter every incoming request is assigned a unique request ID. Further, the REST client enhancements set a header on outgoing requests with this request ID. The ClientFilter looks for this header and uses the request ID from it when found.

Usage

To use the enhanced REST clients use Soabase's ClientBuilder:

ClientBuilder builder = new ClientBuilder(environment);
builder.buildJerseyClient(jerseyClientConfig, clientName);  // for Jersey client
builder.buildHttpClient(httpClientConfig, clientName);      // for Apache client

The ClientBuilder registers the clients in Jersey's dependency injection system. E.g.

@Path(...)
public class MyResource {
    @Inject
    public MyResource(Client jerseyClient) {
        ...
    }
}

The client can also be accessed from SoaFeatures. E.g.

SoaFeatures features = SoaBundle.getFeatures(environment);
Client jerseyClient = features.getNamedRequired(Client.class, clientName);

Using a Different REST Client

To use a REST client other than Jersey or Apache, use the Soabase client APIs and utility classes to enhance your client. The general form for your code is:

// early in your application, create a RetryComponents instance. This is reusable.
ClientBuilder clientBuilder = new ClientBuilder(...);
RetryComponents retryComponents = clientBuilder.getRetryComponents();

// in your method(s) that make REST requests
RequestId.HeaderSetter<REQUEST_TYPE> headerSetter = ... // a functor to set request headers
RequestRunner<REQUEST_TYPE> runner = new RequestRunner<>(retryComponents, headerSetter, requestUri, requestMethod);
while ( requestRunner.shouldContinue() ) {
    URI uri = requestRunner.prepareRequest(request);
    request.setUri(uri);    // substitute the returned URI for your request
    try {
        Response response = ... invoke your request
        if ( requestRunner.isSuccessResponse(response.getStatus()) ) {
            return response;
        }
    } catch ( Exception e ) {
        if ( !requestRunner.shouldBeRetried(e) ) {
            throw e;
        }
    }
}
throw new Exception("Retries expired: " + requestRunner.getOriginalUri());