During the last days I was working with Eclipse Modeling Framework (EMF) within the context of an R&D project. As our architecture became distributed, I had to use EMF outside an Eclipse-based application. Therefore, this article deals with us of EMF in a standalone Java application (standalone meaning here not running in en Eclipse framework like server-side components, Swing applications, etc). I will not present here how to use EMF to create models and generate the respective Java code (you may find a good tutorial on that at
http://www.vogella.de/articles/EclipseEMF/article.html), but I will focus on using the generated code in a standalone Java application.
Let us remind that EMF project is a modeling framework and code generation facility for building tools and other applications based on a structured data model. Models can be specified using annotated Java, XML documents, or modeling tools and then can be used to produce a set of Java classes for the model, along with a set of adapter, factories and utility classes. You may find information and documentation about the EMF project at
http://www.eclipse.org/modeling/emf/docs/ .
Naturally, EMF (and its subprojects: EMF Core, CDO, Compare, Teneo, Model Query, etc) fits well in an Eclipse environment (Eclipse IDE or RCP). Nevertheless, EMF’s runtime features (use of generated code, notification, change recording, validation, persistence, etc) can be used in a standalone Java application. In order to benefits from EMF in such application, you must add all the needed jars to your classpath. In the book “EMF Eclipse Modelling Framework” you may find a table that clearly identifies the required jars based on the desired feature:
- Core runtime, reflective API, validation: org.eclipse.emf.common_<version>.jar and org.eclipse.emf.ecore_<version>.jar
- XML/XMI persistence: org.eclipse.emf.ecore.xmi_<version>.jar and the previous core runtime jars
- EMF.Edit: org.eclipse.emf.edit_<version>.jar and the core runtime jars
- Change model: org.eclipse.emf.change_<version>.jar and the core runtime jars
- Ecore to XML persistence mapping: org.eclipse.emf.mapping.exore2xml_<version>.jar and the core runtime and XML/XMI jars
- XML schema Infoset Model: org.eclipse.xsd_<version>.jar and the core runtime jars.
When using EMF under Eclipse, the plug-in extension mechanism is used to perform registration at runtime. In a standalone environment, default resource factories are not registered. Therefore, for each file extension or scheme the application wants to load or save, one needs to register the corresponding resource factory. For example, to load and save XML documents, it is necessary to add a similar line in your the application:
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xml", new XMLResourceFactoryImpl());
In addition, one also needs to register one’s package, which happens as a side effect of accessing XyzPackage.eINSTANCE attribute. For example, to register the example model, it is necessary to add the following lines to the program:
MyEMFExamplePackage.eINSTANCE.eClass();
ChangePackage.eINSTANCE.eClass(); // only if using EMF change feature
In my application I choose to code a class ResourceManager (which additionally is a Singleton) and put all these registrations in the initialization part of this object.
public class ResourceManager {
/**
* Create the resource manager.
*/
private ResourceManager() {
resourceSet = createResourceSet();
// register factories
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xml", new XMLResourceFactoryImpl());
// register packages
MyEMFExamplePackage.eINSTANCE.eClass();
ChangePackage.eINSTANCE.eClass(); // only if using EMF change feature
}
/**
* Create the resource set.
*/
private ResourceSet createResourceSet() {
ResourceSet rs = new ResourceSetImpl();
// Register the default resource factory -- only needed for stand-alone
rs.getResourceFactoryRegistry()
.getExtensionToFactoryMap()
.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
new XMIResourceFactoryImpl());
rs.setURIConverter(new MapItURIConverter());
return rs;
}
// Other methods ...
}
Now that we have registered all needed factories and packages, we can use the code generated by EMF in order to manipulate, save and load objects. In this example I instantiate a “dummy” model and, save it in an xml file. Subsequently, I load the model and record the modification in order to apply it later.
In this entry, we have seen an example of using EMF outside Eclipse, i.e., in a standalone Java application which could be a server component, a Swing GUI etc. It is to note that in order to use EMF feature in such environment, it is necessary to perform two important steps:
- Add required jars in the classpath
- Register Factories and packages prior to model utilization.