If I have a OSGI Bundle that has dependency jars nested inside the OSGI Bundle jar, do I need to list those classes in the Import-Package manifest so that I could use them? I would think not.
Also how do I add these dependency jars into my bundle. Do I just put them in the root folder? Do I need to add anything to the manifest file to be able to use these dependencies?
Avoid using Bundle-ClassPath manually. You can use maven-bundle-plugin to solve and embed your third party dependencies like this:
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.3</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>lumina.extensions.drivers.luminadb</Export-Package>
<Bundle-Activator>lumina.extensions.drivers.luminadb.internal.Activator</Bundle-Activator>
<Embed-Dependency> YOUR ARTIFACT ID HERE </Embed-Dependency>
</instructions>
</configuration>
</plugin>
(...)
</plugins>
For more information visit http://web.ist.utl.pt/ist162500/?p=110
You should not use Import-Package for embedded jars. Instead use Bundle-ClassPath: .,myjar.jar to add the embedded jars to the bundle classpath.
Related
I've got a CXF web service app in Fuse, and it's got a reference in a camel context xml file to a jar containing my files generated from a WSDL.
<cxf:cxfEndpoint id="LookupEndpoint"
address="${my.LookupUri}"
serviceClass="com.whatever.IWebService"
wsdlURL="wsdl/MyWsdl.wsdl"/>
com.whatever.* is in my <Import-Package> list. The jar is in my maven dependencies. I can say import com.whatever.IWebService; and it doesn't complain.
But maven-bundle-plugin doesn't include this package in the MANIFEST.MF
It includes all my other packages that I requested. But not this one. So in Fuse, when I deploy it, I get ClassNotFoundException, referring to the context.xml class loading.
It is very frustrating. Is there a way to maybe force the plugin to import a certain package? Because their auto-magical dependency solver is ignoring my <Import-Package>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${version.maven-bundle-plugin}</version>
<extensions>true</extensions>
<configuration>
<manifestLocation>src/main/resources/META-INF</manifestLocation>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Import-Package>
*,
com.imports.this.one.fine*,
com.imports.this.one.just.fine*,
com.imports.does.not.import.this.one.*,
</Import-Package>
<Export-Package>
com.something.export.*
</Export-Package>
</instructions>
</configuration>
</plugin>
When you use <Import-Package> with a wildcard, then an OSGi Import-Package header is generated for all packages matching the wildcard that the code in your bundle depends on.
If the maven-bundle-plugin is not generating an import for the package you expect, it means that the code in your bundle doesn't actually reference that package.
Rather than importing this package, shouldn't it be included in the bundle?? Why do you want to import it?
How can I achieve that the plugin does not inline the dependencies in the new build jar file?
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Category>tools</Bundle-Category>
<Fragment-Host>org.jsmpp.jsmpp</Fragment-Host>
<Private-Package>!</Private-Package>
<Export-Package>
org.jsmpp.*;version="2.2.3"
</Export-Package>
<Import-Package>!org.slf4j</Import-Package>
<Bundle-Version>2.2.3</Bundle-Version>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jsmpp</groupId>
<artifactId>jsmpp</artifactId>
</dependency>
</dependencies>
The plugin does not inline any dependencies, unless you include an Embed-Dependency instruction. That instruction can be inherited from a parent POM.
All packages that match the <Export-Package> instruction are included in the bundle, even if those packages come from a dependency. So you can either specify all packages from your bundle explicitly, or use a wildcard and exclude unwanted packages with the '!' prefix, e.g.
<Export-Package>
org.jsmpp.*;version="2.2.3",
!org.jsmpp.donotwant
</Export-Package>
see maven-bundle-plugin documentation
Use _exportcontents instead of Export-Package.
_exportcontents affect only the manifest, whereas Export-Package modify the manifest and the content of your bundle.
see: http://www.aqute.biz/Bnd/Format
I have a maven project , which needs to copy webapp/WEB-INF/ resources from another maven project which is packaged as a war .
How do I do it ?
PLease suggest
As Bittrance said, you should use the maven dependency plugin.
The better way is to create project that include all your shared resources, probably a type zip, which is build up with the assembly plugin. This is the good "maven way". It's a better solution than unpacking a war.
Then, refer it
<dependency>
<groupId>com.mygroup/groupId>
<artifactId>my-dependencies</artifactId>
<version>1.0.0</version>
<type>zip</type>
</dependency>
Next, you use the maven dependency plugin to unpack your resources, in the directory of your choice (probably WEB-INF/ ?)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-cfg-test-resources</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/WEB-INF/</outputDirectory>
<includeArtifacIds>my-resources</includeArtifacIds>
<excludeTypes>pom</excludeTypes>
<excludeTransitive>true</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
I'm not realy sure of this code snippet (written for another purpose), but this is an example.
For more information, please follow this link : http://maven.apache.org/plugins/maven-dependency-plugin/
If you can't shared a common-project including your files, you can unpack war including only ftl (or whatever you want), but it's not a realy clean solution ;)
There is a lot of posts that deal with this subject :
Unzip dependency in maven
...
Just try with the keywords maven-dependency-plugin, unpack :)
Hope that will help you.
I can see some alternatives:
Use external references in your version control system to point all repos to the same files.
The Maven Dependency module can copy and unpack project dependencies. From there, you can use the Maven Assembly plugin (or Ant targets) to include parts of that dependency in your own installation.
At least for the FTL files, perhaps you could package them in a separate Jar file and then load them as resources through the class loader.
If the resources are filtered, you may get into problem with solution 1 if you want the filtered version and 2, 3 if you want the source version.
Hope this helps.
(This assumes your dependent project is java (jar) and not another web app, if it is a webapp I think the solution is similar).
I suggest a (slightly) different approach:
Instead of reading resources from war, add this to your war pom, to generate a jar in the artifact as well as a war:
<!-- maven war plugin config -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
...
<attachClasses>true</attachClasses>
<classesClassifier>some-string</classesClassifier>
</configuration>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
</plugin>
...
<resources>
<!-- This is for inclusion in the jar, so dependent module can load it -->
<resource>
<targetPath>some-path</targetPath>
<directory>src/main/webapp/path...</directory>
<includes>
<include>your-resource</include>
</includes>
</resource>
</resources>
And this to your consuming pom, so the generated jar will be loaded:
<dependency>
<groupId>com.company</groupId>
<artifactId>...</artifactId>
<classifier>some-string</classifier>
</dependency>
Then you will be able to load the resources the usual way (getResourceAsStream("some-path/your-resource"))
I have a project with produces an OSGI bundle using the maven-bundle-plugin. The configuration looks like this:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<inherited>true</inherited>
<configuration>
<instructions>
<Export-Package>${bubble.osgi.exports}</Export-Package>
<Import-Package>${bubble.osgi.imports}</Import-Package>
<Embed-Dependency>${bubble.osgi.embed.dependencies}</Embed-Dependency>
<_versionpolicy>[$(version;==;$(#)),$(version;+;$(#)))</_versionpolicy>
</instructions>
<versions>
<bubble.osgi.version.clean>${project.version}</bubble.osgi.version.clean>
</versions>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>cleanVersions</goal>
</goals>
</execution>
</executions>
</plugin>
The outcome of the project is a single jar file with all the osgi stuff, embedded dependencies etc. included. I rather would like to have 2 jars as outcome, one with the osgi stuff included and one without, as the embedded dependencies cause problems when using it just as a plain jar.
Is there any other way than using the maven assembly plugin for this?
You can move maven-bundle-plugin configuration into separate profile and use something like
mvn package -Posgi
or default. But there will only one artifact produced per build.
I would recommend to use 2 different pom.xml files (in the project) which will produces 2 different artifacts.
The default pom.xml should generate the plain library like foo:bar:1.0.0
Another pom-osgi.xml should generate the OSGi library like foor:bar-osgi:1.0.0
To build the library with another pom use
mvn -f pom-osgi.xml install
I am writing a project for acceptance testing and for various reasons this is dependent on another project which is packaged as a WAR. I have managed to unpack the WAR using the maven-dependency-plugin, but I cannot get my project to include the unpacked WEB-INF/lib/*.jar and WEB-INF/classes/* to be included on the classpath so the build fails. Is there a way to include these files into the classpath, or is there a better way of depending on a WAR?
Many thanks.
There's another option since maven-war-plugin 2.1-alpha-2. In your WAR project:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
This creates a classes artifact which you can use in the acceptance tests project with:
<dependency>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<classifier>classes</classifier>
</dependency>
Indeed, by design, Maven doesn't resolve transitive dependencies of a war declared as dependency of a project. There is actually an issue about that, MNG-1991, but it won't be solved in Maven 2.x and I'm not sure that I don't know if overlays allow to workaround this issue. My understanding of the suggested solution is to duplicate the dependencies, for example in a project of type pom.
(EDIT: After some more digging, I found something interesting in this thread that I'm quoting below:
I have been helping out with the development of the AppFuse project over
the last month where we make heavy use of the war overlay feature in the
Maven war plugin. It is a really nifty feature!
To get max power with war overlays I have developed the Warpath plugin
that allows projects to use war artifacts as fully fledged dependencies.
In brief:
1) The contents of the /WEB-INF/classes directory in the war dependency
artifacts can be included in the project's classpath for normal compile,
etc tasks.
2) Transitive dependencies from the war dependency artifacts become
available for use by other plugins, e.g. compile and ear - so no more
having to include all the dependencies when creating skinny wars!
The plugin has now been actively used in the AppFuse project for the
last few months, and I feel it is at a point where it is both usable and
stable.
Would the war plugin team be interested in including the warpath
functionality inside the war plugin? It would seem to be the most
natural place to host it.
So, I don't have any experience with it, but the maven warpath plugin actually looks nice and simple and is available in the central repo. To use it,include the following plugin configuration element in your pom.xml file:
[...]
<build>
<plugins>
<plugin>
<groupId>org.appfuse</groupId>
<artifactId>maven-warpath-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>add-classes</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
And add the war dependencies you want included in the classpath as warpath type dependencies:
[...]
<dependencies>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.appfuse</groupId>
<artifactId>appfuse-web</artifactId>
<version>2.0</version>
<type>warpath</type>
</dependency>
</dependencies>
[...]
Both the war and warpath dependency types are needed: the war type is used by the Maven war plugin to do the war overlay, the warpath type is used by the Warpath plugin to determine the correct list of artifacts for inclusion in the project classpath.
I'd give it a try.)
Use overlays. First, your test project need to have also packaging war.
Declare dependency of war project you want to test:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>your-project-arftifactId</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>test</scope>
</dependency>
then configure maven-war-plugin overlay:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webresources</directory>
<filtering>true</filtering>
</resource>
</webResources>
<overlays>
<overlay/>
<overlay>
<groupId>your.group</groupId>
<artifactId>your-project-artifactId</artifactId>
</overlay>
</overlays>
</configuration>
</plugin>
In the above example in test project I overwrite webresources configuration files (like conxtext etc.).
EDIT: This solution wasn't tested with Maven 3.
Good point, Justin. That got me actually solving my problem, namely: including a war into an assembly AND including all its transitive dependencies.
I could not duplicate the war-dependency as 'jar' as you suggested since the assembly plugin would not find a jar referenced by that groupId/artefactId, but
duplicating the war-dependency as type pom
works!
The war and its transitive dependencies are not included in the assembly.
To exclude the (now also appearing) pom file I had to add an exclude element like this:
<excludes>
<exclude>*:pom</exclude>
</excludes>
into my assembly.xml file.
I think this could also be a workaround for the original question of this thread.
If you list the dependency on the war project as a jar dependency it seems to pickup the required jars/resources. I'm using Maven 2.2 + m2eclipse.