Skip to content

Defining Endpoint Contracts 1.2.3

Lahiru Sahan Jayasinghe edited this page Jan 1, 2014 · 1 revision

######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 copying the endpoint contract of a web service, or defining new request methods, on a single interface. This interface is then annotated to provide information (metadata) on how to reach the endpoint services and communicate with them.

Almost all usage of the RoboZombie API revolves around this set of annotations for populating endpoint metadata.


####1. Identifying Endpoints

The @Endpoint annotation 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 request 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 Request Methods If the invocation target is a web service, the set of web methods on the service contract may be copied directly. If request methods are created anew, they should be self-explanatory and cover all the parameters of the conversation.


  • Each request method can be identified using the @Request annotation.
@Request
public abstract String timestamp();

By default each invocation executes as an HTTP GET request on the endpoint root-path with no request parameters.


* To populate request parameters, define them as arguments to the method and annotate them with ```@Param```.
@Request
public abstract String convert(@Param("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("q") String conversionString);

  • For request parameters which remain constant for a particular invocation context can be defined using @Request.Param annotations.
@Request(path = "/ig/calculator", params = {@Request.Param(name = "hl", value = "en")})
public abstract String convert(@Param("q") String conversionString);

For request parameters which are populated rarely, use an @Param annotation with a defaultValue attribute to fallback to if null is received.



####3. Populating Headers HTTP headers are treated differently depending on the frequency with which they change.

#####a) Request Headers RoboZombie sorts these into two sets, those which remain constant throughout an endpoint lifetime and those which may change per invocation.

  • Static headers are defined at the method level using the @HeaderSet annotation which takes a set of @HeaderSet.Header annotations.
@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 method arguments annotated with @Header.
@Request
public abstract String crawlBlog((@Header("User-Agent") String userAgent)

#####b) Response Headers Request headers which are modified or introduced at the remote end should be defined as type StringBuilder. This allows the header to be treated as an in-out variable.

######Definition

@Request
public abstract String echo(@Param("s") String echoString, 
                            @Header("Server") StringBuilder serverName);

######Invocation

StringBuilder serverName = new StringBuilder();
String response = endpoint.echo("HELLO", serverName);

logger.info(serverName.toString() + " says " + response);

######Output

$ Jetty(7.0.x) says HELLO

An alternative to this is to use a custom response parser and process the returned headers manually.