Soabase augments the standard Dropwizard HttpClient and Jersey Client with a number of features useful in an SOA environment.
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.
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.
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);
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());