blob: d80f4cf77701a4e39818c45c9007a45a9eda8963 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_191) on Wed Dec 26 11:25:31 CET 2018 -->
<title>ConfigurationDependency</title>
<meta name="date" content="2018-12-26">
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
<script type="text/javascript" src="../../../../../../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="ConfigurationDependency";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/Composition.html" title="annotation in org.apache.felix.dm.annotation.api"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/Destroy.html" title="annotation in org.apache.felix.dm.annotation.api"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../../index.html?org/apache/felix/dm/annotation/api/ConfigurationDependency.html" target="_top">Frames</a></li>
<li><a href="ConfigurationDependency.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li>Required&nbsp;|&nbsp;</li>
<li><a href="#annotation.type.optional.element.summary">Optional</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#annotation.type.element.detail">Element</a></li>
</ul>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<!-- ======== START OF CLASS DATA ======== -->
<div class="header">
<div class="subTitle">org.apache.felix.dm.annotation.api</div>
<h2 title="Annotation Type ConfigurationDependency" class="title">Annotation Type ConfigurationDependency</h2>
</div>
<div class="contentContainer">
<div class="description">
<ul class="blockList">
<li class="blockList">
<hr>
<br>
<pre>@Retention(value=CLASS)
@Target(value=METHOD)
public @interface <span class="memberNameLabel">ConfigurationDependency</span></pre>
<div class="block">Annotates a method for injecting a Configuration Dependency.
<p> A configuration dependency
is required by default, and allows you to depend on the availability of a valid configuration
for your component. This dependency requires the OSGi Configuration Admin Service.
Configuration Dependency callback is always invoked before any service dependency callbacks, and before init/start callbacks.
The annotation can be applied on a callback method which accepts the following parameters:
<ul>
<li>callback(Dictionary)
<li>callback(Component, Dictionary)
<li>callback(Component, Configuration ... configTypes) // type safe configuration interface(s)
<li>callback(Configuration ... configTypes) // type safe configuration interface(s)
<li>callback(Dictionary, Configuration ... configTypes) // type safe configuration interfaces(s)
<li>callback(Component, Dictionary, Configuration ... configTypes) // type safe configuration interfaces(s)
</ul>
<h3>Usage Examples</h3>
<p> In the following example, the Printer components depends on a configuration
whose PID name is "sample.Printer". This service will initialize
its ip/port number from the provided configuration.
<blockquote>
<pre>
package sample;
&#64;Component
public class Printer {
&#64;ConfigurationDependency(propagate=true) // Will use the fqdn of the Printer interface as the pid.
void updated(Dictionary cnf) {
if (cnf != null) {
String ip = cnf.get("address");
int port = Integer.parseInt(cnf.get("port"));
}
}
}
</pre>
</blockquote>
You can also define your own component properties using a custom type-safe interface:
<blockquote>
<pre>
package sample;
interface PrinterConfig {
String getAddress();
int getPort();
}
</pre>
</blockquote>
Next, we define our Printer service which depends on the PrinterConfig:
<blockquote>
<pre>
package sample;
&#64;Component
public class Printer {
&#64;ConfigurationDependency // Will use the fqdn of the PrinterConfig interface as the pid.
void updated(PrinterConfig cnf) {
if (cnf != null) {
String ip = cnf.getAddress();
int port = cnf.getPort();
}
}
}
</pre>
</blockquote>
In the above example, the updated callback accepts a type-safe configuration type (and its fqdn is used as the pid).
<p> Configuration type is a new feature that allows you to specify an interface that is implemented
by DM and such interface is then injected to your callback instead of the actual Dictionary.
Using such configuration interface provides a way for creating type-safe configurations from a actual <code>Dictionary</code> that is
normally injected by Dependency Manager.
The callback accepts in argument an interface that you have to provide, and DM will inject a proxy that converts
method calls from your configuration-type to lookups in the actual map or dictionary. The results of these lookups are then
converted to the expected return type of the invoked configuration method.<br>
As proxies are injected, no implementations of the desired configuration-type are necessary!
</p>
<p>
The lookups performed are based on the name of the method called on the configuration type. The method names are
"mangled" to the following form: <tt>[lower case letter] [any valid character]*</tt>. Method names starting with
<tt>get</tt> or <tt>is</tt> (JavaBean convention) are stripped from these prefixes. For example: given a dictionary
with the key <tt>"foo"</tt> can be accessed from a configuration-type using the following method names:
<tt>foo()</tt>, <tt>getFoo()</tt> and <tt>isFoo()</tt>.<p>
If the property contains a dot (which is invalid in java method names), then dots (".") can be converted using the following conventions:
<ul>
<li> if the method name follows the javabean convention and/or kamel casing convention, then each capital letter is assumed to map to a "dot",
followed by the same letter in lower case. This means only lower case properties are
supported in this case. Example: getFooBar() or fooBar() will map to "foo.bar" property.
<li> else, if the method name follows the standard OSGi metatype specification, then dots
are encoded as "_"; and "_" is encoded as "__". (see OSGi r6 compendium, chapter 105.9.2).
Example: "foo_BAR()" is mapped to "foo.BAR" property; "foo__BAR_zoo()" is mapped to "foo_BAR.zoo" property.
</ul>
<p>
The return values supported are: primitive types (or their object wrappers), strings, enums, arrays of
primitives/strings, <code>Collection</code> types, <code>Map</code> types, <code>Class</code>es and interfaces. When an interface is
returned, it is treated equally to a configuration type, that is, it is returned as a proxy.
</p>
<p>
Arrays can be represented either as comma-separated values, optionally enclosed in square brackets. For example:
<tt>[ a, b, c ]</tt> and <tt>a, b,c</tt> are both considered an array of length 3 with the values "a", "b" and "c".
Alternatively, you can append the array index to the key in the dictionary to obtain the same: a dictionary with
"arr.0" =&gt; "a", "arr.1" =&gt; "b", "arr.2" =&gt; "c" would result in the same array as the earlier examples.
</p>
<p>
Maps can be represented as single string values similarly as arrays, each value consisting of both the key and value
separated by a dot. Optionally, the value can be enclosed in curly brackets. Similar to array, you can use the same
dot notation using the keys. For example, a dictionary with
<pre><code> "map" =&gt; "{key1.value1, key2.value2}"</code></pre>
and a dictionary with
<pre><code> "map.key1" =&gt; "value1", "map2.key2" =&gt; "value2"</code></pre>
result in the same map being returned.
Instead of a map, you could also define an interface with the methods <tt>getKey1()</tt> and <tt>getKey2</tt> and use
that interface as return type instead of a <code>Map</code>.
<p>
In case a lookup does not yield a value from the underlying map or dictionary, the following rules are applied:
<ol>
<li>primitive types yield their default value, as defined by the Java Specification;
<li>string, <code>Class</code>es and enum values yield <code>null</code>;
<li>for arrays, collections and maps, an empty array/collection/map is returned;
<li>for other interface types that are treated as configuration type a null-object is returned.
</ol></div>
</li>
</ul>
</div>
<div class="summary">
<ul class="blockList">
<li class="blockList">
<!-- =========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY =========== -->
<ul class="blockList">
<li class="blockList"><a name="annotation.type.optional.element.summary">
<!-- -->
</a>
<h3>Optional Element Summary</h3>
<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Optional Element Summary table, listing optional elements, and an explanation">
<caption><span>Optional Elements</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Modifier and Type</th>
<th class="colLast" scope="col">Optional Element and Description</th>
</tr>
<tr class="altColor">
<td class="colFirst"><code>java.lang.String</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/felix/dm/annotation/api/ConfigurationDependency.html#name--">name</a></span></code>
<div class="block">The name for this configuration dependency.</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><code>java.lang.String</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/felix/dm/annotation/api/ConfigurationDependency.html#pid--">pid</a></span></code>
<div class="block">Returns the pid for a given service (by default, the pid is the service class name, of the FQDN of
the configuration type found in the updated callback signature.</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><code>java.lang.Class&lt;?&gt;</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/felix/dm/annotation/api/ConfigurationDependency.html#pidClass--">pidClass</a></span></code>
<div class="block">Returns the pid from a class name.</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><code>boolean</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/felix/dm/annotation/api/ConfigurationDependency.html#propagate--">propagate</a></span></code>
<div class="block">Returns true if the configuration properties must be published along with the service.</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><code>boolean</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/felix/dm/annotation/api/ConfigurationDependency.html#required--">required</a></span></code>
<div class="block">Sets the required flag which determines if this configuration dependency is required or not.</div>
</td>
</tr>
</table>
</li>
</ul>
</li>
</ul>
</div>
<div class="details">
<ul class="blockList">
<li class="blockList">
<!-- ============ ANNOTATION TYPE MEMBER DETAIL =========== -->
<ul class="blockList">
<li class="blockList"><a name="annotation.type.element.detail">
<!-- -->
</a>
<h3>Element Detail</h3>
<a name="pid--">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>pid</h4>
<pre>public abstract&nbsp;java.lang.String&nbsp;pid</pre>
<div class="block">Returns the pid for a given service (by default, the pid is the service class name, of the FQDN of
the configuration type found in the updated callback signature.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the pid for a given service (default = Service class name)</dd>
</dl>
<dl>
<dt>Default:</dt>
<dd>""</dd>
</dl>
</li>
</ul>
</li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="pidClass--">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>pidClass</h4>
<pre>public abstract&nbsp;java.lang.Class&lt;?&gt;&nbsp;pidClass</pre>
<div class="block">Returns the pid from a class name. The full class name will be used as the configuration PID.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the pid class whose FQDN name is used as the configuration PID.</dd>
</dl>
<dl>
<dt>Default:</dt>
<dd>java.lang.Object.class</dd>
</dl>
</li>
</ul>
</li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="propagate--">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>propagate</h4>
<pre>public abstract&nbsp;boolean&nbsp;propagate</pre>
<div class="block">Returns true if the configuration properties must be published along with the service.
Any additional service properties specified directly are merged with these. The configuration
dependency properties take precedence over the component service properties, meaning that a given configuration
property will override the same property that is already present in the component service properties.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>true if configuration must be published along with the service, false if not.</dd>
</dl>
<dl>
<dt>Default:</dt>
<dd>false</dd>
</dl>
</li>
</ul>
</li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="required--">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>required</h4>
<pre>public abstract&nbsp;boolean&nbsp;required</pre>
<div class="block">Sets the required flag which determines if this configuration dependency is required or not.
A configuration dependency is required by default.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>this service dependency</dd>
</dl>
<dl>
<dt>Default:</dt>
<dd>true</dd>
</dl>
</li>
</ul>
</li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="name--">
<!-- -->
</a>
<ul class="blockListLast">
<li class="blockList">
<h4>name</h4>
<pre>public abstract&nbsp;java.lang.String&nbsp;name</pre>
<div class="block">The name for this configuration dependency. When you give a name a dependency, it won't be evaluated
immediately, but after the component's init method has been called, and from the init method, you can then return
a map in order to dynamically configure the configuration dependency (the map has to contain a "pid" and/or "propagate"
flag, prefixed with the dependency name). Then the dependency will be evaluated after the component init method, and will
be injected before the start method.
<p> Usage example of a Configuration dependency whose pid and propagate flag is configured dynamically from init method:
<blockquote><pre>
&#47;**
* A Service that dynamically defines an extra dynamic configuration dependency from its init method.
*&#47;
&#64;Component
class X {
private Dictionary m_config;
// Inject initial Configuration (injected before any other required dependencies)
&#64;ConfigurationDependency
void componentConfiguration(Dictionary config) {
// you must throw an exception if the configuration is not valid
m_config = config;
}
&#47;**
* All unnamed dependencies are injected: we can now configure our dynamic configuration whose dependency name is "global".
*&#47;
&#64;Init
Map init() {
return new HashMap() {{
put("global.pid", m_config.get("globalConfig.pid"));
put("global.propagate", m_config.get("globalConfig.propagate"));
}};
}
// Injected after init, and dynamically configured by the init method.
&#64;ConfigurationDependency(name="global")
void globalConfiguration(Dictionary globalConfig) {
// you must throw an exception if the configuration is not valid
}
&#47;**
* All dependencies are injected and our service is now ready to be published.
*&#47;
&#64;Start
void start() {
}
}
</pre></blockquote></div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the dependency name used to configure the dependency dynamically from init callback</dd>
</dl>
<dl>
<dt>Default:</dt>
<dd>""</dd>
</dl>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- ========= END OF CLASS DATA ========= -->
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/Composition.html" title="annotation in org.apache.felix.dm.annotation.api"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../../../../org/apache/felix/dm/annotation/api/Destroy.html" title="annotation in org.apache.felix.dm.annotation.api"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../../../../index.html?org/apache/felix/dm/annotation/api/ConfigurationDependency.html" target="_top">Frames</a></li>
<li><a href="ConfigurationDependency.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li>Required&nbsp;|&nbsp;</li>
<li><a href="#annotation.type.optional.element.summary">Optional</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#annotation.type.element.detail">Element</a></li>
</ul>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>