2. Presentation Overview
1. Dependency Management
2. Hybrid solution for Maven/PDE
methodologies
3. Rules for synchronization between
Maven/PDE
4. Testing in a Maven Environment
5. Maven Plugins Designed for RCP applications
4. Maven Dependencies
• All dependencies at build time are managed through a
pom.xml file located at the base of each project
• pom.xml files will pull in transitive dependencies from
the direct dependencies unless otherwise specified
• Dependencies can either be in-house projects or 3rd
party projects
• Sample Dependency Clip:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
5. PDE (Plug-in Development
Environment) Dependencies
• All dependencies at compile and runtime are managed through
MANIFEST.MF
• For a plugin to add another plugin to it’s build-path (compile time)
and classpath or classloader (runtime) each plugin must contain
valid OSGI manifest metadata:
Bundle-Symbolic-name
Bundle-Version
Required-Bundles
Fragment-Host
Eclipse-BuddyPolicy
Eclipse-RegisterBuddy
etc…
• For this reason, every project needed by an RCP application, has to
remain in an OSGi state, regardless of our desire to manage
everything entirely through the use of pom.xml files
6. Hybrid solution (Maven/PDE
methodologies) Overview
1. A snapshot of today’s dependencies
2. The problem of managing dependencies
through 2 different mechanisms
simultaneously
3. A Hybrid solution
4. A snapshot of today’s dependencies with our
solution
8. Organization Problem
• In the previous example, legitimate RCP Plugin projects
relied on many different in-house projects (containing
common code between server and client) at build-time and
runtime that were never intended to be RCP plugins, this
meant every java-project required OSGi metadata such as a
Manifest.MF file for dependency management
• To continue using these (common code) non-RCP projects
directly in an OSGi container we would have to settle on
managing pom.xml files and MANIFEST.MF files for every
non-RCP project
• This would (in a sense) mean that every change made to
one of these 2 dependency management files would have
to be scrutinized and applied (in a similar but not
necessarily identical manner) to the other file
9. Side by Side example: Trying to keep 2 different
dependency mechanisms in sync
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.example.a
Bundle-Version: 6.6.0.qualifier
Bundle-Vendor: Nice
Require-Bundle: com.example.b;bundle version="1.0.0”,
com.example.c;bundle-version=“2.0.0”
Export-Package: com.new.example.a,
com.example.b,
com.example.c
Build-Id: build.id
<groupId>my.example</groupId>
<artifactId>com.example.a</artifactId>
<version>6.6.0-SNAPSHOT</version>
<dependency>
<groupId>my.example</groupId>
<artifactId>com.example.b</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>my.example</groupId>
<artifactId>com.example.c</artifactId>
<version>2.0.0</version>
</dependency>
10. Solution
• Non-RCP projects are not fundamentally
different than 3rdparty jars such as Spring, or
log4j which are not RCP plugins
• The approach of using an OSGi container fit
the mold in that it can be the delivery system
for all of our non-RCP dependencies
• This led to the concept of the Bridge project
11. The Bridge
• A collection of jars, in 1 single “bundle” that can be used at compile and
runtime by sharing it’s classpath with any bundle that requires it
• Requires a valid OSGi MANIFEST.MF, bundle-name, bundle-version, etc…
• All jars intended to be shared are required to be listed on the bundle-
classpath in the MANIFEST.MF, and all shared packages coming from those
jars must be listed in the Export-Package section
• It is created using the Apache-Maven-Bundle plugin
All jars placed in the Bridge come from Maven dependencies managed by a
single pom.xml
The Manifest.MF file that defines this OSGi container is configured through
the pom file, for our example it automatically outputs out all of the jars on the
bundle-classpath, ignores transitive maven dependencies, and lists out all
packages to be exported to the classpath. It is a great solution that now
requires only minimal configuration going forward
14. BRIDGE PLUGIN
View of dependencies for RCP with the
Bridge
Rcp-
Plugin-C
Rcp-
Plugin-D
Common-
Code-Jar-A
Common-
Code-Jar-B
Common-
Code-Jar-C
Rcp-
Plugin-B
Common-
Code-Jar-D
Rcp-
Plugin-A
15. Guidelines for project synchronization
• Managing names and versions is crucial to
keeping everything in sync at build time
16. Staying in sync
• Managing an RCP application through maven means that we must keep certain artifacts in sync.
OSGi (MANIFEST.MF, feature.xml, category.xml, site.xml)
Maven (pom.xml)
• Each OSGi artifact is identified by a bundle name and must reflect each Maven artifact name
OSGi - Bundle-Name=workstation.acd
MAVEN - <artifactId>workstation.acd</artifactId>
• Moreover, it is important to keep the versions in sync between OSGi and Maven
OSGi - Bundle-Version=6.6.0.qualifier
Maven - <version>6.6.0-SNAPSHOT</version>
(Maven’s convention for snapshot artifacts for development is to have the word “SNAPSHOT”; for OSGi that
convention is to have “.qualifier”)
• In order to ensure everything is kept in sync, it is not recommended to change any of these version
numbers either for OSGi or Maven by hand, but instead to allow tycho to do this work for us. The
maven command: “mvn org.eclipse.tycho:tycho-versions-plugin:set-version -DnewVersion=“6.6.0-
SNAPSHOT”
The above command will result in all pom.xml file versions for the project to update to “6.6.0-SNAPSHOT”
while simultaneously updating all OSGi versions to “6.6.0.qualifier”, thus keeping everything perfectly in
sync between releases.
18. Previous Test project setup
• Previous approach used a gargantuan plugin to hold all unit tests
• Our RCP product consisted of roughly 130 plugins each consisting of
many packages that could be tested
• The gargantuan plugin was setup with package names that mirrored
the multitude of package names of any of the 130 plugins for which
we wanted to test
• Running this enormous test plugin inside of Eclipse resulted in a
single JVM loading everything for the test plugin into a single
classloader; thus giving us the ability to test any protected and
default methods that existed in our production code from our test
plugin (provided that our Test-Class lived in a package that mirrored
the Class it intended to test)
• Previously our tests were not executed as part of our build, instead
tests were only run by development within Eclipse
19. View of Single Test Plugin
Plugin
1
JVM
Plugin
2
Plugin
3
Plugin
4
20. Alternative Approach
• An alternative to a single test project is multiple test projects
• Each new “test” project is created as a plugin fragment to the
actual plugin that it is intended to test
• Using Bundle Fragments we can appropriately mirror the package
structure to put test classes into the same package when loading
tests into an OSGi container
• Each new test fragment will of course require a Manifest file with a
new Manifest header “Fragment-Host=“XX” which specifies a
Bundle which this fragment can attach to at runtime
• This becomes very useful since the Tycho Surefire plugin is now the
tool of choice for executing unit tests within our Maven Build
Process
• The Tycho Surefire plugin will create an OSGi process and install the
Test plugin as a bundle alongside all other required Bundles listed in
the test plugin’s Manifest.MF
22. Pros and cons of a single test plugin
• Pros
– single point of failure in a build system
– Single test means single OSGi process for testing within a Maven
build (very efficient)
• Cons
– A monolithic plugin can only reliably test all protected and
default accessor methods outside of an OSGi container
environment (other than testing Public methods, this approach
can’t provide adequate test coverage within a Maven style
Build)
– Running such a large test plugin with so many dependencies
requires an excessive amount of memory to start up
23. Pros and Cons of Test Fragments
• Pros
– We have the ability to test all but private methods throughout
an entire RCP application using a Maven build
– Tests are split out and don’t all have to be run at once when
wanting to run just the set of tests for a particular RCP plugin
• Cons
– Number of RCP projects in the build reactor essentially doubles
(for each RCP bundle we now have a fragment bundle as well)
– Each test fragment will create an OSGi process to run it’s own
set of tests, that means many OSGi processes created and
destroyed throughout an entire build, this can cause significant
build slowness
24. Tycho: The Maven plugin for RCP
1. What is Tycho and how is it used?
2. Setting up Packaging Types for RCP Resources
3. Materializing RCP applications
25. What is Tycho
• Tycho is THE tool that glues Maven back to a
system that is still tightly coupled to OSGi
metadata
• Tycho is a set of maven plugins for:
initial pom creation - tycho-pomgenerator
artifact versioning - tycho-versions
Compilation - tycho-compiler
Packaging - tycho-packaging
Eclipse Process Creation - tycho-eclipserun
Testing - tycho-surefire
26. Steps to setting up Tycho
1. To begin we need a pom file for each RCP project
– From the root of the overall project we need to run this command: “mvn org.eclipse.tycho:tycho-pomgenerator-
plugin:generate-poms -DgroupId="com.example"”
2. Need to verify that the plugins have the correct packaging type:
eclipse-plugin
eclipse-feature
eclipse-test
eclipse-repository
3. Need to verify artifact names from the pom.xml files match the Bundle-Symbolic-Name from each Manifest.MF
file
4. Need to verify the pom versions match the Bundle-Version numbers from the Manifest.MF file
5. Must add an Eclipse repository location since we will require Eclipse framework jars for the RCP build:
<repositories>
<repository>
<id>eclipse-indigo</id>
<url>http://nexus.dfw.nicelabs.com/content/repositories/eclipse-indigo/</url>
<layout>p2</layout>
</repository>
</repositories>
6. It is also recommended to configure the parent pom file for the overall project to specify the platform for the
desired product
Operating System
Architecture
27. Target Platform Configuration
• The Target Platform Configuration gives us a very
simple mechanism to specifying the flavor that we will
generate for our product
• The Target Platform is also necessary for determining
the OS specific platform jars to use when executing our
unit tests that require a Windowing System
• We can specify a single platform or multiple platforms
for which we can generate executables
Windows (32-bit, 64-bit)
Linux (32-bit, 64-bit)
Mac (32-bit, 64-bit)
28. Target Platform Configuration for
Windows 64 Bit
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>0.22.0</version>
<configuration>
<environments>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86_64</arch>
</environment>
</environments>
<pomDependencies>consider</pomDependencies>
</configuration>
</plugin>
29. Target Platform Configuration for
Windows 32-bit and Mac 64-bit
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<environments>
<!—WINDOWS-->
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86</arch>
</environment>
<!—MAC-->
<environment>
<os>mac</os>
<ws>cocoa</ws>
<arch>x86_64</arch>
</environment>
</environments>
<pomDependencies>consider</pomDependencies>
</configuration>
</plugin>
----- Meeting Notes (4/27/15 15:04) -----
Quickly going over the mechanics of managing dependencies through Maven and through PDE
How to combine non-PDE type artifacts with a PDE build
Gotcha's that can cause the build to get out of sync
What we learned about setting up testing for a Maven Build
Putting Tycho in the drivers seat