Substrate
The interfaces defined within Substrates API are designed with extensibility and evolution in mind, both from a client library and provider implementation perspective. Extensibility starts with the Substrate interface, a foundational interface extended by all interfaces annotated with @Provided, that defines a single method, named environment, that returns an Environment instance.
1 2 3 4 5 6 7 8 9 10 11 |
@Abstract public interface Substrate { default Environment environment () { return Environment.EMPTY; } } |
Environment
The Environment interface, originally designed to allow for interfacing with existing configuration stores and systems, offers a standard way for implementation providers to expose additional extension properties to each of the @Provided annotated interfaces.
The Environment interface extends the Lookup interface with additional type-specific methods for common class types, such as Integer, Long, String, Double, Boolean, etc., where typed values are accessed using a predefined Name, think of a key into a map structure, that can be specified in a provider’s supporting documentation or published within a utility class or interface.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@Abstract public interface Lookup < T > { default Optional< T > get ( final Name name ) { return ofNullable ( get ( name, null ) ); } T get ( Name name, T defValue ); } |
A benefit of this design choice is that the surface area of the interfaces that extend the Substrate interface can be kept to a bare minimum, a “least common denominator” set of properties and operations across all implementations of the Substrates API, while still allowing for the environment-, configuration-, provider-, runtime-specific state of being publically accessible without impacting the ability of a client codebase (agent, application, plugin) to move from one implementation provider to another.
Variable
Using the Variable interface is recommended when working with the Environment interface in repeatedly looking up a particular named value as a provider can optimize the underlying internal implementation, such as adding caching and short-circuiting code paths.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Utility @Provided public interface Variable < T > extends Substrate { T of ( final Environment environment ); default T of ( final Substrate substrate ) { return of ( substrate .environment () ); } } |
The Cortex interface, the Substrates API root fabrication runtime component, offers various overloaded methods to create a type-specific Variable instance, such as specifying a default value when a lookup does not succeed and a transformation when it does.
1 2 3 4 5 6 |
Variable< Long > variable ( final Name name, final Long defValue ) |