Design Model API For Clients
Assumptions and Terminology
Let foo be a service within the system. In what follows, we discuss the design of a client-side API for foo. In the process, we outline a generic model for similar APIs based on a small number of classes and interfaces. These compilation units are placed in org.gcube.common.clients.api package and are implemented in a common-clients-api library.
We work under the following assumptions and using the following terminology:
- services: foo is an HTTP service, in that it uses HTTP at least as its transport protocol. At the time of writing, all system services are more specifically WS RPC services, i.e. use SOAP over HTTP to invoke service-specific APIs. Some such services are stateless, in that their endpoints do not manage any form of state on behalf of clients. Other services are instead stateful, in that their endpoints host a number of service instances, all of which maintain state for a class of clients [1]. In the future, system services may also be REST services, in the broad sense of stateless services that use HTTP as their application protocol[2].
- deployments: foo may be (statically or dynamically) deployed at multiple network addresses. We refer to a service deployment at any given address as a service replica [3]. Discovery Services are available within the system to locate service endpoints that are deployed at different addresses.
- scoped requests: foo may operate in multiple scopes, where each scope partitions the local resources that are visible to its clients, as well as the remote resources that are visible to the operations that foo carries out on behalf of its clients. In particular, the operations of foo may result in the creation of state in a given scope, either locally to foo or remotely, by interaction with other services that create state on behalf of foo and/or its clients. Service scoping requires that requests to foo are scoped, marked with the scope within which they are intended to occur. Unscoped requests or requests made outside one of foo’s scopes are rejected by it.
- secure requests: foo may perform a range of authentication and authorisation checks, including scope checks, in order to restrict access to its operations to distinguished clients. Service security requires that requests made to foo be marked with adequate credentials. Unsecure requests or secure requests that fail authorisation checks are rejected by foo.
- clients: a client of foo may be internal to the system (i.e. a system component in turn) or external to it. Clients often operate within a dedicated runtime, and in this case we refer to them as pure clients. In other cases, they share a common runtime and, like foo, they may be managed by some container. In particular, clients may be services in turn, and in this case we refer to them as a client services.
- ↑ terminology: the system has traditionally used a different terminology for its services. Service instances are called WS-Resources, as WSRF is the set of standards with which they are uniformly exposed at the time of writing. We prefer here the term “service instance” for its wider usage. Note also that WS-Resources and use WS-Lifetime, WS-ResourceProperties and WS-Notification protocols to expose, respectively, lifetime operations, the values of distinguished properties of their state, and subscriptions for/notifications of changes to the values of those properties. Some services capitalise on these standards and become stateful even when they expose a single instance. These stateful services are known as singleton services.
- ↑ teminology: services have been often described within the system as a collection of one or more “port-types”, following the terminology endorsed by WSDL 1.x standards, and then abandoned in WSDL 2.x standards. For its wider adoption and technological independence, we prefer here to follow common terminology whereby a port-type is a service in its own right.
- ↑ terminology: the term “running instance” has been used within the system to indicate a service deployment at a given network address. We prefer here the term “service replica” to avoid confusion with “service instance”, which is more commonly associated with stateful services.
Goals and Principles
Within the previous assumptions, our model is motivated by a goal of consistency across different client APIs. In particular, the model will:
- decrease the overall learning curve associated with using the system;
- increase API quality via sharing of best design practices;
- decrease API first-time and maintenance development costs via shared libraries;
- decrease API documentation costs by reference to shared design elements;
To achieve our goals, we base the model on a set of design principles. In no particular order, these include:
- generality: the model will endorse design solutions that do not limit its applicability to the range of services and clients outlined above;
- coverage: the model will address a wide range of issues that transcend the semantics of individual services, including scoping issues, security issues, replica discovery and management issues, and fault management issues;
- transparency: the model will endorse design solutions that simplify client usage, particularly
with respect to requirements that are specific to our system;
- testability: the model will not endorse design solutions that reduce or unduly complicate the
possibility of unit testing for clients;