How to properly override the generated EMF code?
How to properly override the generated EMF code?
EMF allows generating code from the model. By parameterizing the .genmodel file, we can generate 3 sources of code: model, edit and editor, which contain the java sources that let exploit the defined model.
In order to override the generated code, the traditional method consists in directly modifying the generated code by adding a ‘NOT’ behind the @generated tags. Additionally, the ‘mint’ plugin (in emftool) allows distinguishing the overridden methods (in red) from the added methods (in black) and the generated methods (in blue):
This method is acceptable if little code is modified, however, in the event of projects in which a lot of generated job code has to be added, then it is recommended to:
- clearly separate the generated code from manual code
- automatically generate the code when starting the build process
- take out the generated code from the configuration version system (cvs, svn, git, …) and generate it again when the delivery is made
EMF and Eclipse offer simple solutions to answer this need.
1. Separating the src-gen and the src
In order to work properly, it is important to take ‘sealing’ measures, by clearly separating the generated code from the overriddden code. To do this, parameterize the model using the following instructions:
This operation can be repeated for the edit layer and editor layer.
Then, create a src directory (folder source), dedicated to override the project:
This new source directory will contain a new EMF factory for creating the instances of the overridden classes. This factory comes from the generated factory and permits object creation with the new interfaces:
We will complete the methods of this factory as we override the classes of the generated model.
So, the implementation of the factory is simple:
Then, you just need to link the new factory to EMF by using the extension point factory_override:
This new factory will automatically be used by EMF during the object creation by a call to RentalFactory.eInstance.
Then, the modeled classes only need to be overridden with EMF. In this way, helper methods (add, remove) can be added in the interfaces … :
… and the modelized operations can be overridden in the implementation:
2. Generating the code in Eclipse during the build
If we totally separate the generated code from the overridden code, it can be useful to automate the code generation from the model.
EMF offers us an ant task (emf.Ecore2Java) that allows generating code from a genmodel. Writing the ant file is straightforward:
To execute it, it is important to use the JRE from the workspace (parameter of the build launch, in the JRE tab).
This ant file can then be integrated to the project builder by putting it in the first position in order to ensure that that the generated code is present for the compilation:
3. Generating the code during the build, outside Eclipse
In the build headless process, without having and Eclipse IDE launched, we can generate code both ways,
- using the application org.eclipse.ant.core.antRunner which calls the generation ant which can contain the following tasks
- using the application org.eclipse.emf.codegen.ecore.Generator which only does generation
In both cases, the launch environment has to be set up:
- cd {Installation directory of Eclipse Modeling}
- export LAUNCHER=plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
Generating with the antRunner :
Launch of the build with the antRunner :
java -jar $LAUNCHER -application org.eclipse.ant.core.antRunner -nosplash -buildfile {pathToAntFile}/ecore2java.xml
This method is useful if the ant file does a bit more than that of the code generation.
Generating with the ecore.Generator
This method is useful if there is only code to generate from the model:
The parameters of the application are: java -jar $LAUNCHER -application org.eclipse.emf.codegen.ecore.Generator
Usage arguments: [-projects ]
[-dynamicTemplates] [-forceOverwrite | -diff]
[-generateSchema] [-nonNLSMarkers]
[-codeFormatting { default | } ]
[-model] [-edit] [-editor] [-tests]
[-autoBuild true | false ]
genmodel-file [ target-root-directory ]
Example:
- export PROJECT_HOME={path to your project}
- java -jar $LAUNCHER -application org.eclipse.emf.codegen.ecore.Generator -projects $PROJECT_HOME -model -nosplash $PROJECT_HOME/model/rental.genmodel $PROJECT_HOME
In order to go deeper in these notions, I advise you to read this general article on the matter, presented atinfoq and written by Sven Efftinge (XText project manager)
Feel free to comment this article if you have remarks !
OPCoach
Hi Francois,
It is probably possible to extract the ‘JET’ component from the emf plugins and to have a very small java launching this generation. But launching an OSGi application is as difficult as a Java application. So why would you like to have a ‘main’ java for that ?
Then if you have some java you can easily launch it from maven.
You can write me an email or call me by phone if you want to explore these ideas.. (see the contact page of the site)
Olivier
Francois
Dear Olivier,
very could post.
I have still one question: is it possible to generate the code with emf from ecore/genmodel without any eclipse IDE?
In both case, it seems that you need to be in a eclipse environment even if you call the method by command line.
Is there a way for instance to integrate it in a maven build? totally independant from Eclipse environment?
Thanks
Francois, from France
Francois
Dear Olivier,
thanks for this synthesis.
could you also explain how to call the code generator directly from a java class with a main.
I am trying to setup a maven plugin project dedicated to generate this.
Thanks for your help