• Guide Tutorials Examples Services App notes Links FAQ Forum
  • Guide
    Tutorials
    Example Projects
    Documentation
    Service Catalog
    OSGi Specifications
    App Notes
    Where to Find Stuff
    Videos
    Known Issues
    Frequently Asked Questions
  • This website and its associated repositories, are deprecated and no longer supported by the OSGi Alliance. Please visit https://enroute.osgi.org for the latest supported version of OSGi enRoute.

    This enRoute v2 archive site is kept for those who do not intend to use the latest version of OSGi enRoute. If you are new to OSGi enRoute, then please start with the latest OSGi enRoute.

    Getting Xcore to work in Bndtools

    This example project shows how Xcore can work within Bndtools. It’s divided into two sub-goals:

    • Get Xcore to work via the Eclipse UI with Bndtools
    • Get Xcore to work via Bnd Gradle Plugin on the command line

    Getting Xcore to Work via Eclipse UI

    High level:

    • Create and configure an Xcore project
    • Add Xcore-related repositories and dependencies using Bndtools semantics
    • Customize for Equinox runtime
    • Compile and test the Xcore model

    Create and Configure Xcore Project

    (Note: the example uses the project name and package name of com.example.bndtools.xcore.model.)

    • Create a Bnd workspace based on the GitHub “bndtools/workspace” template
    • Create a new project: “Bnd OSGi Project” → “OSGi Standard Templates” → “Component Development”. Consider this the “Xcore project”
    • Via context menu on above project, select “Configure” → “Convert to Xtext Project”
    • Via context menu root project (which contains “cnf”), select “Configure” → “Convert to Gradle Project”
    • Create the following basic Xcore model in the Xcore project, saved in the “model/Model.xcore” file. (Note: the “model” directory is not a source directory.)
        @GenModel(
          bundleManifest="false",
          updateClasspath="false",
          modelDirectory="/com.example.bndtools.xcore.model/src",
          oSGiCompatible="true",
          forceOverwrite="true"
        )
        package com.example.bndtools.xcore.model
        
        class One
        {
          refers Two two opposite one 
        }
        
        class Two
        {
          refers One one opposite two
        }
    

    Add repositories and dependencies using bndtools semantics

    • Resolve the Xcore dependencies (i.e. @GenModel annotation) by adding the following repositories to build.bnd cnf project:
        -plugin.5.Xtext: \
          aQute.bnd.repository.p2.provider.P2Repository; \
            url = http://download.eclipse.org/modeling/tmf/xtext/updates/releases/2.10.0/; \
            name = Xtext
        
        -plugin.6.EmfCore: \
          aQute.bnd.repository.p2.provider.P2Repository; \
            url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/core/S201501230452/; \
            name = EmfCore
        
        -plugin.7.EmfBase: \
          aQute.bnd.repository.p2.provider.P2Repository; \
            url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/base/S201501230348/; \
            name = EmfBase
        
        -plugin.8.EmfXcore: \
          aQute.bnd.repository.p2.provider.P2Repository; \
            url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/xcore/R201502020452/; \
            name = EmfXcore
        
        # Downloads everything, will be slow
        # Currently only needed for the one JDT dependency 
        -plugin.9.Neon: \
          aQute.bnd.repository.p2.provider.P2Repository; \
            url = http://download.eclipse.org/eclipse/updates/4.6/R-4.6.1-201609071200/; \
            name = Neon
    
    • Add the following build dependencies to the Xcore project’s bnd.bnd:
      • org.eclipse.emf.ecore
      • org.eclipse.xtext.xbase.lib
      • org.eclipse.emf.ecore.xcore.lib
      • org.eclipse.emf.common
      • org.eclipse.xtext.ecore
      • org.eclipse.emf.codegen.ecore.xtext
      • org.eclipse.emf.ecore.xcore
      • org.eclipse.xtext
      • org.eclipse.xtext.xbase
      • org.eclipse.emf.codegen.ecore
      • org.eclipse.jdt.core

    Customize For Equinox Runtime

    • Modify the Xcore bnd.bnd to include the following:
        # plugin.xml and its properties are needed
        # To generate these, edit and save Xcore model
        # Model not needed for runtime
        Include-Resource: plugin.xml, plugin.properties, OSGI-OPT/model=model
        
        # The bsn needs to specify the singleton attribute
        Bundle-SymbolicName: ${p};singleton:=true
    
    • Export all of the auto-generated packages:
        # Mirrors what the auto-generated plugin.xml declares
        Export-Package: \
          com.example.bndtools.xcore.model,\
          com.example.bndtools.xcore.model.impl,\
          com.example.bndtools.xcore.model.util
    

    Compile and test the Xcore model

    After saving bnd.bnd, which triggers a build, Xcore should auto-generate the following source and related files:

    • src/com.example.bndtools.xcore.model.* Java files
    • build.properties
    • plugin.properties
    • plugin.xml

    Note: Xcore shouldn’t add any additional libraries to the Xcore project build path.

    Unit Test

    Refer to the Testing the Provider with %28Standard%29 JUnit section for background on unit testing in Bndtools.

    • In the Xcore project, add the following to test/com.example.bndtools.xcore.model/ExampleTest.java:
        @Test
        public void testXcore() {
          One one = ModelFactory.eINSTANCE.createOne();
          Two two = ModelFactory.eINSTANCE.createTwo();
          one.setTwo(two);
          assertEquals(one, two.getOne());
        }
    

    Running the above as a standard JUnit test should successfully execute.

    Integration Test

    Refer to the Testing in OSGi section for background on integration testing in bndtools.

    By default, Xcore uses the package name of the model as the EMF namespace URI (nsURI). Xcore registers this nsURI using the Equinox Extension Registry, declared in the Xcore project’s plugin.xml file. The nsURI is registered in the EMF Package Registry.

    The integration test below queries the EMF Package Registry for the model’s nsURI. If found, it implies the bundle was able to register its extension point to the Equinox Extension Registry and register the model’s nsURI to the EMF Package Registry.

    • Create a new project: “Bnd OSGi Project” → “OSGi Standard Templates” → “Integration Testing”. Consider this the ITest project.
    • Add the following to the Build Path in the ITest bnd.bnd:
      • org.eclipse.emf.ecore
      • org.eclipse.emf.common
      • com.example.bndtools.xcore.model
    • Modify the following in the bnd.bnd Run configuration:
      • In the “Core Runtime” section:
        • “OSGi Framework”: org.eclipse.osgi. Do not choose Felix since Equinox-specific extensions are used.
        • Execution Env: JavaSE-1.8 or similar
      • In the “Run Requirements”:
        • The model and test bundles
        • org.eclipse.emf.ecore
        • org.eclipse.emf.common
        • org.eclipse.xtext.xbase.lib
        • org.eclipse.emf.ecore.xcore.lib
        • org.eclipse.core.resources
      • Click on the “Resolve” button and save
    • Add the following test to /com.example.bndtools.xcore.test/src/com/example/bndtools/xcore/test/ExampleIntegrationTest.java:
        @Test
        public void shouldBeRegistered() {
          String nsURI = "com.example.bndtools.xcore.model";
          EPackage.Registry registry = EPackage.Registry.INSTANCE;
          EPackage ePackage = registry.getEPackage(nsURI);
          assertNotNull(ePackage);
        }
    
    • Via the context menu on the ITest project, select “Run As” → “Bnd OSGi Test Launcher (JUnit)”.

    This should successfully execute.

    Get Xcore to work via Gradle on the command line

    • Create “build.gradle”
    • Build jar
    • Add plugin as dependency

    Create “build.gradle”

    Per the Bnd Gradle Plugin README:

    If special Gradle build behavior is needed, beyond changes to the project’s bnd.bnd file, then you should place a build.gradle file in the root of the project and place your customizations in there.

    • Create a new build.gradle file in the Xcore project with the following:
    plugins {
        id 'org.xtext.builder' version '1.0.12'
    }
    
    // Needed for plugin repository
    repositories {
        jcenter()
    }
    
    ext.xtextVersion = "2.10.0"
    
    // Non-plugin dependencies managed via bnd.bnd
    dependencies {
        compile "org.eclipse.xtext:org.eclipse.xtext:${xtextVersion}"
        compile "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}"
        compile 'org.eclipse.emf:org.eclipse.emf.ecore.xcore.lib:+'
    
        xtextLanguages 'org.eclipse.emf:org.eclipse.emf.ecore.xcore:+'
        xtextLanguages 'org.eclipse.emf:org.eclipse.emf.ecore.xcore.lib:+'
        xtextLanguages 'org.eclipse.emf:org.eclipse.emf.codegen.ecore:+'
        xtextLanguages 'org.eclipse.emf:org.eclipse.emf.codegen.ecore.xtext:+'
        xtextLanguages "org.eclipse.xtext:org.eclipse.xtext.ecore:${xtextVersion}"
        xtextLanguages 'org.eclipse.jdt:org.eclipse.jdt.core:+'
    }
    
    xtext {
        version = "${xtextVersion}"
        languages {
            ecore {
                setup = 'org.eclipse.xtext.ecore.EcoreSupport'
            }
            codegen {
                setup = 'org.eclipse.emf.codegen.ecore.xtext.GenModelSupport'
            }
            xcore {
                setup = 'org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup'
                generator.outlet.producesJava = true
            }
        }
        sourceSets {
            main {
                srcDir 'model'
                // Move the generated Xcore output to the src directory
                output {
                    dir(xtext.languages.xcore.generator.outlet, 'src')
                }
            }
        }
    }
    

    Notes on the above:

    • The added repository section is needed for plugin dependency resolution
    • The compile and xtextLanguages dependencies are managed via the Xcore project’s bnd.bnd file
    • The srcDir 'model' directive tells Xtext to use the model directory as its source directory
    • The generated source output is moved to Bndtools’s default source directory

    Build jar

    The below uses Buildship to visually control Gradle.

    • Install Buildship
    • Open “Gradle Executions” and “Gradle Tasks” views
    • In “Gradle Tasks”, select the Xcore project, “build” folder, “jar” task, execute it:
    :com.example.bndtools.xcore.model:generateXtext
    :com.example.bndtools.xcore.model:compileJava
    :com.example.bndtools.xcore.model:processResources UP-TO-DATE
    :com.example.bndtools.xcore.model:classes
    :com.example.bndtools.xcore.model:jar
    
    BUILD SUCCESSFUL
    
    Total time: 14.425 secs
    

    You should see something similar to the above.

    • Copyright © 2021 OSGi™ Alliance.