A library providing DI with JSR-330 annotations and extensible YML/JSON configuration.
The intended goal is to have both "traditional" DI capabilities and a non-intrusive, runtime-evaluated configuration system with an emphasis on composition. Each configuration file represents a small graph of objects that can be composed with others in order to create an application.
Add the following in your pom.xml:
<dependency>
<groupId>com.noleme</groupId>
<artifactId>noleme-vault</artifactId>
<version>0.19.3</version>
</dependency>Noleme Vault is designed around a three-stage process for managing dependencies and configuration:
- Parsing & Extraction: a
VaultParserreads configuration files (YAML, JSON) and producesDefinitions, representing a blueprint of a dependency graph, along with registered variables that may be used. - Compilation & Registration: the
VaultFactorytakes theseDefinitionsand handles the resolution of service dependencies, validates the graph structure (checking for circular dependencies or missing services), and registers resulting services and variables into aCellar. - Runtime & Injection: the
Vaultinstance then can be used as the injection service, leveraging theCellarand providing DI capabilities via JSR-330 annotations or direct queries.
- Vault: The main entry point for the library. It provides a high-level API for instantiating services and performing injections
- Cellar: A container for runtime objects. It holds the actual instances of services and the values of configuration variables
- Definitions: A registry of service and variable metadata before they are instantiated
- VaultParser: An extensible component responsible for translating external configuration formats (eg. YML/JSON) into
Definitions - VaultFactory: The engine that transforms
Definitionsinto a liveCellarof services
The next section sheds some light on how these work together.
A basic example of using this library with a yml configuration file:
Given a dummy configuration file my_conf.yml:
variables:
my_var: 12.34
my_other_var: "interesting"
my_env_var: ${MY_VAR:default_value}
services:
my_service:
class: "me.company.MyClass"
constructor:
- "not so interesting"
- "##my_var##"
my_other_service:
class: "me.company.MyOtherClass"
constructor:
- "##my_other_var##"We could perform injection via annotations on a dummy class such as:
public class MyService
{
private final MyClass service;
private final MyOtherClass otherService;
@Inject
public MyService(MyClass service, @Named("my_other_service") MyOtherClass otherService)
{
this.service = service;
this.otherService = otherService;
}
}..and do the following:
var vault = Vault.with("my_conf.yml");
MyService service = vault.instance(MyService.class);It's also possible to use field annotations and proceed the following way:
public class MyService
{
@Inject private MyClass service;
@Inject private MyOtherClass otherService;
}MyService service = vault.inject(new MyService());Alternatively we could directly query one of the declared services:
MyClass myService = vault.instance(MyClass.class, "my_service");For more details on the library's features, check out the following documentation pages:
- Introduction: Design philosophy and key components
- Services: Declarations, constructors, factory methods, and lifecycle
- Variables: Variable definitions, environment variables, and runtime overrides
- Composition: Imports, scoped blueprints, and service tagging
- JSR-330: JSR-330 annotations, field/constructor injection, and modules
- Advanced: Custom modules, preprocessors, and programmatic composition
This project will require you to have the following:
- Java 11+
- Git (versioning)
- Maven (dependency resolving, publishing and packaging)