-
Notifications
You must be signed in to change notification settings - Fork 1
Defining Endpoint Contracts
######The intended use of an endpoint contract is to identify a set of remote services and provide information for successful communication.
You start off by defining and exact copy (mirror) of the endpoint, with all its public methods (services), on a single interface. This interface is then annotated to provide information (metadata) on how to reach the endpoint services and communicate with them using data structures & a common format which both ends understand.
Almost all usage of the ZombieLink API revolves around this set of annotations for populating endpoint metadata.
####1. Identifying Endpoints
- The
@Endpointannotation is used to mark interfaces which specify contracts for remote endpoints. - It takes a mandatory host parameter which specifies the target endpoint host-name for all service invocations.
@Endpoint("www.google.com")
public interface CurrencyConverterEndpoint {}- It can be optionally configured to use a different scheme and port, along with a root-path.
@Endpoint(scheme = "https", value = "www.google.com", port = "443", path = "/ig/calculator")
public interface CurrencyConverterEndpoint {}####2. Defining Services
- Each endpoint service can be identified using the
@Requestannotation.
@Request
public abstract String timestamp();By default each service is executed as an HTTP GET request on the endpoint root-path with no request parameters.
- To populate request parameters, define them as arguments to the service method and annotate them with
@Param.
@Request
public abstract String convert(@Param(name = "q") String conversionString);- A request may also be configured to use an alternative HTTP method type or be invoked on a sub-path from the root.
@Request(path = "/ig/calculator", method = RequestMethod.HTTP_POST)
public abstract String convert(@Param(name = "q") String conversionString);- At times, certain request parameters remain constant for a particular invocation context. For example administrative credentials, language, number of results ..etc. These static request parameters can be defined using
@Request.Paramon theparamsattribute.
@Request(path = "/ig/calculator", params = {@Request.Param(name = "hl", value = "en")})
public abstract String convert(@Param(name = "q") String conversionString);For request parameters which are populated rarely, use an
@Paramannotation with adefaultValueattribute to fallback to if null is received.
####3. Populating Headers Certain requests require special HTTP headers to be set for proper processing at the remote end. These could be Content-Type, User-Agent, Authorization ...etc.
-
Static headers are defined at the request level using the
@HeaderSetannotation which takes a set of@HeaderSet.Headerannotations.
@Request
@HeaderSet({@HeaderSet.Header(name = "Accept", value = "application/rss+xml"),
@HeaderSet.Header(name = "Accept-Charset", value = "utf-8")})
public abstract String getRSSFeed();-
Dynamic headers are populated via service arguments annotated with
@Header.
@Request
public abstract String crawlBlog((@Header("User-Agent") String userAgent)- Certain headers may be changed at the remote end or new headers may be added. To receive headers which may be altered or introduced in the response, simply define the header type as
StringBuilder. This allows the header to be a in-out variable.
@Request
public abstract String echo(@Param(name = "s") String echoString,
@Header("Server") StringBuilder serverName);StringBuilder serverName = new StringBuilder();
String response = endpoint.echo("HELLO", serverName);
logger.info(serverName.toString() + " says " + response);$ Jetty(7.0.x) says HELLOAn alternative to this method is to use a custom response parser and process the returned headers manually.