This commit introduces support to easily discover resources in remote
service APIs and periodically validating they're still available.
The core concept is a RemoteResource and its primary implementation
DiscoveredResource which consists of a ServiceInstanceProvider and a
TraversalDescription. The service instance provider abstracts the location
of the service the DiscoveredResource is hosted at. Currently there are
two implementations available: a StaticServiceInstanceProvider that — as
the name suggests — returns a statically configured instance, as well as
the DynamicServiceInstanceProvider which takes a DiscoveryClient and service
name as input to dynamically discover the ServiceInstance on request.
The TraversalDefinition is a SAM type that allows to define the path traversals
that shall be executed to discover the target resource within the service
instance. This allows the following configuration:
DiscoveryClient client = …
ServiceInstanceProvider provider = new DynamicServiceInstanceProvider(client, "stores");
RemoteResource resource = new DiscoveredResource(provider, traverson -> traverson.follow("stores", "search", "by-location");
This will cause the following to happen:
1. In this default state the resource is undiscovered and calls to getLink()
will return null.
2. A call to verifyOrDiscover() will trigger resource discovery, i.e. lookup
the service instance using the discovery client, execute the path traversal
as defined and store the final link discovered ("by-location") in the
discovered resource.
3. Calls to getLink() will return that link. Calls to verifyOrDiscover()
will issue a HEAD request to verify the resource is still available and
reset the link if not. Subsequent calls to verifyOrDiscover() will trigger
rediscovery.
That means that we basically shield against either the service instance becoming
unavailable or the resource becoming unavailable within the service instance
(due to some URI restructuring or the like).
The calls to verifyOrDiscover() are currently automated by a RemoteResourceRefresher
which is auto-configured if a RemoteResource is declared as Spring bean
and its initial and fixed delay can be configured via properties in the
spring.cloud.hypermedia namespace.