Skip to content

Building standalone Java applications

Ábel Hegedüs edited this page Jan 4, 2016 · 5 revisions

Bundling Eclipse plug-ins into Java applications using Maven is non-trivial, as one has to consider both the Maven and OSGi dependencies during the build. In general, Maven does not support loading dependencies from p2 repositories, unless some plug-in, like Tycho makes it available. However, using Tycho to build executable jars is not the best way to go, as a lot of Maven plug-ins (e.g. ones required to build the applications) does have some issues with the classpath created with Tycho.

In general, we follow the following approach:

  • During development all functionality that requires the Platform to be loaded should be separated into different classes. This way, a standalone application does not have to load everything (less dependencies, less issues)
  • Build all plug-ins with Tycho
  • Have a standalone Maven module that represents the executable application. Does not have to contain any code at all; but usually has to redefine dependencies.

Pitfalls and Know-How

  • When copying the separate dependency jars into a single directory, make sure the classpath has the same strings as the jar names. Some maven plugins may handle version informations differently, thus the required jars might not get loaded causing ClassNotFoundException. We haven't found a solution to this problem, we opted to use fat-jar instead since it doesn't have this problem. A typical case where these issues come forth:
  • Referred dependency was built with Maven/Tycho, and the resulting artifacts are put into a remote repository.
  • The maven-dependency-plugin and the maven-jar-plugin uses the snapshot qualifier differently in this case, thus the filenames of the copied artifacts and the manifest.mf entry are different.
  • To create fat-jar with maven, use the maven-shade-plugin and the maven-jar-plugin. The maven-jar-plugin only provides the main class while the maven-shade-plugin assembles the jar. Be careful with the miminizeJar option as it might remove required dependencies from the jar.
  • When building fat-jar, exclude *.RSA, *.DSA and *.SF files, otherwise security exceptions may get thrown. This can be done with maven-shade-plugin's filters.
  • The 2.9.0.rc versions of Xtext limits the upper version of Guava to 14.0.1. This can cause issues since eclipse uses 15.0. To circumvent this issue, exclude the Guava dependency from all Xtext dependencies and add it manually to the pom. See corresponding bug report for details.
  • Usually, it is a good idea to prevent the Java application to traverse the OSGi dependencies being traversed, instead provide maven dependencies for the Java application. For that, Maven has exclusion rules, but the * exclusion requires recent Maven versions (3.1+) to work correctly; and Maven 3.1 is known to throw warnings for wildcard exclusion rules.
<dependency>
	<groupId>org.eclipse.incquery</groupId>
	<artifactId>org.eclipse.incquery.querybasedfeatures.runtime</artifactId>
	<version>${incquery.version}</version>
	<exclusions>
		<exclusion>
        		<groupId>*</groupId>
		        <artifactId>*</artifactId>
		</exclusion>
	</exclusions>
</dependency>
  • debug the built application with Eclipse remote debugging: www.onkarjoshi.com/blog/224/how-to-suspend-vm-on-startup-when-remote-debugging-your-java-app/
  • register everything manually that would otherwise happen through extensions, this includes, among others:
    • resource factories for EMF
    • EPackages (XPackage.eInstance.eClass
    • URI mappings (pathmaps)
    • Xtext standalone injectors
    • UML profiles (https://www.eclipse.org/forums/index.php/t/580003/), UMLPlugin.EPackageNsURIToProfileLocationMap.put(XPackage.eNS_URI, URI.createURI("pathmap://<resourceUri>#_<fragment>"))
    • If the type mapping checker is used, make sure that the IncQuery UML standalone setup is performed, otherwise the qualified names of primitive types cannot be resolved.

Dependency management for the EMDW compiler

The standalone EMDW compiler has the following high-level dependencies (and all their transitive dependencies):

  • UML (metamodel, profiles, etc.)
  • EMF-IncQuery runtime
  • VIATRA runtime
  • Xtext runtime (for rAlf)
  • XSemantics runtime (for rAlf)

The organization of the code allows to reduce the required dependencies of the final application. In general, all classes that are referred by the main application (either directly or indirectly) are required to be available in the classpath; if some classes are not loaded, the Java application can ignore those dependencies for the execution (of course, the Tycho-based compilation requires them). For this reason, the following table collects all dependencies used by the Java application (selected by Tycho), and are categorized by them being readily available as a Maven dependency (OK), currently not available in official maven repositories (NEEDED), unnecessary (DONTCARE!) or unknown (??).

Generally, the dependencies on the Eclipse Platform itself should be minimized (in case of Xtext, it is not possible to remove it entirely; a small subset of classes are used from it); all these dependencies should be used with extra care, as any code from there could require the platform itself being running (not true in standalone Java applications).

status name
?? org.eclipse.uml2.codegen.ecore
?? org.eclipse.emf.codegen
?? org.eclipse.emf.codegen.ecore
?? org.eclipse.emf.mapping.ecore2xml
?? org.eclipse.uml2.uml.profile.standard
DONTCARE! com.ibm.icu
DONTCARE! org.eclipse.core.commands
DONTCARE! org.eclipse.core.contenttype
DONTCARE! org.eclipse.core.expressions
DONTCARE! org.eclipse.core.filesystem
DONTCARE! org.eclipse.core.filesystem.java7" fragment="true
DONTCARE! org.eclipse.core.filesystem.win32.x86_64" fragment="true
DONTCARE! org.eclipse.core.jobs
DONTCARE! org.eclipse.core.resources
DONTCARE! org.eclipse.core.resources.win32.x86_64" fragment="true
DONTCARE! org.eclipse.core.runtime
DONTCARE! org.eclipse.core.runtime.compatibility.registry" fragment="true
DONTCARE! org.eclipse.core.variables
DONTCARE! org.eclipse.debug.core
DONTCARE! org.eclipse.equinox.app
DONTCARE! org.eclipse.equinox.common
DONTCARE! org.eclipse.equinox.preferences
DONTCARE! org.eclipse.equinox.registry
DONTCARE! org.eclipse.jdt.compiler.apt" fragment="true
DONTCARE! org.eclipse.jdt.compiler.tool" fragment="true
DONTCARE! org.eclipse.jdt.core
DONTCARE! org.eclipse.jdt.debug
DONTCARE! org.eclipse.jdt.launching
DONTCARE! org.eclipse.osgi
DONTCARE! org.eclipse.osgi.compatibility.state" fragment="true
DONTCARE! org.eclipse.text
NEEDED! org.eclipse.incquery.querybasedfeatures.runtime
NEEDED! org.eclipse.incquery.uml
NEEDED! org.eclipse.incquery.validation.core
OK! com.ericsson.xtumlrt.oopl.cpp.model
OK! com.ericsson.xtumlrt.oopl.model
OK! com.google.guava
OK! com.google.inject
OK! com.google.inject.multibindings" fragment="true
OK! com.incquerylabs.emdw.cpp.app
OK! com.incquerylabs.emdw.cpp.bodyconverter
OK! com.incquerylabs.emdw.cpp.codegeneration
OK! com.incquerylabs.emdw.cpp.common
OK! com.incquerylabs.emdw.cpp.transformation
OK! com.incquerylabs.emdw.snippet.model
OK! com.incquerylabs.emdw.toolchain
OK! com.incquerylabs.emdw.umlintegration.queries
OK! com.incquerylabs.emdw.umlintegration.trace
OK! com.incquerylabs.emdw.umlintegration.transformation
OK! com.incquerylabs.emdw.valuedescriptor.model
OK! com.incquerylabs.emdw.xtuml.incquery
OK! com.incquerylabs.emdw.xtuml.incquery.validation
OK! com.incquerylabs.uml.ralf
OK! com.incquerylabs.uml.ralf.snippetcompiler
OK! it.xsemantics.runtime
OK! javax.inject
OK! javax.xml
OK! org.antlr.runtime
OK! org.apache.log4j
OK! org.eclipse.emf.common
OK! org.eclipse.emf.ecore
OK! org.eclipse.emf.ecore.xmi
OK! org.eclipse.incquery.patternlanguage
OK! org.eclipse.incquery.patternlanguage.emf
OK! org.eclipse.incquery.runtime
OK! org.eclipse.incquery.runtime.base
OK! org.eclipse.incquery.runtime.base.itc
OK! org.eclipse.incquery.runtime.evm
OK! org.eclipse.incquery.runtime.matchers
OK! org.eclipse.incquery.runtime.rete
OK! org.eclipse.incquery.runtime.rete.recipes
OK! org.eclipse.papyrusrt.xtumlrt.common.model
OK! org.eclipse.papyrusrt.xtumlrt.xtuml.model
OK! org.eclipse.uml2
OK! org.eclipse.uml2.common
OK! org.eclipse.uml2.types
OK! org.eclipse.uml2.uml
OK! org.eclipse.uml2.uml.resources
OK! org.eclipse.viatra.emf.runtime
OK! org.eclipse.xtend.lib
OK! org.eclipse.xtend.lib.macro
OK! org.eclipse.xtext
OK! org.eclipse.xtext.common.types
OK! org.eclipse.xtext.logging" fragment="true
OK! org.eclipse.xtext.util
OK! org.eclipse.xtext.xbase
OK! org.eclipse.xtext.xbase.lib
OK! org.objectweb.asm
Clone this wiki locally