Generating Java code from EMF models automatically

EMF provides a nice code generation facility for generating Java class hierarchy from ecore models. There is support for hand-made modifications to the generated code, or a large selection of generation parameters are available through a generator model.

However, we had a different need together with the VIATRA2 project: we explicitly forbid in our internal policy modifications to the generated Java code in order to avoid non-reusable models, and as this way the generated code does not contain any extra information to the generator model, we do not want to store the Java classes in our Subversion repository.

Another minor obstacle was that the code generation does not happen automatically (e.g. as in the LPG editor of the IMP project) – so simply not committing the generated code to the repository would mean a manual invocation of the generator that is inconvenient.

Luckily, the code generator is available using specific ANT tasks, allowing to write a build file that describes how to generate the required Java code, reusing the existing build model if necessary:

<emf.Ecore2Java
 genModel="org.eclipse.viatra2.gtasm.model/model/gtasmmodel_updated.genmodel"
 model="org.eclipse.viatra2.gtasm.model/model/gtasmmodel.ecore"
 generatemodelproject="true"
 generateeditorproject="true"
 generateeditproject="true"
 reconcilegenmodel="reload" >

Some interesting points:

  • As the selected Ant task is provided by an OSGi plug-in, it is important to set the Runtime JRE to the same one as used by the workspace, otherwise the called task will not be found.
  • As the genmodel generator is not available as an Ant task, the ecore2Java task was used. In this case it is important to use the reconcilegenmodel attribute to avoid the unnecessary override of the genmodel
  • Regardless of the value of the generate*project attributes if the *project were not given as sub-tags, the corresponding code was not generated. This seems like a bug for me, as this duplicates information already present in the genmodel, but I am not sure.
  • The code generator does not set the generated files Derived attribute, thus it is not excluded from the svn repository. Unfortunately, it is not possible without writing custom tasks, as there is no such command (yet) in Eclipse (but hopefully the patch gets committed in Indigo).

This ant task mimics the GUI-based code generators functionality, thus fulfilling our needs, except two things: it does not exclude generated code from the repository, and does not run automatically.

The repository exclusion is resolved using a hack: the src folders are listed in all generated projects in the svn:ignore variable – thus manually disallowing their sharing. This approach works well, because if no code is generated, the src folder might be missing, that is marked with a very explicit error message (as it is still referenced in the project properties), but if the task is executed, the folder is created as well (and the source folder reference will be working).

For the automatic building Eclipse provides a neat way: External tools (e.g. Ant scripts, or shell scripts, etc.) can be added as project builders. A Run configuration has to be created for the selected task, that can be added to the project. This means, our script is executed each time the selected project changes

The Ant task has been set as a custom builder
https://i1.wp.com/cubussapiens.hu/wp-content/uploads/2010/12/Screen-shot-2010-12-12-at-23.11.33.png?w=790 790w" sizes="(max-width: 300px) 85vw, 300px" /> Builders page in the Project properties

Finally, some other modifications were made to the task in order to provide a more standard build: first, as not the entire project is generated at every invocation of the script (the projects could not be deleted, because the generator does not support setting the version number of the generated edit and editor projects), if all project stubs are downloaded from the repository, the build order might not be adequate. To overcome this, a manual build is executed for all projects at the end.

A second modification is a clean task, that removes all source folders, in order to provide a “clean”, out-of-the-box experience for a regeneration. This task can also be registered at the builder properties.

The full, modified script looks as following (using Gist from Github):

Update: the eclipse.build tasks are not available in Eclipse, as mentioned by a comment. They are provided by the Buckminster tool, and are not required for the EMF code generation, so it is safe to remove them. However, in this case the refreshing and building of the projects have to be managed in another way (e.g. registering the Ant script as an External builder for the projects).

This simple script helps in a lot of cases – and because the ecore models does not change very often, its performance is not really an issue (we have quite a large ecore model, so the generator runs about 30-40 seconds). My main issues are the following:

  • I don’t like to reproduce information from the genmodel in the build script. I am not entirely sure which information is read from the genmodel and which is inferred from the parameters, making the solution a bit volatile.
  • The missing derived flag command. It would be quite a nice touch if the code would take care of it.

Alltogether, if you like it, feel free to use it (licensed under EPL). I also would be glad if somebody could give me a hint about how to enhance the script – this is only my second Ant build script, so I don’t know the language very well. 🙂

Author: Zoltán Ujhelyi

I am an Eclipse Technology Expert at IncQuery Labs Ltd. and a regular contributor of open-source projects, most importantly the VIATRA project at eclipse.org. Furthermore, I am in the process of finishing my PhD in computer science at the Budapest University of Technology and Economics focusing on analysis techniques for model queries and transformations.

15 thoughts on “Generating Java code from EMF models automatically”

  1. Where can I find the eclipse.build command?

    I get the following error when trying to use this in my skript:

    x:\xxx\xxx.xxx.xxx\build.xml:xx: Problem: failed to create task or type eclipse.build

  2. @?: The eclipse.build calls are provided by the Eclipse framework – sorry, but not really sure which plug-in was responsible.

    I checked my live code that also does not have this line. The corresponding Eclipse help states that an incremental build command is available (http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/guide/ant_eclipse_tasks.htm); maybe that can be used or the eclipse.build steps could be removed at all.

    When I have time, I will update the Gist; thanks for pointing out the error.

  3. @?: Thank you again for pointing out the errors of my script. I updated the script with more detailed comments about the eclipse.build steps, and state that they are provided by Buckminster.

    These steps are not required, so if you manage to refresh/build your projects otherwise, feel free to remove them.

  4. Hello friends

    As I can achieve automatically generate the following, taking the model .Ecore

    I want to generate automatically:

    1) .genmodel
    2) plugin edit
    3) plugin editor

    just having the .ecore

    many thanks friends, and Merry Christmas

  5. @julian: If I recall correctly, the approach detailed above creates the genmodel file if it is missing. I don’t remember it exactly, as it was quite a time ago I used this.

    If I misunderstood your question, then feel free to ask again for clarification.

  6. I want to do is generate the .genmodel automatically without having to open the wizard, create it from the file .ecore. and generate all the EMF.

    I do not know if I understand

    thanks

  7. @julian: Ok, I hope I understand now your question, and try to outline the possible answers:

    1. If you want to use the graphical user interface, then it is not possible to do what you want: EMF expects you to generate the .genmodel file using the corresponding wizard.
    1. a. As an exception, the newer syntax called Xcore gets away without genmodels. If you are working with a brand new model, this might be an alternative. In this case you do not have to worry about manually executing the code generator, as it would be executed after every change of the model.

    2. If you want to write an Eclipse plug-in to execute everything, look at the importers of EMF. For me it is not the most common name to look for when looking at this issue.

    3. If you have an Eclipse installation, you can use that to execute the entire generation process from the command line something along the following two commands:
    3.1 Generate genmodel: eclipse -noSplash -data C:\temp\emf-ws -application org.eclipse.emf.importer.ecore.Ecore2GenModel metamodel.ecore
    3.2 Generate code eclipse -noSplash -data C:\temp\emf-ws
    -application org.eclipse.emf.codegen.ecore.Generator metamodel.genmodel

    4. If you are using Ant, simply follow the description of this blog post.

    I hope, this helps you a bit where to start.
    Cheers!

  8. hello friends,

    I’m trying to run an ant task that contains a target of emf.Ecore2Java, I try to run it from java but I get the following error:

    Problem: failed to create task or type emf.Ecore2Java

    pictures in this more specific

  9. @julian Vela: Hi,

    basically, you need to have the EMF generator tasks in your Ant classpath. One way to achieve this is to have EMF installed in an Eclipse instance, and execute Ant from within this Eclipse instance. This was what I was doing for generating EMF instances.

  10. @julian Vela:
    Hello,

    generally, for an Ant task to work it has to be on the classpath used by the Ant executor. One way to achieve this was to execute the Ant script from Eclipse, using the Run/External tools… option, while putting the build script file inside the plug-in project where the generated code will be placed.

    This way it found the script files. If you want to execute your scripts without Eclipse, you have to set up the classpath. This was done for me sometimes in the past using Buckminster (as mentioned in the post). In our current builds we are using Maven; there it is also possible to add additional sources to the classpath (configured here http://git.eclipse.org/c/incquery/org.eclipse.incquery.git/tree/plugins/org.eclipse.incquery.xcore.model/pom.xml).

    If you want to do it manually, look up the classpath configuration parameters of Ant, I am lucky enough not knowing them by heart. 🙂

  11. hello Pity to disturb tnato . already included in the ant classpath , but the error persists :

    Exception: _C : \ Users \ Admin \ Documents \ Young Investigator JAVS \ Tools \ Eclipse versions \ SINFOCI MDE \ Workspace_CHICO_CIAT \ CHICO_CIAT \ chico.plugin \ build \ build.xml : 35 : The following error occurred while executing this line :
    C: \ Users \ Admin \ Documents \ Young Investigator JAVS \ Tools \ Eclipse versions \ SINFOCI MDE \ Workspace_CHICO_CIAT \ CHICO_CIAT \ chico.plugin \ build \ build.xml : 27 : Problem : failed to create task or type emf.Ecore2Java

    when I run it from java like this:

    BuildFile File = new File (” build / build.xml “);
    Project p = new Project ( ) ;
    p.setUserProperty ( ” ant.file ” buildFile.getAbsolutePath ());
    p.init ( ) ;
    ProjectHelper ProjectHelper.getProjectHelper helper = ();
    p.addReference ( ” ant.projectHelper ” helper ) ;
    helper.parse (p, BuildFile );
    p.executeTarget ( p.getDefaultTarget ());

  12. @julian Vela:
    Hi,

    I am sorry, but I never have executed Ant from a Java program directly. However, if you are not depending on Ant (for any other reason), I would try to execute the generator directly from the Java program.

    To learn how to execute this, try to open either the EcoreImporterApplication and/or the EcoreImporter classes from the org.eclipse.emf.importer.ecore plug-in (git repository browsing here: http://git.eclipse.org/c/emf/org.eclipse.emf.git/tree/plugins/org.eclipse.emf.importer.ecore). I guess, this may integrate in a more manageable way (but have never tried it before).

    Cheers,
    Zoltán

Leave a Reply