Migration
The introduction of plugins significantly eases migration issues because of the tight coupling between the software version of a plugin and the data model it uses. The plugin itself is responsible for implementing proper data model migration and XperienCentral offers an easy API to implement this.
In This Topic
Version number
Each plugin has a version number that consists of three numbers. The version number has a meaning and it is very important to use it properly because it tells users of the plugin the kind of changes they can expect between two separate versions of the plugin. The three parts of the version number have the following meaning:
- Major version - A major software update of the plugin. Such an update may change exposed APIs which may cause incompatibility with plugins that depend on it.
- Minor version - A backwards compatible plugin update. The exposed API has not been changed and plugins that depend on this plugin will therefore be compatible with the updated version. The API can be extended with additional functions.
- Micro version - Update without any change to the interface or published services.
If you properly use this version numbering system, other developers that may use services or classes exposed by this plugin will know in advance whether they should expect problems when upgrading to a later version of the plugin.
The version number of the plugin should be defined in the pom.xml
of the plugin. For example to define the version to be 1.0.2:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="…" ...> ... <groupId>...</groupId> <artifactId>...</artifactId> <version>1.0.2</version> ... </project>
When defining version numbers for your plugin, be sure that they conform to the development guidelines (G017 and G019 in particular).
Plugin Updates
When updating a plugin, the version number of the plugin must always be updated. Depending on the type of change the major, minor or micro version number must be updated:
- Major update - Property definitions of node types may be changed or removed, methods of exposed interfaces and classes may be changed in signature.
- Minor update - Additional property definitions may be added to node types but existing property definitions are not be changed or removed. Additional methods may be added to exposed interfaces and classes but the signature of existing methods are not be changed.
- Micro update - Node types are unaffected. The implementation of methods of exposed interfaces and classes may be changed, but no new methods have been added and the signature of existing methods are not changed.
Changes in the Data Model
The version number plays an important role in data model migration. A plugin version is tied to a particular data model and when the data model is updated, the plugin’s version should also change. Using the version number it is possible to implement the migration logic that is needed to upgrade content managed by the entity manager created from an x.y.z version of the plugin to x.y.z+1.
In order to implement the migration of the data model from x.y.z to x.y.z+1 you should implement the upgradeContent
method in the class defining the data model. Arguments passed to this method are the fromVersion
, which indicates the current version of the data model and a collection of nodes on which the migration must be performed. This method is invoked by the framework automatically if a new version of the plugin is installed. Note that a plugin doesn’t necessarily have to define this method - it’s only invoked, using reflection, if it exists.
The implementation of upgradeContent
is up to the developer. It may be implemented in a way that it is capable of upgrading from any version to the latest version or that it requires previous updates first. In the latter case, the method should throw an IncompatibeUpdateException
when the implementation of upgradeContent
is not capable of migrating from the fromVersion
to this version. The next part clarifies the migration implementation further with an example.
- The
upgradeContent
method will only be invoked on nodes managed by the Entity Manager. - The
upgradeContent
method is static. To use the Entity Manager (or any other service) in a static method, see Using Services in Static Methods. - Proper handling of content migration is a required guideline - see G020.
Explicitly setting the Platform Dependency
By default, the minimum and maximum version of XperienCentral that a plugin can run on is calculated as follows: If the version of XperienCentral for which you build the plugin is x.y.z, then the minimum version of XperienCentral on which the plugin can run is x.y and the maximum version is (x+1).0. It is also possible to explicity set the minimum and maximum versions of XperienCentral on which a plugin can run in the POM file using the setting properties webmanager.wcb-min-version
and webmanager.wcb-max-version
. For example:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>nl.gx.webmanager.wcbs</groupId> <artifactId>XperienCentral-wcbs</artifactId> <version>10.6.0-SNAPSHOT</version> </parent> <packaging>osgi-bundle</packaging> <artifactId>wmpjcrbrowser</artifactId> <name>JCR Browser</name> <properties> <Webmanager.wcb.max-version>10.4</Webmanager.wcb.max-version> <Webmanager.wcb.min-version>10.0</Webmanager.wcb.min-version> </properties> ... </project>
If webmanager.wcb.min-version
and webmanager.wcb.max-version
are not specified, the default versions as described above are calculated and used.
Example
An example of a "Keyword" plugin that changes its node type definition (data model) over time is presented here. The following updates to the node type definition are performed:
- The 1.0 version of the plugin contains a
keyword
property - The 1.1 version adds an additional
secondaryKeyword
property - The 1.2 version adds an additional
keywords
property is added. The propertieskeyword
andsecondaryKeyword
are deprecated - The 2.0 version removes the
keyword
andsecondaryKeyword
properties
The fromVersion
argument of the upgradeContent
method is the version of the plugin currently installed. This example uses an approach that requires previous version updates, which means that each version must be installed separately. So to update from 1.0 to 2.0, the system administrator first has to deploy 1.1, then 1.2 and finally 2.0. The code snippets below provide examples of how the code looks like for the several versions.
Version 1.0
@Property public String getKeyword(){...} public void setKeyword(String keyword) {...}
Version 1.1
@Property public String getKeyword(){...} public void setKeyword(String keyword) {...} @Property public String getSecondaryKeyword(){...} public void setSecondaryKeyword(String keyword) {...}
Version 1.2
@Property @Deprecated public String getKeyword(){ return getKeywords()[0]; } public void setKeyword(String keyword) { setKeywords(new String[]{keyword, “”}); } @Property @Deprecated public String getSecondaryKeyword(){ return getKeywords()[1]; } public void setSecondaryKeyword(String keyword) { setKeywords(new String[]{“”, keyword}); } @Property public String[] getKeywords() {...} public void setKeywords(String[] keywords) {...} public static void upgradeContent(String fromVersion, Node[] nodes) throws IncompatibeUpdateException { if (fromVersion.compareTo(“1.1”) != 0) { String msg = “This update requires 1.1. “; msg += “Current Plugin version is “ + fromVersion; throw new IncompatibeUpdateException(msg); } else { updateKeywords(nodes); } } public static void updateKeywords(Node[] nodes) { for (int i=0; i<nodes.length;i++) { String pKeyword = nodes[i].getProperty("keyword").getString(); String sKeyword = nodes[i].getProperty("secondaryKeyword").getString(); String[] keywords = new String[]{pKeyword, sKeyword}; nodes[i].setProperty(“keywords”, keywords); } nodes[0].getSession().save(); }
Version 2.0
@Property public String[] getKeywords() {...} public void setKeywords(String[] keywords) {...} public static void upgradeContent(String fromVersion, Node[] nodes) throws IncompatibeUpdateException { if (fromVersion.compareTo(“1.2”) != 0 { String msg = “This update requires 1.2. “; msg += “Current Plugin version is “ + fromVersion; throw new IncompatibeUpdateException(msg); } }