Pax Exam test with embedded karaf container: One mvn dependency in feature must be preloaded

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Pax Exam test with embedded karaf container: One mvn dependency in feature must be preloaded

Steinar Bang
Version numbers: karaf 4.0.9
                 pax exam 4.10.0

Since moving to the karaf container in the pax exam tests I've tried to
simplify things further.

The current code starts the war bundle manually:
    @Before
    public void setup() throws BundleException {
        // Can't use injection for the Webapp service since the bundle isn't
        // started until setUp and all injections are resolved
        // before the tests start.
        //
        // Creating a service listener instead.
        ukelonnServiceListener = new ServiceListener() {

            @Override
                public void serviceChanged(ServiceEvent event) {
                    @SuppressWarnings("rawtypes")
                        ServiceReference sr = event.getServiceReference();
                    @SuppressWarnings("unchecked")
                        Object rawService = bundleContext.getService(sr);
                    if (rawService instanceof UkelonnService) {
                        UkelonnService service = (UkelonnService) rawService;
                        switch(event.getType()) {
                          case ServiceEvent.REGISTERED:
                            ukelonnService = service;
                            break;
                          default:
                            break;
                        }
                    }
                }
            };
        bundleContext.addServiceListener(ukelonnServiceListener);

        // The war bundle has to be manually started or it won't work
        final String bundlePath = "mvn:no.priv.bang.ukelonn/ukelonn.bundle/" + getMavenProjectVersion() + "/war";
        installWarBundle = bundleContext.installBundle(bundlePath);
        installWarBundle.start();
    }

    @After
    public void tearDown() throws BundleException {
    installWarBundle.stop();
    }

But I figured that if the war bundle starts by itself in karaf it would
start by itself in the pax exam karaf container.

So I removed @Before and @After methods, shown above, and replaced the
injection
    @Inject
    BundleContext bundleContext;

with the injection
    @Inject
    UkelonnService ukelonnService;

(UkelonnService is a web service that is registered once the war bundle
has fully started. It's not used in production. I've just used it in
tests and during debugging in gogo shell).

But that failed on startup with a strange error message, and was fixed
by a strange cure.

The error message I got, was:
2017-04-17 16:04:54,117 | ERROR | FelixStartLevel  | BootFeaturesInstaller            | 6 - org.apache.karaf.features.core - 4.0.9 | Error installing boot features
org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=ukelonn; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=ukelonn)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve ukelonn/1.0.0.SNAPSHOT: missing requirement [ukelonn/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.ukelonn; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.ukelonn/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.ukelonn/1.0.0.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.apache.shiro.authc)(version>=1.3.0)(!(version>=2.0.0)))"]]
        at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42)
        at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:389)
        at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
        at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:347)
        at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:216)
        at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:263)
        at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1176)
        at org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:1074)
        at java.util.concurrent.FutureTask.run(Unknown Source)[:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)[:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)[:1.8.0_121]
        at java.lang.Thread.run(Unknown Source)[:1.8.0_121]

This is strange, because the missing package is in a bundle that's
referred to in the ukelonn karaf feature. The template file is here:
 https://github.com/steinarb/ukelonn/blob/master/ukelonn.bundle/src/main/feature/feature.xml

The missing requirement is the first non-feature dependency of the
feature. In the template file, it is:
  <bundle start-level="80">mvn:org.apache.shiro/shiro-core/${dependency.shiro.version}</bundle>

In the feature repository that is loaded into karaf, it is:
        <bundle start-level="80">mvn:org.apache.shiro/shiro-core/1.3.1</bundle>

The strange fix, is that if I add this maven bundle specifically to the
karaf container pax exam config, then the test starts without a problem:
    @Configuration
    public Option[] config() {
        final MavenArtifactUrlReference karafUrl = maven().groupId("org.apache.karaf").artifactId("apache-karaf-minimal").type("zip").versionAsInProject();
        final MavenArtifactUrlReference paxJdbcRepo = maven().groupId("org.ops4j.pax.jdbc").artifactId("pax-jdbc-features").versionAsInProject().type("xml").classifier("features");
        final MavenArtifactUrlReference ukelonnFeatureRepo = maven().groupId("no.priv.bang.ukelonn").artifactId("ukelonn.karaf").versionAsInProject().type("xml").classifier("features");
        return options(
            karafDistributionConfiguration().frameworkUrl(karafUrl).unpackDirectory(new File("target/exam")).useDeployFolder(false).runEmbedded(true),
            configureConsole().ignoreLocalConsole().ignoreRemoteShell(),
            junitBundles(),
            mavenBundle("org.apache.shiro", "shiro-core").versionAsInProject(),
            features(paxJdbcRepo),
            features(ukelonnFeatureRepo, "ukelonn-db-derby-test", "ukelonn"));
    }

So my questions are:
 1. Why wasn't the mvn: URL in the feature enough to load the
    dependency?
 2. Why did it help to preload the bundle explitly?
 3. Why is it just one of the bundles required by the feature that has
    this problem?


Thanks!


- Steinar

PS its not a showstopper, I have a workaround that makes the test work
by specifying the bundle explicitly, I just would like to know why this
happens

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Pax Exam test with embedded karaf container: One mvn dependency in feature must be preloaded

Steinar Bang
>>>>> Steinar Bang <[hidden email]>:
> But that failed on startup with a strange error message, and was fixed
> by a strange cure.

> The error message I got, was:
> 2017-04-17 16:04:54,117 | ERROR | FelixStartLevel  | BootFeaturesInstaller            | 6 - org.apache.karaf.features.core - 4.0.9 | Error installing boot features
> org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=ukelonn; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=ukelonn)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve ukelonn/1.0.0.SNAPSHOT: missing requirement [ukelonn/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.ukelonn; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.ukelonn/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.ukelonn/1.0.0.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.apache.shiro.authc)(version>=1.3.0)(!(version>=2.0.0)))"]]
> at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42)
> at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:389)
> at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
> at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:347)
> at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:216)
> at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:263)
> at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1176)
> at org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:1074)
> at java.util.concurrent.FutureTask.run(Unknown Source)[:1.8.0_121]
> at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)[:1.8.0_121]
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)[:1.8.0_121]
> at java.lang.Thread.run(Unknown Source)[:1.8.0_121]

I have no idea how or why, but karaf stopped requiring the preloaded
bundle.  Now it works as expected, with the dependency loaded from the
feature:
 https://github.com/steinarb/ukelonn/blob/using-vaadin/ukelonn.tests/src/test/java/no/priv/bang/ukelonn/tests/UkelonnServiceIntegrationTest.java#L37

I haven't tried building from a clean workspace and clean
~/.m2/repository (I will cross that bridge if I get to it).

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Pax Exam test with embedded karaf container: One mvn dependency in feature must be preloaded

Steinar Bang
>>>>> Steinar Bang <[hidden email]>:

>>>>> Steinar Bang <[hidden email]>:
>> But that failed on startup with a strange error message, and was fixed
>> by a strange cure.

>> The error message I got, was:
>> 2017-04-17 16:04:54,117 | ERROR | FelixStartLevel  | BootFeaturesInstaller            | 6 - org.apache.karaf.features.core - 4.0.9 | Error installing boot features
>> org.osgi.service.resolver.ResolutionException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=ukelonn; type=karaf.feature; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; filter:="(&(osgi.identity=ukelonn)(type=karaf.feature)(version>=1.0.0.SNAPSHOT)(version<=1.0.0.SNAPSHOT))" [caused by: Unable to resolve ukelonn/1.0.0.SNAPSHOT: missing requirement [ukelonn/1.0.0.SNAPSHOT] osgi.identity; osgi.identity=no.priv.bang.ukelonn; type=osgi.bundle; version="[1.0.0.SNAPSHOT,1.0.0.SNAPSHOT]"; resolution:=mandatory [caused by: Unable to resolve no.priv.bang.ukelonn/1.0.0.SNAPSHOT: missing requirement [no.priv.bang.ukelonn/1.0.0.SNAPSHOT] osgi.wiring.package; filter:="(&(osgi.wiring.package=org.apache.shiro.authc)(version>=1.3.0)(!(version>=2.0.0)))"]]
>>       at org.apache.felix.resolver.ResolutionError.toException(ResolutionError.java:42)
>>       at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:389)
>>       at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:375)
>>       at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:347)
>>       at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:216)
>>       at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:263)
>>       at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1176)
>>       at org.apache.karaf.features.internal.service.FeaturesServiceImpl$1.call(FeaturesServiceImpl.java:1074)
>>       at java.util.concurrent.FutureTask.run(Unknown Source)[:1.8.0_121]
>>       at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)[:1.8.0_121]
>>       at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)[:1.8.0_121]
>>       at java.lang.Thread.run(Unknown Source)[:1.8.0_121]

> I have no idea how or why, but karaf stopped requiring the preloaded
> bundle.  Now it works as expected, with the dependency loaded from the
> feature:
>  https://github.com/steinarb/ukelonn/blob/using-vaadin/ukelonn.tests/src/test/java/no/priv/bang/ukelonn/tests/UkelonnServiceIntegrationTest.java#L37

> I haven't tried building from a clean workspace and clean
> ~/.m2/repository (I will cross that bridge if I get to it).

FWIW I think that all of the weirdness I saw was caused by me using
three different versions of osgi core to build the various bundles.

When I moved to karaf 4.1.1 and OSGi 6.0 I cleaned up all of that and
all bundles now have the same version of OSGi core (and the need for the
troublesome OSGi compendium went away):
 https://github.com/steinarb/ukelonn/commit/9fc41d0ee19b5758526bc8165667569e697dfa36


The reason for the different osgi.core versions in the project predates
my move to karaf, where I wanted my app to run both with "mvn
pax:provision" and running from a manually set up pax exam test.  This
required quite a bit of trial and error experimentation.

I think part of my reluctance to make the move to karaf last autumn, was
that I had invested so much time and effort into making the "mvn
pax:provision" run, and the manually set up pax exam test load the
bundles right... I didn't just want to throw that effort away...:-)

But now I'm glad I did. :-)

Loading...