I was recently trying to solve problem with an Eclipse RCP application that has its build managed entirely by Maven (with Tycho plugin) and I have spent hours trying to find a clear and reliable solution on how-to integrate it properly with Maven pom-defined dependent components.
The problem definition
- Creating a single standalone Eclipse RCP that builds with Maven using Tycho plugin, as for headless automated compilation,
- and at the same time uses the Simple Framework (for convenient Java object serialization to XML) taken from Maven central repository that way.
The problem turned out to be a bit non-trivial - mainly becuase it requires bridging two separate realms:
- the native Maven view of things
- with the way Eclipse sees the world
They are not compatible to each other.
Note: The term
plug-in is heavily overloaded here in this post. It is
very well applicable to the context of Eclipse development (PDE and plug-ins as
fundamental block the entire Eclipse’s is made of) as well to Maven context (the Maven’s
plug-ins for performing various build tasks in the build system). So be careful.
An RCP application
I have defined the following structure of an example RCP application
eclipse . ├── bundles │ ├── rcp │ │ ├── build.properties │ │ ├── META-INF │ │ ├── plugin.xml │ │ └── src │ └── pom.xml ├── releng │ ├── configuration.neon │ │ └── pom.xml │ ├── pom.xml │ ├── product │ │ ├── example.product │ │ ├── pom.xml │ ├── targetplatform │ │ ├── example.target.target │ │ └── pom.xml │ └── updatesite │ ├── category.xml │ └── pom.xml └── pom.xml
This is pretty popular layout of this kind of projects, where Tycho plugin is being used to build an Eclipse product.
You may have a look to this tutorial for that guides through process of getting a similar structure for an arbitraty Eclipse RCP project with build governed by Maven.
Once you have your
pom.xml files setup, you can just execute:
mvn clean verify
from a command line and you’ll get your product built in the
This is the world of Eclipse Tycho, and what it means is that ALL DEPENDENCIES
between various components within this complex structure are described using
OSGi bundle manifests (sitting in
META-INF directories of Eclipse’s plugins).
The entire application is made of two software components groups:
- Binary components that come from Eclipse’s
p2repository and contribute to the target platform definition (as described in
- A source code that in this case reside in the
rcpsub-directory with RCP application skeleton as well as two simple plugins:
Both Tycho Maven plugin as well as Eclipse can take such a structure and perform a valid build of the final RCP product.
The Ecilpse target platform definition can be easily extended to any other thirdparty components as long as they are packaged to form of OSGi bundles. There are already popular public repositories of such ones (like Orbit one) so chances are you might find what you already need there. Adding those components is easy, just edit target platform XML file, add repository and features you need.
But how about non-OSGi components? Now comes the challenge.
At the same time there is a vast selection of thirdparty and universal Java
components out there, managed by Maven dependency mechanism in
e.g. like this for Simple Framework:
... <dependency> <groupId>org.simpleframework</groupId> <artifactId>simple-xml</artifactId> <version>2.7.1</version> </dependency> ...
At this point I have a rather said message: there seem to be no good way to have a single-pass and purely Maven-driven build process that starts with clean sources annd correctly bridges the two worlds to deliver final artifacts (like RCP app correctly intergrated with thirdparty Maven components).
You have to use two-step approach instead, with a local Maven repository as an intermediate storage.
The process can look like this.
The first Maven build will:
- create an OSGi wrapper for a Maven component that you want to use (like the Simple Framework shown above)
- install this component in the local
By this time your local repository will have two variants of the library co-exising side-by side: the original one and the one wrapped in OSGi container.
The second, separate Maven build, will build RCP application with Maven and Tycho that includes the bundle created in the previous step into Eclipse’s target platform definition - thus making it visible to the entire Eclipse project setup and Tycho build.
The wrapper project
To achieve all that, the project with Maven pom-defined dependencies can be placed
maven-deps directory and can look simply that:
maven-deps . └── pom.xml
pom.xml file using
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>com.example.mavendeps</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>bundle</packaging> <dependencies> <dependency> <groupId>org.simpleframework</groupId> <artifactId>simple-xml</artifactId> <version>2.7.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>3.0.1</version> <extensions>true</extensions> <configuration> <instructions> <Export-Package>*</Export-Package> <Embed-Dependency>*;scope=compile|runtime;inline=false</Embed-Dependency> <Embed-StripGroup>true</Embed-StripGroup> <Embed-Transitive>true</Embed-Transitive> <Import-Package></Import-Package> </instructions> </configuration> </plugin> </plugins> </build> </project>
This special plugin will create an OSGi bundle jar with
Simple Framework jar taken from Maven repository, as well as all dependent required components (controlled by
and finally, also an embedded
MANIFEST.MF file that exports all packages
available there. With
mvn install command, this bundle will be installed in local
m2 repository and become available for any other Maven-govern build.
Altering RCP project
To ensure our RCP project gets that Maven dependency bundle, we need to edit
MANIFEST.MF file of the Eclipse
rcp project and add in the
Require-Bundle: section a
In addition, we need to enable Tycho to get that OSGi bundle from
where it is available, that is our local
m2 Maven repository. This is done by
adding an extra configuration parameter
pomDependencies like this:
... <plugin> <groupId>org.eclipse.tycho</groupId> <artifactId>target-platform-configuration</artifactId> <version>1.0.0</version> <configuration> <pomDependencies>consider</pomDependencies> <configuration> ... </plugin> ...
This will command Tycho to look for required and non-resolved bundles in a local maven repository, and when found there, add them to the target platform with all the rest.
Once those two modifications are done, classes from
package can be directly imported in RCP java files, and will be correctly
resolved at both: compile- and run-time.
Building from a command line
The combined command line build sequence for the entire solution will look like this then:
# the first building phase... cd maven-deps mvn clean install cd .. # ... and the second cd eclipse mvn clean verify
Remark: The very first
mvn clean install step is required
to be performed only once, when you start working with the checked-out sources.
When done, it will not have to be repeated over and over again,
until some extra-ordinary event happens (like invalidation of your
local Maven repository or bumping the required thirdparty library version number