User Tools

Site Tools


Sidebar

Dave Orme muses about data-first development.

My current work emphasizes data engineering and analysis using Kubernetes, Clojure, Scala, Eclipse, and Google Cloud Platform or AWS.


Blog

The Cloud

Scala, Clojure, and FP

Data-First Development

Agile

Older work

Coconut Palm Software home


Donate Bitcoin:

1Ecnr9vtkC8b9FvmQjQaJ9ZsHB127UzVD6

Keywords:

Kubernetes, Docker, Streaming Data, Spark, Scala, Clojure, OSGi, Karaf, GCP, AWS, SQL

Disclaimer:

Everything I say here is my own opinion and not necessarily that of my employer.

blog:emf-prevayler

EMF-Prevayler, or PreMF

Have you ever wanted 100% transparent persistence for your memory-based EMF models?

As-in, after issuing one line to connect a Resource to a directory in your file system, you don't have to think about persistence any longer; you just manipulate your model using regular EMF and Java code. And all changes are automatically persisted to disk.

If so, maybe you would like something like the following:

// Given the following helper method:
 
private Resource makePersistentSystem(String tempDirPath) {
	Resource newSystem = new XMIResourceImpl();
	EmfPersister persister = new EmfPersister(newSystem, tempDirPath, -1);
	Resource persistentSystem = persister.getPersistentSystemRoot();  // Get the persistent decorator
	return persistentSystem;
}
 
// We can write:
 
String tempDirPath = tempDir().getAbsolutePath();
 
// Create a Resource and make it persistent
Resource persistentSystem = makePersistentSystem(tempDirPath);
 
// Add a Person to the persistent resource
Person person = factory.createPerson();
person.setFirstName("Dave");
persistentSystem.getContents().add(person);
 
// Create a second (empty) Resource
Resource secondSystem = new XMIResourceImpl();
 
// Attach it to the persistent system's directory, which will restore the 
// first system's contents into the second one
new EmfPersister(secondSystem, tempDirPath, -1);
 
// Now the second system should have a *copy* of the Person above
assertEquals(1, secondSystem.getContents().size());
Person restoredPerson = (Person) secondSystem.getContents().get(0);
assertTrue("Structurally equal", EcoreUtil.equals(person, restoredPerson));
assertFalse("Not the same object", restoredPerson.equals(person));

What's happening here is that whenever an object inside the Resource is mutated, Prevayler transparently notes this fact in a transaction journal in the specified directory. You don't have to do anything to make it happen.

The current implementation puts a decorator around every EMF object that intercepts method calls and if they mutate state, runs them through Prevayler.

So far there are only two catches.

1) When you create a new object, after adding it to a PreMF-managed object graph, you have to remember to either manually call the API that makes the object reference itself persistent, or just get it back out of the object graph (which will give you a persistent version).

2) #equals behaves slightly differently with persistent and non-persistent objects. If you ask a persistent object if it is equal to a non-persistent object, it will do the right thing. But a non-persistent object won't know how to compare itself with a persistent object. This only matters if you forget to make a new object reference persistent after adding it to the persistent object graph (as described in #1).

The current experimental implementation just makes the contents of XMLResource#getContents() persistent. Work is underway to make the rest of the EMF API persistent the same way.

Does this sound interesting/exciting?

I'm still an EMF newbie. Details of the approach/design are in the README.md on GitHub:

https://github.com/pieceoftheloaf/emf-prevayler

I'd love to hear what people think of this and/or if there's a better way to accomplish the same thing.

~~LINKBACK~~ ~~DISCUSSION:closed~~

blog/emf-prevayler.txt · Last modified: 2014/10/17 22:08 (external edit)