jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bruno Sinou <bsi...@argeo.org>
Subject Adding mandatory properties to existing repository - any news under the sun ?
Date Thu, 26 May 2011 14:32:53 GMT

we are running an application based on JackRabbit 2.2 and we are
facing our first migration.
Some of the changes in our model are not trivial : typically, we have
to add some new mandatory properties.

As I have looked on the fori and the mailing lists, I have found a few
thread on the subject, typically
	+ http://markmail.org/message/pyyj4pqew6f7peog
	+ http://markmail.org/message/4ui7en5d6myygngm

I have then implemented some unit tests to validate the approach,
following the below steps :

1) instantiate a newly created JCR repository based on the old CND,
populate and close it. The repository persistence is backed by a H2
2) instantiate the repo based on a tmp CND, where new mandatory
properties are marked optionnal
3) update all existing items in the repo to create the new properties
== Following step is the hack!
4) stop the repository, delete the
/repository/nodetypes/custom_nodetypes.xml file
5) restart the repo based on the new CND file.

Everything seems to work fine, but the process is not very clean. Can
someone who has already experienced this process on large live
application share some feedbacks ?

Furthermore, all threads on the subject I have found seem to be kind
of old (version 1.x)  : is there a cleaner/newer way to process  ?

Thanks in advance.


========== ===================
For those interested, you can find below some pseudo code : JUnit test
case in a spring framework with 3 set of lazy loading beans (an old, a
tmp and a new).

private final static String MY_NEW_PROPERTY = "custom:myNewProperty"

// Initialize base with old data
Backend curBackend = getBeanWithName(Backend.class, "oldBackend");
Session curSession = getBeanWithName(Session.class, "oldJcrSession");

Node importNode_old = curBackend.doImportFromCVS(new Date(),
extractOld.getInputStream(), model);

/** Test if persistence works after refreshing bean context */

// Force the context to close to refresh beans
// Note that a closed context cannot be started again, a new one must
be created.
ConfigurableApplicationContext cac = getContext();
cac = getContext();
curBackend = getBeanWithName(Backend.class, "oldBackend");
curSession = getBeanWithName(Session.class, "oldJcrSession");
long nbOfRow = curBackend.listAllEbis().getSize();
assertEquals(3, nbOfRow);

// Introduce tmp data model and update existing nodes
cac = getContext();
curBackend = getBeanWithName(Backend.class, "tmpBackend");
curSession = getBeanWithName(Session.class, "tmpJcrSession");

UpdateModel um = new UpdateModel();

// populate existing items with newly created mandatory fields.
um.createMandatoryProperty(curBackend, MY_NEW_PROPERTY,
PropertyType.STRING, "");

// Introduce new data model

// HACK : manually delete old node type definition to enable non-trivial
// changes on node definition
File nodeTypeFile = new File(pathToRepository + relPathToNodeTypeFile);
boolean hackOk = nodeTypeFile.delete();
if (hackOk)
	log.info("Old custom_nodetypes.xml file has been deleted.");
	log.warn("Old custom_nodetypes.xml file could not be deleted"
		+ " : new CND file won't be loaded correctly.");

cac = getContext();
curBackend = getBeanWithName(Backend.class, "newBackend");
curSession = getBeanWithName(Session.class, "newJcrSession");

// Import some new data and check if new property is taken into account
Node importNode_new = curBackend.doImportFromCVS(new Date(),
extractNew.getInputStream(), model);
Node newNode = curBackend.getItemById(anId);
assertEquals("A newly imported value",

// try to modify an old Item to see if no exception is thrown
Node node = curBackend.getItemById(anIdOfAnOldItem);
node.setProperty(MY_NEW_PROPERTY, "a sample value");

View raw message