Integration and Interoperability Facilities Framework: Client Libraries Framework
gCube includes client libraries for many of its services and defines a general model for their design. The model requires that all libraries offer a common set of capabilities and adopt uniform patterns for the design of their APIs, regardless of service semantics and technology stacks. The model, however, does not indicate how capabilities and patterns should be implemented, nor does it mandate low-level API details.
The client library framework supports the implementation of client libraries which comply with the model. Through code sharing, the framework reduces development costs for client libraries and ensures the consistency and correctness of their implementations.
In this document, we assume familiarity with the design model and illustrate how the framework can be used to develop a model-compliant client library for a hypothetical foo
service.
Distribution
The framework is layered across as a set of components, all of which are available in our Maven repositories as artifacts in the org.gcube.core
group.
common-clients is the top layer of the framework and comprises classes and interfaces that do not depend on particular technology stacks. In this sense, common-clients
is as general as the design model. Lower layers of the framework adapt common-clients
to specific stacks. At the time of writing, gCore
is the dominant technology stack for gCube services and their clients. common-gcore-clients is thus the only available specialisation of common-clients
.
We assume accordingly that foo
is a gCore service, i.e. a JAX-RPC Java service that can be deployed in one or more gCore
containers on some gCube hosting nodes. We also assume that the client library for foo
is developed as a Maven project, in line with system recommendations. To use the framework, the library declares a compile-time dependency on common-gcore-clients
in its POM, as follows:
<dependency> <groupId>org.gcube.core</groupId> <artifactId>common-gcore-clients</artifactId> <version>...</version> <scope>compile</version> </dependency>
This dependency brings common-gcore-clients
and its transitive dependencies, including common-clients
, on the compile-time classpath of the library. The version will vary over time and is 2.0.0
at the time of writing.
The library depends also on the stub library of foo
, which we also assume available as a Maven artifact, e.g.:
<dependency> <groupId>org.gcube.samples</groupId> <artifactId>foo-stubs</artifactId> <version>...</version> <scope>compile</version> </dependency>
Overview
The main design pattern defined by the model is that of a service proxy. This requires that foo
endpoints be represented in the library by an interface Foo
and an implementation DefaultFoo
. The former defines methods that the latter implements against the API of the foo
stubs. For example, if FooPortType
is the type of foo
stubs and bar()
one of their String
-valued methods:
public interface Foo { String bar() throws ...; } public class DefaultFoo implements Foo { public String bar() throws ... { ...FooPortType endpoint... try { return endpoint.bar(); } catch(...) { //fault handling } }
While the pattern is straightforward, complexity arises from:
- the requirements of particular methods. The model specifies how
Foo
andDefaultFoo
should be designed when methods take or return given types of values (e.g. streams), handle faults with given semantics (e.g. service contingencies), or execute under a given operational semantics (e.g. asynchronously).
- the configuration and operation of proxies. The model requires proxies to work in either one of two modes:
- in direct mode, proxies obtain the address of given service endpoints from clients and execute all their methods against those endpoints. Clients model addresses as
W3EndpointReference
s or - depending on wetherfoo
is a stateless or stateless service - as(host, port)
pairs or(host, port, key)
triples. Since stubs APIs for gCore services model addresses asEndpointReferenceType
s, the library must implement address conversion and address validation;
- in direct mode, proxies obtain the address of given service endpoints from clients and execute all their methods against those endpoints. Clients model addresses as
- in discovery mode, proxies identify service endpoints from queries to gCube discovery services and are responsible for using the results in a fault-tolerant and optimised manner. Queries must be high-level value-objects and the library must implement specific binding and caching strategies for query results.
The framework offer limited support for the implementation of Foo
‘s API, as there are external libraries that provide it when and where it is required (e.g. the streams library, the scope library, or the security library). However, the framework includes the common faults and callback components defined by the model. We discuss these components and their placement within the framework here.
On the other hand, the framework can meet all proxy configuration and operation requirements on behalf of the library. We give a tour below of the support available in this area and expand on individual components in later sections.