-
Notifications
You must be signed in to change notification settings - Fork 10
Library Philosophy
This library is build with extensibility and modularity in mind. Therefore, it is possible to consume only parts of the library, depending on the use case at hand.
The most basic module, which is the bare minimum any application could use,
is the java-core-api
module.
It
contains the ServiceBinding
interface,
which is what this library is all about.
Additionally, the module also ships a default implementation of the
interface (the DefaultServiceBinding
class),
as well as some more fundamental classes.
The java-access-api
module
builds on top of the core API.
It
contains the ServiceBindingAccessor
interface,
which defines the API for retrieving ServiceBinding
instances from the environment.
The most noteworthy implementation next to the ServiceBindingAccessor
interface
is the DefaultServiceBindingAccessor
class.
This class serves as a static, always accessible singleton-like entry point to retrieve a ServiceBindingAccessor
instance.
Under the hood, it uses the service locator pattern to find available implementations of the ServiceBindingAccessor
interface on the class path and combines them
using the ServiceBindingMerger
.
This way, it combines the results of all available SerivceBindingAccessor
implementations, which is how multiple
runtime environments can work together.
Applications and libraries are requested to use this implementation as a FALLBACK only.
Please find more guidance about best practices and recommendations in the Best Practices section.
The java-consumption-api
module
also builds on top of the core API.
It provides type-safe abstractions over the ServiceBinding
that can be used to read data from a given ServiceBinding
in more complex scenarios.
The Service Binding Library comes with out-of-the-box support for Cloud Foundry and K8s (e.g. SAP Kyma) in combination with the SAP BTP Service Operator runtime environments.
However, the library is designed to be extensible, so that support for additional runtime environments can be added
easily by adding new implementations of the ServiceBindingAccessor
interface.
These implementations should follow the same principals as the existing ones, which can be summarized as follows:
- Be lenient. Anticipate that the implementation might be called for a runtime environment that it does not support.
In this case, the implementation should return an empty
ServiceBinding
list. Refrain from throwing exceptions if possible. - Focus on one specific type of service binding per implementation.
- Expose the implementation via the service locator
pattern if it should be picked up by
the
DefaultServiceBindingAccessor
( and theServiceBindingAccessor#getInstancesViaServiceLoader()
) implementation by default.
This library is somewhat opinionated about the way it should be used. The following sections describe the best practices and recommendations for using the library.
The ServiceBinding
interface is an immutable abstraction.
This means that the data contained in a ServiceBinding
instance cannot be changed after it has been created.
As a consequence, operating on the same ServiceBinding
instance for a longer period of time is not recommended as the
contained data might be outdated (e.g. the service binding might have been rotated in the meantime).
Instead, it is recommended to retrieve a fresh ServiceBinding
instance from the ServiceBindingAccessor
whenever
the data is needed.
As explained in the section above, it is recommended to retrieve a fresh ServiceBinding
instance from the
ServiceBindingAccessor
whenever the data is needed.
However, this does not mean that the ServiceBindingAccessor
itself cannot cache the results of its operations.
In fact, the library even comes
with the SimpleServiceBindingCache
,
which can be used to cache the results of a ServiceBindingAccessor
instance for a fixed amount of time.
By default (i.e. within the DefaultServiceBindingAccessor
), this cache is used to store the results of the
underlying ServiceBindingAccessor
for 5
minutes.
That way, expensive operations (such as reading from the file system) are significantly reduced.
This library focuses on instance-based state almost exclusively (the DefaultServiceBindingAccessor
is the only
exception).
Doing so provides the following benefits:
- It allows for more flexibility in terms of testing. For example, if APIs accept an instance of
ServiceBinding
instead of always loading them from theDefaultServiceBindingAccessor
, they can be tested in isolation (i.e. without having to manipulate the static state of theDefaultServiceBindingAccessor
). - It allows for more flexibility in terms of extensibility. If applications want to support a custom runtime, for example, they don't need to change any existing code of this library but, instead, can just add more code from their side. Everything else should just continue to work.
This library uses a lot of composition instead of inheritance, especially in the ServiceBindingAccessor
related
classes.
This is done to allow for more flexibility in terms of extensibility and should be adopted by applications that want to
extend the functionality of this library.