Deploying a Maven Built OSGi Package in ServiceMix: "Unresolved constraint in bundle ..." - java

I can build my projects "samba.interfaces" and "samba.message" without problems. But when I try to start "samba.message" bundle in ServiceMix (requires the "samba.interfaces" bundle that contains the package de.samba.common), I get the following error:
Error executing command: Unresolved constraint in bundle message [195]: module;
(&(bundle-symbolic-name=de.samba.common)(bundle-version>=0.0.1))
So, what is the symbolic name used for? Does it have to be the same as the main package? This is the part of the POM that specifies the message bundle:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.2.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Activator>de.samba.message.Activator</Bundle-Activator>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>SAMBA Message</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Import-Package>
javax.jws,
javax.wsdl,
javax.xml.bind,
javax.xml.bind.annotation,
javax.xml.namespace,
javax.xml.ws,
META-INF.cxf,
META-INF.cxf.osgi,
org.apache.cxf.endpoint,
org.apache.cxf.bus,
org.apache.cxf.bus.spring,
org.apache.cxf.bus.resource,
org.apache.cxf.configuration.spring,
org.apache.cxf.resource,
org.apache.cxf.service.model,
org.apache.cxf.jaxws,
org.apache.cxf.transport.http_osgi,
org.springframework.beans.factory.config,
org.springframework.beans.factory.xml,
org.springframework.core.io,
org.springframework.beans.factory,
org.springframework.context.support,
org.springframework.beans,
org.springframework.context,
org.osgi.framework,
org.apache.log4j,
de.samba.common.auditingcontrol.*,
de.samba.common.collect.*,
de.samba.common.message.*,
de.samba.common.repository.*,
de.samba.common.security.*,
de.samba.common,
*
</Import-Package>
<Export-Package>de.samba.message.*</Export-Package>
<Private-Package>
</Private-Package>
<!--
<DynamicImport-Package>*</DynamicImport-Package>
-->
</instructions>
Any ideas what might cause this error?

I do not have much idea of OSGI, but have the following observations.
The documentation specifies how <Bundle-SymbolicName> is computed. In their Real-World Example, they do not seem to have the projectId.
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>

Okay, I found the problem myself. Error executing command: Unresolved constraint in bundle message [195]: module; (&(bundle-symbolic-name=de.samba.common)(bundle-version>=0.0.1)) was completely unexpected, and it came from having a MANIFEST.MF file inside src/main/resources/META-INF that usually describes the bundle information if you're doing plugin/OSGi development. Seems that the Maven BND Plugin includes that file and ONLY generates new information if it isn't there.
So the problem was solved after removing src/main/resources/META-INF/MANIFEST.MF so the plugin could generate the proper one.

Related

Apache Felix 6.0.1: BundleException on init

With Apache Felix 6.0.1 I'm getting the following error when initializing the OSGi framework:
ERROR: Error parsing system bundle statement.
org.osgi.framework.BundleException: Exported package names cannot be zero length.
at org.apache.felix.framework.util.manifestparser.ManifestParser.normalizeExportClauses(ManifestParser.java:865)
at org.apache.felix.framework.util.manifestparser.ManifestParser.<init>(ManifestParser.java:217)
at org.apache.felix.framework.ExtensionManager$ExtensionManagerRevision.update(ExtensionManager.java:977)
at org.apache.felix.framework.ExtensionManager$ExtensionManagerRevision.access$000(ExtensionManager.java:885)
at org.apache.felix.framework.ExtensionManager.updateRevision(ExtensionManager.java:378)
at org.apache.felix.framework.Felix.init(Felix.java:744)
at org.apache.felix.framework.Felix.init(Felix.java:637)
I didn't get this error with Apache Felix 5.x
And I couldn't find any JAR which has an empty package names declaration except my executable JAR, which is not an OSGi bundle at all.
Why do I get this error?
Update
The issue seems to be with the bundle goal of the Maven Bundle Plugin v4.1.0
In one startup JAR with bundle packaging I have:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<versions>
<module.b.osgi.version.clean>${project.version}</module.b.osgi.version.clean>
</versions>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>cleanVersions</goal>
</goals>
</execution>
</executions>
</plugin>
In a properties file with resource filtering set to true I have:
org.osgi.framework.system.packages.extra=${module-b.packages}
module-b.packages=${module-a.packages}, \
org.mymodule.b;version="${module.b.osgi.version.clean}", \
${foo-${foo.specification.version}}
In the generated target/classes directory I have as expected:
org.osgi.framework.system.packages.extra=${module-b.packages}
module-b.packages=${module-a.packages}, \
org.mymodule.b;version="0.14.0.SNAPSHOT", \
${foo-${foo.specification.version}}
But in the JAR it then suddenly looks like this:
org.osgi.framework.system.packages.extra=${module-b.packages}
module-b.packages=${module-a.packages}, \
org.mymodule.b;version="0.14.0.SNAPSHOT", \
Somehow ${foo-${foo.specification.version}} got stripped to empty string!
Update 2
As this happens in the startup code, my current work-around is to change the packaging type back to jar. The OSGi clean version still gets substituted, but the Manifest file doesn't contain any OSGi entries anymore.
I think it is a regression bug in the Maven Bundle Plugin.
I've filed an issue here: https://issues.apache.org/jira/browse/FELIX-5980

Can i place third party jars in karaf (any specific folder) to resolve transitive dependencies?

I have various self made projects that have third party libraries dependencies.
I am bundling them for OSGI container but unable to resolve deep dependencies in my projects.
Now i am looking for karaf folder where i can place my libraries so bundles can directly access them and not to install them.
More over i am using maven too.
EDIT:
After following your 'feature' solution i am able to produce manifest containg transitive dependencies but problem is now it also look for very common java files: e.g: below is list of quite big dependencies:
bsh -- Cannot be resolved
com.fasterxml.jackson.annotation -- Cannot be resolved
com.fasterxml.jackson.core -- Cannot be resolved
com.fasterxml.jackson.databind -- Cannot be resolved
com.fasterxml.jackson.databind.annotation -- Cannot be resolved
com.fasterxml.jackson.databind.module -- Cannot be resolved
com.gargoylesoftware.htmlunit -- Cannot be resolved
com.gargoylesoftware.htmlunit.util -- Cannot be resolved
com.google.protobuf -- Cannot be resolved
com.ibm.uvm.tools -- Cannot be resolved
com.ibm.websphere.uow -- Cannot be resolved
com.ibm.wsspi.uow -- Cannot be resolved
com.jamonapi -- Cannot be resolved
com.jamonapi.utils -- Cannot be resolved
com.jayway.jsonpath -- Cannot be resolved
com.jcraft.jzlib -- Cannot be resolved
com.mysema.query.types -- Cannot be resolved
com.sun.javadoc -- Cannot be resolved and overwritten by Boot Delegation
com.sun.jdmk.comm -- Cannot be resolved and overwritten by Boot Delegation
com.sun.net.httpserver -- Cannot be resolved and overwritten by Boot Delegation
com.sun.tools.javadoc -- Cannot be resolved and overwritten by Boot Delegation
com.sun.xml.fastinfoset.sax -- Cannot be resolved and overwritten by Boot Delegation
com.sun.xml.fastinfoset.stax -- Cannot be resolved and overwritten by Boot Delegation
com.typesafe.config -- Cannot be resolved
groovy.lang -- Cannot be resolved
groovy.xml -- Cannot be resolved
javassist -- Cannot be resolved
javax.activation from org.apache.felix.framework (0)
javax.annotation from org.apache.felix.framework (0)
javax.crypto from org.apache.felix.framework (0)
javax.crypto.spec from org.apache.felix.framework (0)
javax.ejb -- Cannot be resolved
javax.el -- Cannot be resolved
javax.enterprise.concurrent -- Cannot be resolved
javax.enterprise.context -- Cannot be resolved
javax.enterprise.context.spi -- Cannot be resolved
javax.enterprise.event -- Cannot be resolved
javax.enterprise.inject -- Cannot be resolved
javax.enterprise.inject.spi -- Cannot be resolved
javax.enterprise.util -- Cannot be resolved
To answer your question: You could drop all your dependency bundles into the $KARAF_HOME/deploy folder and Karaf would deploy them for you.
However, this is not very convenient as it is a manual process and not driven by Maven. Instead have a look at Karaf's concept of feature repositories. You can use the Karaf maven plugin to create a feature repository for your bundles and their (transitive) dependencies. If you need to ship your application as a single artifact, you can use the same plugin to create a KAR archive, which is zip file that contains both the feature repository and the required dependencies in a self-contained deployment unit.
To get started put a template feature.xml file into src/main/feature:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.3.0 http://karaf.apache.org/xmlns/features/v1.3.0"
name="My feature">
<feature name="${project.artifactId}" version="${project.version}" description="Describe feature here">
<!-- Add "self" to the list of dependencies -->
<bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
</feature>
</features>
Then set up the plugin to populate the feature template based on your maven dependencies:
<plugin>
<groupId>org.apache.karaf.tooling</groupId>
<artifactId>karaf-maven-plugin</artifactId>
<configuration>
<includeTransitiveDependency>true</includeTransitiveDependency>
</configuration>
<executions>
<execution>
<id>generate-features-descriptor</id>
<goals>
<goal>features-generate-descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
Building your project will create an additional maven artifact together with your bundle jar in your local maven repository: xxx-features.xml
You can make a local Karaf aware of your feature repository with the feature:repo-add command. Then add your feature with the feature:install command. This will start your bundle and all its declared (transitive) Maven dependencies.
EDIT:
As you mentioned in the comments that some (all?) your dependencies are plain JARs, not OSGi bundles, possibly you are better off embedding those non-OSGi dependencies into your own bundle with the maven-bundle-plugin. This can be quite tedious though. Most non-OSGi JARs have package imports that are either not used during runtime at all, or not used in your specific usage scenario. To avoid blowing up your OSGi dependency list beyond your list of transitive maven dependencies, you then have to prevent those "inherited" packages from being added to the list of package imports in the MANIFEST of your own bundle. E.g., I have a bundle that uses the httl template library, which again depends on Javassist. Neither are OSGi bundles. So I embed both and suppress the import of the packages declared in either the httl or javassist code but not required at runtime:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Embed-Dependency>*;scope=compile|runtime;inline=false;artifactId=httl|javassist</Embed-Dependency>
<Embed-Transitive>false</Embed-Transitive>
<Import-Package>
!com.alibaba.*,
!com.thoughtworks.*,
!javassist.*,
!net.htmlparser.*,
!org.apache.commons.logging.*,
!org.codehaus.jackson.*,
!org.joda.convert.*,
!com.sun.jdi.*,
!javax.servlet.*,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
If I understand your question correctly, you want to build your artefact but not include the 3rd party libraries. Have you tried setting the 3rd party libraries you do not want bundled to provided?
e.g.
<dependency>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
<version>[1.0,]</version>
<scope>provided</scope>
</dependency>

karaf 3 with OSGi , how install a bundle

How create a bundle using Apache karaf 3? Someone know ?
I have try in Eclipse:
I export a jar with a manifest file ... and why I have this error:
karaf#root(dev)> feature:repo-add file:///C:/Users/xx/Downloads/apache-kara
f-3.0.1/apache-karaf-3.0.1/deploy/features.xml
Adding feature url file:///C:/Users/xx/Downloads/apache-karaf-3.0.1/apache-
karaf-3.0.1/deploy/features.xml
karaf#root(dev)> feature:install greeter_server
Error executing command: Jar is not a bundle, no Bundle-SymbolicName file:///C:/
Users/xx/Downloads/apache-karaf-3.0.1/apache-karaf-3.0.1/deploy/nebula_cdat
etime_VF4.jar
karaf#root(dev)>
This is my features.xml:
<features>
<feature name='greeter_server' version='1.0'>
<bundle>file:///C:/Users/xx/Downloads/apache-karaf-3.0.1/apache-karaf-3.0.1/deploy/nebula_cdatetime_VF4.jar</bundle>
</feature>
</features>
When you want to export a bundle or a declarative service from eclipse rcp you must use the file -> export -> plugin development-> deployable plugins and fragments as explained here.
Obviously the project you want to export as a bundle must have a sound manifest file. To have an idea of a correct osgi-friendly structure your project should have, you could create a test plugin project in eclipse rcp using the File → New → Other... → Plug-in Development → Plug-in Project menu. In the wizard you can choose to create a simple osgi bundle with an activator. The outcome is a skeleton for your new osgi bundle.
I think an easier and cleaner way is to use Maven. This way you can produce a correct OSGI ready JAR which may be loaded quickly into Karaf.
In this case pom.xml file should be like this:
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>your.group
<artifactId>artifact-123</artifactId>
<name>Karaf OSGI Module</name>
<packaging>bundle</packaging>
....
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions />
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
This kind of POM file will produce a JAR which is OSGI compatible and you don't have to mess up with absolute file names. In your feature.xml we can declare the module like this:
<bundle>mvn:your.group/artifact-123/${pom.version}</bundle>

Can't get rid of Split package, multiple jars provide the same package

I have main project (projectA), which has a library depencency (projectB), both has package.subpackage in them. I would like to inline the library in the main project. Main project configuration is quite simple (in addition the the depencency listed with 'compile' scope:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions combine.inherited="append">
...
<Export-Package>package.*;version=${packet.version};-split-package:=merge-first</Export-Package>
<Bundle-SymbolicName>${project.artifactId};singleton=true</Bundle-SymbolicName>
</instructions>
</configuration>
</plugin>
Yet it yields following warning
--- maven-bundle-plugin:2.4.0:bundle (default-bundle) # projectA ---
Bundle project:projectA:bundle:version : Split package, multiple jars provide the same package:project/subproject
Use Import/Export Package directive -split-package:=(merge-first|merge-last|error|first) to get rid of this warning
Package found in [Jar:., Jar:subproject]
Class path [Jar:., Jar:subproject]
I have split-package directive yet the warning persists.
What I would love it a way to simply inline everything from the explicitly listed artifact and nothing more (even if there are more dependencies stated), without any transitive dependencies. Preferably without any warnings about split package.
I think that you need the maven shade plug-in

unable to resolve jar dependencies for annotation processor

I have an annotation processor that depends on an external jar - lib.jar
I'm packaging my processor as a jar and using it while compiling my client.
I had it working fine until I introduced lib.jar when the client compilation started failing with this message.
Exception thrown while constructing Processor object: java.lang.NoClassDefFoundError: com/foo/FooBar
I tried placing lib.jar in the classpath for my client but it didn't help. What am I missing?
Add lib.jar to your annotation factory classpath in addition to your processor jar. In Eclipse, it's under project properties, Java Compiler, Annotation Processing, Factory Path.
(a bit late)
The search path is explained here :
http://docs.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#processing
and it seems that dependencies only need to be in the classpath.
with maven:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<annotationProcessors>
<annotationProcessor>
*your annotation class qualified name*
</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
plus the dependency to the annotation processor artifact.
I had this issue in eclipse IDE to use an annotation processor having external dependencies.
To solve his you can build a jar-with-dependencies lib to be used in Eclipse IDE.

Categories

Resources