Java, Eclipse and Web programming Tutorials
Follow me on twitter About Lars Vogel

Eclipse Modeling Framework (EMF) - Persisting models

Lars Vogel

Version 0.1

20.01.2010

Revision History
Revision 0.1 20.01.2010Lars Vogel
split from main EMF article into own article

Eclipse EMF - Persistence

This article describes how to persists Eclipse EMF in XMI (XML).

This article is based on Eclipse 3.5.


Table of Contents

1. Models and Eclipse EMF
2. Writing and loading EMF models via Java code
2.1. Using the model code
2.2. Create model via Java code and save it
2.3. Load an existing model
3. Appendix: Encryption
4. Thank you
5. Questions and Discussion
6. Links and Literature
6.1. Source Code
6.2. EMF Resources
6.3. Other Resources

1. Models and Eclipse EMF

For a general introduction into Eclipse EMF please see Eclipse EMF Tutorial

This article focus on the persistence of EMF models via XMI. It also explains how to use encryption for the XMI files.

2. Writing and loading EMF models via Java code

2.1. Using the model code

EMF allows to store the model content via the EMF persistence framework. By default EMF uses XMI (XML Metadata Interchange). XMI is an standard for exchanging metadata information via Extensible Markup Language (XML).

The generated model code looks like normal Java code and can be used like normal Java code. The *PackageImpl.java.init() method needs to be called before doing anything else as this method initializes the model and the listeners.

The following demonstrates how you create a model instance via Java code, save it and load it again.

2.2. Create model via Java code and save it

Create a new plugin project "de.vogella.emf.webpage.instance". Add the following dependency to your "plugin.xml".

  • org.eclipse.emf.ecore
  • org.eclipse.emf.ecore.xmi

Tip

Objects which do not have a "contains relationship" must be added explicitly to the resource.getContents().add(). If objects are not added and not included in a contains relationship an exception is thrown when calling resource.save()

				
package writeWebpage;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

import datamodel.website.MyWeb;
import datamodel.website.Webpage;
import datamodel.website.WebsiteFactory;
import datamodel.website.WebsitePackage;
import datamodel.website.impl.WebsitePackageImpl;

public class CreateSaveTester {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Initialize the model
		WebsitePackage.eINSTANCE.eClass();
		// Retrieve the default factory singleton
		WebsiteFactory factory = WebsiteFactory.eINSTANCE;

		// Create the content of the model via this program
		MyWeb myWeb = factory.createMyWeb();
		Webpage page = factory.createWebpage();
		page.setName("index");
		page.setDescription("Main webpage");
		page.setKeywords("Eclipse, EMF");
		page.setTitle("Eclipse EMF");
		myWeb.getPages().add(page);

		// As of here we preparing to save the model content

		// Register the XMI resource factory for the .website extension

		Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
		Map<String, Object> m = reg.getExtensionToFactoryMap();
		m.put("website", new XMIResourceFactoryImpl());

		// Obtain a new resource set
		ResourceSet resSet = new ResourceSetImpl();

		// Create a resource
		Resource resource = resSet.createResource(URI
				.createURI("website/My2.website"));
		// Get the first model element and cast it to the right type, in my
		// example everything is hierarchical included in this first node
		resource.getContents().add(myWeb);

		// Now save the content.
		try {
			resource.save(Collections.EMPTY_MAP);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

			

2.3. Load an existing model

The following coding can be used to load an existing model.

				

package writeWebpage;

import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

import datamodel.website.MyWeb;
import datamodel.website.WebsitePackage;
import datamodel.website.impl.WebsitePackageImpl;

public class EMFModelLoad {
	public MyWeb load() {
		// Initialize the model
		WebsitePackage.eINSTANCE.eClass();
		
		// Register the XMI resource factory for the .website extension

		Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
		Map<String, Object> m = reg.getExtensionToFactoryMap();
		m.put("website", new XMIResourceFactoryImpl());

		// Obtain a new resource set
		ResourceSet resSet = new ResourceSetImpl();

		// Get the resource
		Resource resource = resSet.getResource(URI
				.createURI("website/My.website"), true);
		// Get the first model element and cast it to the right type, in my
		// example everything is hierarchical included in this first node
		MyWeb myWeb = (MyWeb) resource.getContents().get(0);
		return myWeb;
	}

}

			

You can then access the model content via standard Java coding.

				
package writeWebpage;

import java.util.Iterator;

import datamodel.website.MyWeb;
import datamodel.website.Webpage;

public class LoadTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Loading the existing model
		EMFModelLoad loader = new EMFModelLoad();
		MyWeb myWeb = loader.load();
		// Accessing the model information
		System.out.println(myWeb.getDescription());
		System.out.println(myWeb.getTitle());
		// Lets see what info the webpage has
		for (Iterator<Webpage> iterator = myWeb.getPages().iterator(); iterator
				.hasNext();) {
			Webpage page = iterator.next();
			System.out.println("Name : " + page.getName());
			// We could also iterate over the Articles...
		}
	}
}

			

3. Appendix: Encryption

EMF has the possibility to encrypt the data model before writing it and to decrypt it before loading. The following demonstrates this.

Create an model based on the following interface.

			
package mymodel;

import org.eclipse.emf.ecore.EObject;
/**
 * @model
 */
public interface IPerson extends EObject {
	/**
	 * @model default="";
	 */
	public String getLastname();
}


		

Create the following factory which sets the option for encryption.

			
package factory;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.AESCipherImpl;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

public class MyXMIFactoryImpl extends XMIResourceFactoryImpl {

	@Override
	public Resource createResource(URI uri) {
		XMIResourceFactoryImpl resFactory = new XMIResourceFactoryImpl();
		XMIResource resource = (XMIResource) resFactory.createResource(uri);
		try {
			resource.getDefaultLoadOptions().put(Resource.OPTION_CIPHER,
					new AESCipherImpl("12345"));
			resource.getDefaultSaveOptions().put(Resource.OPTION_CIPHER,
					new AESCipherImpl("12345"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resource;
	}
}

		

Create the following test class.

			
package load;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import mymodel.IPerson;
import mymodel.MymodelFactory;
import mymodel.impl.MymodelPackageImpl;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;

import factory.MyXMIFactoryImpl;

public class Create {
	public void create() {
		MymodelPackageImpl.init();
		// Retrieve the default factory singleton
		MymodelFactory factory = MymodelFactory.eINSTANCE;

		// Create the content of the model via this program
		IPerson person = factory.createIPerson();
		person.setLastname("Lars");

		// Register the XMI resource factory for the .website extension
		Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
		Map<String, Object> m = reg.getExtensionToFactoryMap();
		m.put("person", new MyXMIFactoryImpl());

		// Obtain a new resource set
		ResourceSet resSet = new ResourceSetImpl();

		// Create a resource
		Resource resource = resSet.createResource(URI
		.createURI("mymodel.person"));
		resource.getContents().add(person);

		// Now save the content.
			try {
				resource.save(Collections.EMPTY_MAP);
			} catch (IOException e) {
				e.printStackTrace();
			}
	}
	
	public void load() {
		// Initialize the model
		MymodelPackageImpl.init();
		// Register the XMI resource factory for the .website extension
		Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
		Map<String, Object> m = reg.getExtensionToFactoryMap();
		m.put("person", new MyXMIFactoryImpl());
		ResourceSet resSet = new ResourceSetImpl();
		Resource resource = resSet.getResource(URI
				.createURI("mymodel.person"), true);
		try {
			IPerson person= (IPerson) resource.getContents().get(0);
			System.out.println(person.getLastname());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		Create test = new Create();
		test.create();
		test.load();
	}
}

		

4. Thank you

Thank you for practicing with this tutorial.

Please note that I maintain this website in my private time. If you like the information I'm providing please help me by donating.

5. Questions and Discussion

For questions and discussion around this article please use the www.vogella.de Google Group. Also if you note an error in this article please post the error and if possible the correction to the Group.

I believe the following is a very good guideline for asking questions in general and also for the Google group How To Ask Questions The Smart Way.

6. Links and Literature

6.1. Source Code

http://www.vogella.de/code/codeeclipse.html Source Code of Examples

6.2. EMF Resources

http://www.eclipse.org/modeling/emf Eclipse EMF Homepage

http://www.eclipse.org/modeling/emf/docs/ EMF Documentation

http://www.ibm.com/developerworks/opensource/library/os-ecemf1 Model with the Eclipse Modeling Framework, Part 1: Create UML models and generate code

http://www.ibm.com/developerworks/opensource/library/os-ecemf2 Model with the Eclipse Modeling Framework, Part 2: Generate code with Eclipse's Java Emitter Templates

http://www.eclipse.org/m2m/atl/ ATL allows model to model transformation for EMF