| :jbake-type: page |
| :jbake-status: published |
| |
| = Apache Tamaya - Extension: Resolver |
| |
| [[Resolver]] |
| == Tamaya Resolver (Extension Module) |
| |
| Tamaya _Resolver_ is an extension module. Refer to the link:../extensions.html[extensions documentation] for further details. |
| |
| |
| === What functionality this module provides ? |
| |
| Tamaya _Resolver_ is an extension module. Refer to the link:../extensions.html[extensions documentation] |
| for further details about modules. |
| |
| Tamaya Resolver provides a dynamic resolution mechanism, which allows to use UNIX-styled (+${...}+ placeholder |
| expressions in your configuration values. The resolver hereby supports transitive resolution and also prevents |
| cycles to loop endlessly. |
| |
| |
| === Compatibility |
| |
| The module is based on Java 8. |
| |
| |
| === Installation |
| |
| To benefit from dynamic value resolution you only must add the corresponding dependency to your module: |
| |
| [source, xml, subs=attributes+] |
| ----------------------------------------------- |
| <dependency> |
| <groupId>org.apache.tamaya.ext</groupId> |
| <artifactId>tamaya-resolver</artifactId> |
| <version>{tamaya_version}</version> |
| </dependency> |
| ----------------------------------------------- |
| |
| The module automatically registers an according +PropertyFilter+ that is automatically called, whenever a value |
| is accessed. |
| |
| |
| === Available Resolvers |
| |
| Currently the module defines the following resolvers: |
| |
| .Available Resolvers |
| [cols="<.1,<.2,<.1"] |
| |======= |
| | _Expression_ |
| | _Description_ |
| | _Example_ |
| |
| | +conf:<configKey>+ |
| | Reads another configKey and replaces the expression with the value found. |
| | conf-ref=${conf:anotherConf.entryKey} |
| |
| | +resource:<resourceRef>+ |
| | Reads a resource from the current classpath and replaces the expression with the given text content. |
| | cp-ref=${resource:Testresource.txt} |
| |
| | +file:<fileRef>+ |
| | Reads a resource from the current classpath and replaces the expression with the given text content. |
| | file-ref=${file:c:\myFile.txt} |
| |
| |+url:<url>+ |
| |Reads an URL and replaces the expression with the given text content. |
| | url-ref=${url:http://www.google.com} |
| |
| |======= |
| |
| |
| === Explicit Expression Resolution |
| |
| The resolvers registered are normall running implicitly, when corresponding placeholders are used in configuration |
| values. Additionally the expression resolution functionality can also used explcitly: |
| |
| [source,java] |
| --------------- |
| public final class Resolver { |
| |
| public static Resolver getInstance(); |
| public static Resolver getInstance(ClassLoader classLoader); |
| |
| public String evaluateExpression(String key, String value); |
| public String evaluateExpression(String key, String value, ClassLoader classLoader); |
| public String evaluateExpression(String value); |
| public String evaluateExpression(String value, boolean maskNotFound); |
| } |
| --------------- |
| |
| === SPI: Implementing your own Resolvers |
| |
| The module also provides a small but powerful SPI for adding your own resolver implementations. Basically the |
| first and most important thing to do is implementing the +ExpressionResolver+ interface: |
| |
| .Implementing a Custom Resolver |
| [source, java] |
| ----------------------------------------------- |
| public class PwdDecrypter implements ExpressionResolver { |
| |
| @Override |
| public String getResolverPrefix() { |
| return "decrypt:"; |
| } |
| |
| @Override |
| public String evaluate(String expression) { |
| return decrypt(expression); |
| } |
| |
| private String decrypt(String s) { |
| ... |
| } |
| } |
| ----------------------------------------------- |
| |
| Basically that is all you must do, after having registered the class with the +ServiceLoader+ it will be found |
| and loaded by the implementation. With that all expressions that start with the given prefix are passed to the |
| resolver, so all the following expressions will be sent to the implementation: |
| |
| [source,listing] |
| ----------------------------------------------- |
| blabla ${decrypt:myname} |
| blabla ${decrypt:myname} foo blabla ${decrypt:myname} |
| ----------------------------------------------- |
| |
| Hereby evaluation is repeated until no further change of values could be detetced. In case of a endless loop |
| the evaluation is broken after a (configurable) number of cycles. |
| |
| |
| Under the hood instances of +ExpressionResolver+ are managed by an implementation of the +ExpressionEvaluator+ |
| interface: |
| |
| [source, java] |
| ----------------------------------------------- |
| public interface ExpressionEvaluator { |
| /** |
| * Evaluates the current expression. |
| * @param key the key, not null. |
| * @param value the value to be filtered/evaluated. |
| * @return the filtered/evaluated value, including null. |
| */ |
| String evaluateExpression(String key, String value); |
| } |
| ----------------------------------------------- |
| |
| Implementing and registering this interface gives you full control, but in most cases you should be fine with |
| the default implementation in place. |