A few days ago I finished my bachelor thesis with the title Integrating Xtext in an existing Software development process. I developed a domain specific language with Xtext and some extensions for easily adding new generators as new Eclipse plug-ins.

After finishing the thesis I added a Maven Tycho based build configuration. The build configuration can be easily deployed to TeamCity, Hudson or any other build server of your choice. I assume that you have already developed an Xtext based DSL and you know a little bit about OSGi and Maven.

The complete project source code can be found at https://github.com/schakko/xtext-plugin-with-maven-tycho

Preparations

First of all you should think about a sensible directory structure. I use the following organization

  • /plugins contains your Eclipse based plug-ins
  • /features contains the Eclipse features for bundling your plug-ins
  • /releng is used for the release engineering process and holds the project for the p2 update site
  • /pom.xml is the master POM for your complete project.

Directory structure of your DSL project

Set up the master pom.xml

Every pom.xml inside the subdirectories inherits from the master pom.xml. The configuration defines all modules of your project, sets the needed plug-in repositories and plug-ins. The most interesting part of the lifecycle configuration is, that the xtend-maven-plugin is not executed in generate-sources but generate-resources. This is needed as the MWE2 workflow of your DSL project has to be executed first. If you have both plug-ins inside the generate-sources phase the xtend-maven-plugin will be called first, resulting in a ClassNotFoundException as the DSL infrastructure is not generated yet. So the compilation of Xtend is moved to generate-resources which is executed after generate-sources phase. Another solution would be moving the xtend-maven-plugin to every child pom but this means duplicate configuration code.

Set up your DSL project

pom.xml

The pom.xml contains the plug-in for executing the MWE2 workflow. Notice that your <workflowDescriptor> must begin with src/ or you will receive the message Cannot create a resource for…. All the other stuff is straight forward. The packaging type eclipse-plugin is introduced by the tycho-maven-plugin.

build.properties

The file build.properties contains the source and binary folders. This is important, as tycho-maven-plugin uses this file as reference for compiling and packaging the sources. The xtend-gen directory must be added.

META-INF/MANIFEST.MF

It is important, that your Bundle-Version must end with the suffix .qualifier, e.g. 1.0.0.qualifier. The string is automatically replaced with the build date.

Set up your test project

Copy generated files

At first the two automatic generated files from src-gen (*InjectorProvider.java and *UiInjectorProvider.java) must be copied to the src folder if you want use the xtend-maven-plugin. The Xtend Maven plug-in does not allow (at least in version 2.2.1) any additional source pathes so that none class in src-gen can be found by xtend-maven-plugin. Remove the src-gen directory from your Eclipse classpath too.

pom.xml

The pom.xml for the test project uses a different Xtend version because I ran into heavy problems with the xtend-maven-plugin using the ValidatorHelper. Referencing the ValidatorHelper class results in a GenericSignatureFormatError. Sven Efftinge mentioned yesterday that the bug should be fixed in the latest snapshot.

The packaging type must be eclipse-test-plugin.

pom.xml of your test project

build.properties

Include the xtend-gen directory and make sure that the src-gen directory is not included because of the xtend-maven-plugin problem.

META-INF/MANIFEST.MF

The MANIFEST.MF uses the Import-Package statement for importing Mockito. See the next section how to set up this dependency.

Creating a dependency project

I used Mockito as mocking framework inside my tests. Adding this dependency is a little bit tricky:

  • Adding the mockito-all-1.9.5.jar to your Eclipse build path does not work. Maven does not know anything about your .classpath settings.
  • Adding a dependency to the pom.xml means that the compilation with Maven would work but not the installation on the client because there is no OSGi package for Mockito available.
  • Converting the mockito package to an OSGi package is not ideal. Every dependeny must be repackaged.

A much better solution is including the required JAR files inside an own OSGi package. I took the idea from the atlassian-connector project.

New Plug-in project

Create a new Eclipse plug-in project, create a folder lib and copy the  mockito-all-1.9.5.jar inside.

pom.xml

Nothing new, just use eclipse-plugin as packaging type.

build.properties

Your build.properties must include the lib directory.

META-INF/MANIFEST.MF

Here comes the interesting part. We use Bundle-ClassPath to define the additional path to the mockito JAR file. Every package inside this JAR file is re-exported via Export-Package.

Include the mockito framework in an OSGi bundle

Set up your UI project

pom.xml

The pom.xml must use the packaging type eclipse-plugin.

build.properties

I added the schema and icons directory and plugin.xml. This depends on your needs.

META-INF/MANIFEST.MF

Nothing new.

Set up your feature projects

Features are bundles which consist of different plug-ins. Lars Vogel made a good tutorial which you can use for more information

We need to create two features:

  • A runtime/core feature with your DSL and UI plug-in
  • A test feature with the test and dependencies plug-in

pom.xml

Create a pom.xml and use the packaging type eclipse-feature.

Configure the core feature

Set up your update site

The update site contains every feature the user can install. Lars wrote a tutorial about this but my needs were different. I wanted to deploy the content on a local webserver with a simple copy command.

To do so, generate a new update site project inside your releng directory and add a category definition (in Eclipse: Plug-in Development > Category Definition).

category.xml

The category.xml contains the features which are available through he update site. First of all, add a new category named “Xtext” and assign both of your previously created features to this category.

pom.xml

The packaging must be eclipse-repository. I use the copy-maven-plugin for copying the update site to the local webserver.

Configure the update site for your features

Run it local

With all these settings the project can be build inside Eclipse without m2e plug-in and on the command line. Go to the command line and execute mvn install:

Successful build on command line

Move it to your build server

Create  a new configuration in your TeamCity instance and add a Maven buildstep. I pass the -DupdateSite.target parameter for specifying the destination directory of the update site.

Configure the Maven build step in your TeamCity instance

Install your plug-ins

Enter the path to your update site and you will see your installable Xtext DSL

Install your Xtext DSL in Eclipse

I am asking you for a donation.

You liked the content or this article has helped and reduced the amount of time you have struggled with this issue? Please donate a few bucks so I can keep going with solving challenges.


3 Comments

Michael Vorburger · March 4, 2013 at 11:49 pm

Hallo, we made a template for something very similar to what you describe on https://github.com/vorburger/xtext-maven-examples – may be you’re interesting in having a look to compare notes.

admin · March 7, 2013 at 11:08 am

Good work, Michael. Our approaches seem to be very similar 😉

Michael · December 1, 2013 at 9:13 am

Hi,

I created a Maven archetype that creates the appropriate project structure: https://github.com/fuinorg/emt-xtext-archetype

Cheers,
Michael

Leave a Reply