OpenDaylight: Listen for flow updates - opendaylight

I am trying to implement an OpenDaylight bundle that receives notifications when flows change. Therefore, I implemented DataTreeChangeListener<Flow>. The project compiles and starts (./karaf/target/assembly/bin/karaf), but when I install additional package (feature:install odl-restconf odl-l2switch-switch odl-dluxapps-yangvisualizer odl-dluxapps-yangman odl-dlux-core odl-dluxapps-nodes odl-dluxapps-topology odl-mdsal-apidocs), I get the following error:
Unsatisfied Requirements:
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.netconf.sal.rest.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.netconf.sal.restconf.api)"
Unsatisfied Requirements:
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.codecs)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.handlers)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.schema)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.spi)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.references)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.rests.services.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.rests.transactions)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.services.simple.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.streams.listeners)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.streams.websockets)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.mapping)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.parser)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.parser.builder)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.validations)"
Error executing command: Error restarting bundles:
Could not resolve module: org.opendaylight.netconf.restconf-nb-bierman02 [318]
Bundle was not resolved because of a uses contraint violation.
org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve resource org.opendaylight.netconf.restconf-nb-bierman02 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-bierman02"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"] because it is exposed to package 'javax.annotation' from resources javax.annotation-api [osgi.identity; osgi.identity="javax.annotation-api"; type="osgi.bundle"; version:Version="1.2.0"] and org.eclipse.osgi [osgi.identity; osgi.identity="org.eclipse.osgi"; type="osgi.bundle"; version:Version="3.11.3.v20170209-1843"; singleton:="true"] via two dependency chains.
Chain 1:
org.opendaylight.netconf.restconf-nb-bierman02 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-bierman02"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"]
import: (osgi.wiring.package=javax.annotation)
|
export: osgi.wiring.package: javax.annotation
javax.annotation-api [osgi.identity; osgi.identity="javax.annotation-api"; type="osgi.bundle"; version:Version="1.2.0"]
Chain 2:
org.opendaylight.netconf.restconf-nb-bierman02 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-bierman02"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"]
import: (&(osgi.wiring.package=com.google.common.base)(&(version>=23.3.0)(!(version>=24.0.0))))
|
export: osgi.wiring.package=com.google.common.base; uses:=javax.annotation
com.google.guava [osgi.identity; osgi.identity="com.google.guava"; type="osgi.bundle"; version:Version="23.3.0.jre"]
import: (osgi.wiring.package=javax.annotation)
|
export: osgi.wiring.package: javax.annotation
org.eclipse.osgi [osgi.identity; osgi.identity="org.eclipse.osgi"; type="osgi.bundle"; version:Version="3.11.3.v20170209-1843"; singleton:="true"]
Could not resolve module: org.opendaylight.netconf.restconf-nb-rfc8040 [319]
Bundle was not resolved because of a uses contraint violation.
org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve resource org.opendaylight.netconf.restconf-nb-rfc8040 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-rfc8040"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"] because it is exposed to package 'javax.annotation' from resources javax.annotation-api [osgi.identity; osgi.identity="javax.annotation-api"; type="osgi.bundle"; version:Version="1.2.0"] and org.eclipse.osgi [osgi.identity; osgi.identity="org.eclipse.osgi"; type="osgi.bundle"; version:Version="3.11.3.v20170209-1843"; singleton:="true"] via two dependency chains.
Chain 1:
org.opendaylight.netconf.restconf-nb-rfc8040 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-rfc8040"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"]
import: (osgi.wiring.package=javax.annotation)
|
export: osgi.wiring.package: javax.annotation
javax.annotation-api [osgi.identity; osgi.identity="javax.annotation-api"; type="osgi.bundle"; version:Version="1.2.0"]
Chain 2:
org.opendaylight.netconf.restconf-nb-rfc8040 [osgi.identity; osgi.identity="org.opendaylight.netconf.restconf-nb-rfc8040"; type="osgi.bundle"; version:Version="1.7.0.SNAPSHOT"]
import: (&(osgi.wiring.package=com.google.common.base)(&(version>=23.3.0)(!(version>=24.0.0))))
|
export: osgi.wiring.package=com.google.common.base; uses:=javax.annotation
com.google.guava [osgi.identity; osgi.identity="com.google.guava"; type="osgi.bundle"; version:Version="23.3.0.jre"]
import: (osgi.wiring.package=javax.annotation)
|
export: osgi.wiring.package: javax.annotation
org.eclipse.osgi [osgi.identity; osgi.identity="org.eclipse.osgi"; type="osgi.bundle"; version:Version="3.11.3.v20170209-1843"; singleton:="true"]
karaf#root()> Unsatisfied Requirements:
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.netconf.sal.rest.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.netconf.sal.restconf.api)"
Unsatisfied Requirements:
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.codecs)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.handlers)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.schema)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.jersey.providers.spi)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.references)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.rests.services.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.rests.transactions)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.services.simple.api)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.streams.listeners)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.streams.websockets)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.mapping)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.parser)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.parser.builder)"
osgi.wiring.package; filter:="(osgi.wiring.package=org.opendaylight.restconf.nb.rfc8040.utils.validations)"
What am I missing? The complete code is available at Github
Thanks in advance!
Max

If you are seeing this on the latest ODL (Oxygen), then this is the same problem that recently sometimes surfaced on OpenDaylight's integration build as well... we are now tracking this in https://jira.opendaylight.org/browse/NETCONF-516.
We are hoping that merge of https://git.opendaylight.org/gerrit/#/c/68255/ will fix this in the short term, also https://git.opendaylight.org/gerrit/#/c/67184/ should help in the longer term (when projects bump to new odlparent); you could also try https://git.opendaylight.org/gerrit/#/c/68199/ although that was found not to help.

Related

feature:install fails and returns "Unable to resolve root" message

I have downloaded and uncompressed OpenDayLight's Sulfur release (I have tested Tar and Zip versions with the same results). I ran bin/karaf and it started correctly. Then I tried to install a feature, specifically "feature:install odl-mdsal-distributed-datastore" and I get the following error message (long):
Error executing command: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=odl-mdsal-distributed-datastore; type=karaf.feature; version="[5.0.5,5.0.5]"; filter:="(&(osgi.identity=odl-mdsal-distributed-datastore)(type=karaf.feature)(version>=5.0.5)(version<=5.0.5))" [caused by: Unable to resolve odl-mdsal-distributed-datastore/5.0.5: missing requirement [odl-mdsal-distributed-datastore/5.0.5] osgi.identity; osgi.identity=org.opendaylight.controller.sal-distributed-datastore; type=osgi.bundle; version="[5.0.5,5.0.5]"; resolution:=mandatory [caused by: Unable to resolve org.opendaylight.controller.sal-distributed-datastore/5.0.5: missing requirement [org.opendaylight.controller.sal-distributed-datastore/5.0.5] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.opendaylight.mdsal.dom.broker)(version>=9.0.0)(!(version>=10.0.0)))" [caused by: Unable to resolve org.opendaylight.mdsal.dom-broker/9.0.4: missing requirement [org.opendaylight.mdsal.dom-broker/9.0.4] osgi.service; filter:="(objectClass=org.opendaylight.mdsal.dom.api.DOMSchemaService)"; effective:=active [caused by: Unable to resolve org.opendaylight.mdsal.dom-schema-osgi/9.0.4: missing requirement [org.opendaylight.mdsal.dom-schema-osgi/9.0.4] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.opendaylight.mdsal.binding.runtime.spi)(version>=9.0.0)(!(version>=10.0.0)))" [caused by: Unable to resolve org.opendaylight.mdsal.binding-runtime-spi/9.0.4: missing requirement [org.opendaylight.mdsal.binding-runtime-spi/9.0.4] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.opendaylight.mdsal.binding.runtime.api)(version>=9.0.0)(!(version>=10.0.0)))" [caused by: Unable to resolve org.opendaylight.mdsal.binding-runtime-api/9.0.4: missing requirement [org.opendaylight.mdsal.binding-runtime-api/9.0.4] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.opendaylight.mdsal.binding.model.api)(version>=9.0.0)(!(version>=10.0.0)))" [caused by: Unable to resolve org.opendaylight.mdsal.binding-model-api/9.0.4: missing requirement [org.opendaylight.mdsal.binding-model-api/9.0.4] osgi.identity; osgi.identity="root#odl-mdsal-binding-runtime-api-9.0.4"; type=karaf.subsystem; version="[0,0.0.0]"; resolution:=mandatory [caused by: Unable to resolve root#odl-mdsal-binding-runtime-api-9.0.4: missing requirement [root#odl-mdsal-binding-runtime-api-9.0.4] osgi.identity; osgi.identity=odl-mdsal-binding-runtime-api; type=karaf.feature; version="[9.0.4,9.0.4]" [caused by: Unable to resolve odl-mdsal-binding-runtime-api/9.0.4: missing requirement [odl-mdsal-binding-runtime-api/9.0.4] osgi.identity; osgi.identity=odl-yangtools-parser; type=karaf.feature; version="[8.0.0,9.0.0)" [caused by: Unable to resolve odl-yangtools-parser/8.0.6: missing requirement [odl-yangtools-parser/8.0.6] osgi.identity; osgi.identity=odl-yangtools-xpath; type=karaf.feature; version="[8.0.6,8.0.6]" [caused by: Unable to resolve odl-yangtools-xpath/8.0.6: missing requirement [odl-yangtools-xpath/8.0.6] osgi.identity; osgi.identity=yang-xpath-impl; type=osgi.bundle; version="[8.0.6,8.0.6]"; resolution:=mandatory [caused by: Unable to resolve yang-xpath-impl/8.0.6: missing requirement [yang-xpath-impl/8.0.6] osgi.wiring.package; filter:="(osgi.wiring.package=javax.inject)"]]]]]]]]]]]]
I have tried installing other features with similar results.
However, I downloaded OpenDayLight's Phosphorus, Zip version, tried to install the same feature, and it ran successfully.
Does anyone know why feature:install fails in Sulfur but runs OK in Phosphorus?

Error installing boot features of karaf in kettle

I am trying to integrate kettle and the big data plugin into my project.
when the karaf of kettle loads the plugin named pdi-osgi-bridge-activator. it throws an exception :
2018-09-01 16:52:09.303 DEBUG 9236 --- [ Thread-52] o.a.k.f.internal.FeaturesServiceImpl : Starting bundle: pdi-osgi-bridge-activator
2018-09-01 16:52:09.365 ERROR 9236 --- [ Thread-52] o.a.k.f.internal.BootFeaturesInstaller : Error installing boot features
java.lang.Exception: Could not start bundle wrap:mvn:pentaho/pdi-osgi-bridge-activator/7.1.0.0-12 in feature(s) pentaho-base-1.0: Unresolved constraint in bundle pdi-osgi-bridge-activator [60]: Unable to resolve 60.0: missing requirement [60.0] osgi.wiring.package; (osgi.wiring.package=org.pentaho.di.core.exception)
at org.apache.karaf.features.internal.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:504) ~[3.0.3:na]
at org.apache.karaf.features.internal.FeaturesServiceImpl.installFeatures(FeaturesServiceImpl.java:459) ~[3.0.3:na]
at org.apache.karaf.features.internal.BootFeaturesInstaller.installBootFeatures(BootFeaturesInstaller.java:92) ~[3.0.3:na]
at org.apache.karaf.features.internal.BootFeaturesInstaller$1.run(BootFeaturesInstaller.java:71) [3.0.3:na]
Caused by: org.osgi.framework.BundleException: Unresolved constraint in bundle pdi-osgi-bridge-activator [60]: Unable to resolve 60.0: missing requirement [60.0] osgi.wiring.package; (osgi.wiring.package=org.pentaho.di.core.exception)
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3974) ~[org.apache.felix.main-4.2.1.jar:na]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2037) ~[org.apache.felix.main-4.2.1.jar:na]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955) ~[org.apache.felix.main-4.2.1.jar:na]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942) ~[org.apache.felix.main-4.2.1.jar:na]
at org.apache.karaf.features.internal.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:501) ~[3.0.3:na]
... 3 common frames omitted
i know the class:
org.pentaho.osgi.legacy.LegacyPluginExtenderFactory
uses
org.pentaho.di.core.exception.KettlePluginException
but these is nothing happen if i start kettle by Spoon.bat.
do i miss some arguments or configurations?
Which bundle has "org.pentaho.di.core.exception.KettlePluginException"?
It need some bundle to export it.

Karaf - Unable to resolve: missing requirement (osgi.wiring.package; (&(osgi.wiring.package=javax.jms)(version>=2.0.0)(!(version>=3.0.0)))])

I'm trying to install bundle on Karaf but but I keep getting the following error:
Caused by: org.osgi.framework.BundleException: Unable to resolve axsjmsblueprintcaller [56](R 56.0): missing requirement [axsjmsblueprintcaller [56](R 56.0)] osgi.wiring.package; (&(osgi.wiring.package=javax.jms)(version>=2.0.0)(!(version>=3.0.0))) [caused by: Unable to resolve javax.jms-api [58](R 58.0): missing requirement [javax.jms-api [58](R 58.0)] osgi.wiring.package; (osgi.wiring.package=javax.transaction.xa)] Unresolved requirements: [[axsjmsblueprintcaller [56](R 56.0)] osgi.wiring.package; (&(osgi.wiring.package=javax.jms)(version>=2.0.0)(!(version>=3.0.0)))]
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4111)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.Felix.startBundle(Felix.java:2117)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)[org.apache.felix.framework-5.4.0.jar:]
at org.apache.karaf.bundle.command.Install.execute(Install.java:96)[24:org.apache.karaf.bundle.core:4.0.4]
... 11 more
After that i'm trying to download javax.jms(javax.jms-api version 2.0.1) and copy it to deploy folder on karaf and run it again but it's still throw that exeption.
Karaf cannot start the bundle. Please help me!

Unable to install KAR containing camel-spring: spring beans missing

I've built an application bundled in an OSGi JAR package and now I'm trying to create a KAR file to easy deployment to Apache Karaf 4.0.8.
When I drop the KAR file there's a warning message complaining that it's impossible to resolve camel-spring due to the missing org.springframework.beans requirement.
2017-01-18 19:07:12,239 | WARN | raf-4.0.8/deploy | KarServiceImpl | 36 -
org.apache.karaf.kar.core - 4.0.8 | Unable to install Kar feature
interfacturas-kar/1.0.0.SNAPSHOT
org.osgi.service.resolver.ResolutionException: Unable to resolve root:
missing requirement [root] osgi.identity;
osgi.identity=interfacturas-kar;
type=karaf.feature;
version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]";
filter:="(&(osgi.identity=interfacturas-kar)
(type=karaf.feature(version>=1.0.0.SNAPSHOT)
(version<=1.0.0.SNAPSHOT))"
[caused by: Unable to resolve interfacturas-kar/1.0.0.SNAPSHOT:
missing requirement [interfacturas-kar/1.0.0.SNAPSHOT] osgi.identity;
osgi.identity=org.apache.camel.camel-spring;
type=osgi.bundle;
version="[2.17.0.redhat-630187,2.17.0.redhat-630187]";
resolution:=mandatory
[caused by: Unable to resolve org.apache.camel.camel-spring/2.17.0.redhat-630187:
missing requirement [org.apache.camel.camel-spring/2.17.0.redhat-630187]
osgi.wiring.package;
filter:="(&(osgi.wiring.package=org.springframework.beans)
(version>=3.2.0)(!(version>=4.0.0)))"]]
I cannot figure why this is happening! The kar file does contain spring-beans JAR file of an appropriate version:
$ unzip -l interfacturas-kar-1.0.0-SNAPSHOT.kar
...
614354 2017-01-11 19:07 repository/org/springframework/spring-beans/3.2.16.RELEASE/spring-beans-3.2.16.RELEASE.jar
...
The KAR file and its associated feature XML file is completely generated by karaf-maven-plugin, and it also lists the spring-beans dependency:
<bundle>wrap:mvn:org.springframework/spring-beans/3.2.16.RELEASE</bundle>
along with other spring related resources.
Any has some idea how to fix this? Or why is it happening?
BTW, camel-spring actually comes as a dependency of camel-cxf; I'm using blueprint for defining the routes.

Package uses conflict: Import-Package: org.springframework.mail.javamail; version="0.0.0"

when running my osgi application
i am getting following error:
!ENTRY com.mypackage.commons 4 0 2011-07-06 15:52:21.841
!MESSAGE
!STACK 0
org.osgi.framework.BundleException: The bundle could not be resolved. Reason: Package uses conflict: Import-Package: org.springframework.mail.javamail; version="0.0.0"
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverError(AbstractBundle.java:1313)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolutionFailureException(AbstractBundle.java:1297)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:319)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:370)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1068)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:557)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:464)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:248)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:445)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:220)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:330)
please advise.
problem solved by using latest version of org.springframework.context.support dependency.
More information is necessary to diagnose the problem. First I recommend running on Apache Felix rather than Equinox – even if only temporarily – because it has better diagnostics for uses-constraints problems. Also try reading my blog posts: http://njbartlett.name/2011/02/09/uses-constraints.html and http://njbartlett.name/2011/03/31/uses-constraints-in-felix.html

Resources