Skip to content

Documentation

Michael Pratt edited this page Apr 29, 2016 · 3 revisions

API Client Framework Design

This page highlights the core components of the API Client Framework.

ApiComand

This is the core building block for executing remote commands. It extends HystrixCommand so you can invoke it using the standard Hystrix mechanisms (execute, queue, observe). It implements the abstract run method from HystrixCommand, which does the following:

  1. Check for data in command cache to avoid remote service call (if applicable).
  2. Setup Spring Retry context.
  3. Call your custom UriProvider and RemoteServiceCallback.
  4. Put result in command cache before returning to client (if applicable).

This class provides a fluent Builder class to easily build commands, and you'll see that many of the concrete client implementations (like SpringRestClient in robusto-spring) provide helper methods for creating new ApiCommand instances while hiding most of the boiler plate setup.

UriProvider

This interface provides a mechanism for discovering remote services using any lookup strategy you like. At HomeAdvisor, we use Apache Curator for our service registration and discovery, so we use the CuratorUriProvider in robusto-curator, but the core library also includes a ConstantUriProvider implementation that simply uses the same URI for all remote service calls. This is useful if you want to point your client at a load balanced IP/address that never changes.

The single method of this interface takes a RemoteServiceCallback, to which it should pass in an appropriate URL after doing any service discovery or lookup:

public interface UriProvider<T>
{
T execute(RemoteServiceCallback<T> callback);
}

RemoteServiceCallback

This interface provides the mechanism for executing remote service calls using a URL from the UriProvider. This is where you should provide the HTTP client of your choice, or whatever transport you plan to use. At HomeAdvisor we use Spring Web Client quite heavily, but in the past have also used Jersey Client. Not being tied to a specific provider or protocol is what makes the API Client Framework so flexible.

This interface has a single method, which is invoked by the UriProvider after it determines a suitable URL to use:

public interface RemoteServiceCallback<T>
{
T run(String url);
}

AbstractApiClient

This abstract class can be used as a starting point for builder API clients. It is not required to build and execute ApiCommands, but is intended to tie together some of the concepts available in the framework such as command caching and configuration. The SpringRestClient is extension of this class available in robusto-spring, and it uses Spring Web Client to execute HTTP calls. It also provides several helper commands for quickly building ApiCommands.

ClientConfiguration

This class provides a basic set of configuration options that are pertinent to every client, though your own clients can certainly ignore what they don't need from here. It provides reasonable defaults for Hystrix and Spring Retry, as well as some generic connect and read timeout values and settings for command caching.

Extensions of AbstractApiClient can and should create extensions of this class that provide both new configuration values that are specific to their needs, as well as different ways to obtain configuration values. For example, at HomeAdvisor, we have a custom extension of this class that obtains configuration from the application environment. But you could also extend this class to get configuration from external sources such as Spring Cloud or Netflix Archaius

CommandContext

This interface is intended to provide a way to pass information between your clients (which are likely executing on one thread pool) and the _ApiCommand_s, which execute on the Hystrix thread pool. There are currently two key methods you can utilize from this class:

String getCommandName();
Object getCommandAttribute(String key);
void setCommandAttribute(String key, Object val);

The first is a command name, which is used to name Hystrix command and thread pools, and is also used in SpringRestClient and SpringClientConfiguration to lookup properties per command. For example, if you have a client that makes 2 remote calls, the first command might be named ValidatePassword and the second might be called ResetPassword. Using these names, you can configure different connect and request timeouts in SpringRestClient, or different Hystrix thread pool properties, for example. This command will also appear in log messages and the Hystrix metrics stream if you choose to use it.

One other note on command name. The SpringRestClient introduces a method named buildCommandGroupName that you can override to use your own convention. The default behavior is to derive the command name from the Java method name by simply capitalizing the first character. For example, validatePassword would become ValidatePassword.

The other part of the CommandContext interface is command attributes. This is essentially a key/value map that lets you pass arbitrary data to commands. For example, at HomeAdvisor we use it to pass correlation IDs into _ApiCommand_s to track multiple hop API calls between microservices.