blob: 8d2c0c69d3cb99cb37a2dd27c0932357d2e8f7a6 [file] [log] [blame]
:jbake-type: page
:jbake-status: published
= Apache Tamaya - Extension: CDI Support
toc::[]
[[CDI]]
== Tamaya CDI Integration (Extension Modules)
Tamaya _CDI_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details.
=== What functionality this module provides ?
Apache _CDI_ provides integration with CDI:
* Loading of CDI managed SPI components as configuration extensions such as +PropertySources, PropertySourceProviders,
PropertyFilters, etc+. This also includes SPI defined by any Tamaya submodules.
This is useful when Tamaya is used as an application module managed by the CDI implementation.
* Implement and enable Tamaya's configuration injection services (either using CDI injection or
Tamaya's standalone injection module.
Hereby there are two implementations provided:
* +tamaya-injection-cdi+ implements injection by using CDI's injection mechanism to inject configuration values into the
beans managed by the CDI systems.
* +tamaya-injection-standalone+ implements injection by integrating the +tamaya-injection+ SE based injection module (also used
for Spring and OSGI injection) with CDI. Injection hereby is performed by the Tamaya SE module, whereas
beans and injection control overall are still managed by CDI.
* One difference, of course, is that +tamaya-injection-standalone+ also provides an SE compatible API (+ConfigurationInjection,
ConfigurationInjector+), which is not available, when using the purely CDI based variant.
The annotations used for all injection functionality in Tamaya is defined as a separate module. This allows you to
code against the injection API without dependency on the concrete injection implementation. As a consequence your
components will be compatible regardless if deployed in a pure SE or as Java EE (CDI) or Spring environment:
[source, xml, subs=attributes+]
-----------------------------------------------
<dependency>
<groupId>org.apache.tamaya.ext</groupId>
<artifactId>tamaya-injection-api</artifactId>
<version>{tamaya_version}</version>
</dependency>
-----------------------------------------------
=== Compatibility
All modules are based on Java 7, so they will not run on Java 7 and beyond.
=== Installation
To benefit from Tamaya CDI integration you only must one of the following dependencies to your module. Ensure that
you never have installed both CDI extensions at the same time because this may be lead to unforseen side-effects.
.CDI Java EE Application Configuration
[source, xml, subs=attributes+]
-----------------------------------------------
<dependency>
<groupId>org.apache.tamaya.ext</groupId>
<artifactId>tamaya-cdi</artifactId>
<version>{tamaya_version}</version>
</dependency>
-----------------------------------------------
.To use Tamaya's _standalone injection support_, you additionally should add the
following dependency. If this dependency is missing injection is purely based on
CDI injection features.
[source, xml, subs=attributes+]
-----------------------------------------------
<dependency>
<groupId>org.apache.tamaya.ext</groupId>
<artifactId>tamaya-injection-standalone</artifactId>
<version>{tamaya_version}</version>
</dependency>
-----------------------------------------------
Both components will auto-register its components and override the default +ServicceContext+ in use. Additionally they
register CDI extensions that implement Configuration injection as described before.
For working with a pure non Java EE environment have a look at the link:mod_injection-standalone.html[tamaya-injection-standalone module].
Additionally you have to register Tamaya's CDI extension modules into your `beans-xml`:
Contents of `META-INF/services/javax.enterprise.inject.spi.Extension`:
[source, properties]
-----------------------------------------------
# Register Tamaya to perform injection
# org.apache.tamaya.cdi.TamayaCDIInjectionExtension
# org.apache.tamaya.cdi.TamayaSEInjectionExtension
org.apache.tamaya.cdi.TamayaCDIAccessor
-----------------------------------------------
If you want to use CDI standard injection (using +@Inject @Config+), activate
+org.apache.tamaya.cdi.TamayaCDIInjectionExtension+ as a CDI extension.
If you want to use +SE based injection+ (using +@Config+ *without* +@Inject+),
activate +org.apache.tamaya.cdi.TamayaSEInjectionExtension+ instead of.
Though not recommended, it is possible to activate both extension at the same time.
=== Annotating your Classes
Basically annotating your classes is straightforward. +@Config+ defines an additional CDI qualifier that is, depending
on the module deployed, handled by a CDI producer (+tamaya-cdi-ee+) or the Tamaya SE injection mechanism $
(+tamaya-cdi-se+). All types injected by this module are injected using _dependent scope_. Keep in mind that values injected into fields by Tamaya cannot be used within constructors because https://docs.jboss.org/weld/reference/latest/en-US/html/injection.html[they will not yet have been injected].
[source, java]
--------------------------------------------------------
@RequestScoped
public class ConfiguredClass{
@Config
private String testProperty;
@Config({"a.b.c.key1","a.b.c.key2","a.b.c.key3"},
defaultValue="The current \\${JAVA_HOME} env property is ${env:JAVA_HOME}.")
String value1;
@Config({"foo","a.b.c.key2"})
private String value2;
@Config
@ConfigDefault("N/A")
private String runtimeVersion;
@Config(defdaultValue="${sys:java.version}")
private String javaVersion2;
@Config(defaultValue="5")
private Integer int1;
...
}
--------------------------------------------------------
=== Registering CDI managed components into the Application's ConfigurationContext
As mentioned both modules allow to provide Tamaya SPI extensions modules as ordinary CDI managed beans. By default
extensions should be registered using +@Singleton+ or +@ApplicationScoped+ scope annotations. So you can define/deploy
additional application specific +PropertySources+ and other artifacts simply by defining a CDI managed bean implementing
the required SPI interface:
[source, java]
--------------------------------------------------------
@Singleton
public class TestPropertySource implements PropertySource{
final Map<String,String> config = new HashMap<>();
public TestPropertySource(){
config.put("a.b.c.key1", "keys current a.b.c.key1");
config.put("a.b.c.key2", "keys current a.b.c.key2");
config.put("{"+getName()+"}source", getClass().getName());
}
@Override
public int getOrdinal() {
return 10;
}
@Override
public String getName() {
return getClass().getName();
}
@Override
public String get(String key) {
return config.get(key);
}
@Override
public Map<String, String> getProperties() {
return config;
}
@Override
public boolean isScannable() {
return true;
}
}
--------------------------------------------------------
To enable this (optional) feature you must replace Tamaya's +ServiceContext+ with the
CDI aware implementation:
Contents of `META-INF/services/org.apache.tamaya.spi.ServiceContext`:
[source, properties]
-----------------------------------------------
# Registering a CDI aware service context
CDIAwareServiceContext
-----------------------------------------------
=== Advanced Use Cases
Beside basic configuration Tamaya also covers additional requirements:
* _Reading multiple keys, where the first successful one is determining the value of the configuration, is
simply possible, by adding multiple keys to the +@Configy+ annotation.
E.g. for trying first +a.b+ and then +new.b+ you would configure it as follows:
[source,java]
--------------------------------------------------------------------------------------
@Config({"a.b", "new.b"}
private String value;
--------------------------------------------------------------------------------------
* When you must apply a +ConfigOperator+ to your config, before reading the configuration, you can
configure one as follows:
[source,java]
--------------------------------------------------------------------------------------
@Config({"a.b", "new.b"}
@WithConfigOperator(MyOperator.class)
private String value;
--------------------------------------------------------------------------------------
* When you must apply a some special conversion, or you use a type that is not registered
for conversion, you can configure a custom converter to be applied as follows:
[source,java]
--------------------------------------------------------------------------------------
@Config({"a.b", "new.b"}
@WithPropertyConverter(MyConverter.class)
private MySpecialFooType value;
--------------------------------------------------------------------------------------
* Often multiple keys in a class belong to the same root section. So instead of copying this to
every entry you can define the most common root sections in the type's header:
[source,java]
--------------------------------------------------------------------------------------
@ConfigDefaultSections({"aaaa", "new"});
public class MyType{
@Config({"b", "[legacy.bKey]"} // lookups: "aaaa.b", "new.b", legacy.bKey
private String value;
--------------------------------------------------------------------------------------
In the example above +legacy.bKey+ defines an absolute key, which is not combined with any defined
default section parts.