Run Hippo Updater Scripts on Startup

April 12th 2019 Hippo CMS Maven

Once a Hippo CMS project is deployed to production for the first time, editors will start changing the content there. There's no easy way to merge those changes with the ones coming from developers. The official recommendation is to use Groovy updater scripts to do that when necessary.

Fortunately, such merging of content can usually be avoided. A rare scenario in which this isn't always possible are dynamic resource bundles with translations. Since editors will modify existing translations using the bundle editor, the resource bundles can't simply be overwritten when deploying a new version with additional translation keys.

Groovy updater scripts are the right tool for adding these new translation keys without changing existing ones. Bart Vreeken has written a great blogpost describing the approach that you can take. You can find the accompanying source code on GitHub. For same reason, there's no link to it from the blogpost although it is mentioned several times.

Most probably, you will want to execute this updater script on every Hippo startup to apply any changes included with the latest version. This Hippo CMS feature is almost completely undocumented. I could only find a mention of it in the article about running the scripts:

It's possible to automatically execute scripts on startup by using the repository-data-application module to add the scripts as content definitions to /hippo:configuration/hippo:update/hippo:queue. Once the application has started, it will execute any scripts in the queue.

After some experimentation I came up with a solution which seems to work. I started by adding the script to the Updater Editor Registry in my development instance. Thanks to the auto-export feature, this created a corresponding registry.yaml file in the repository-data/application/src/main/resources/hcm-content/configuration/update folder.

By changing the node in the first line of the file from /hippo:configuration/hippo:update/hippo:registry/ScriptName to /hippo:configuration/hippo:update/hippo:queue/ScriptName (I recommend that you also rename the file to queue.yaml although this doesn't affect the behavior), the script will be added to the queue during startup instead to the registry. This will cause it to be executed immediately. You can confirm that by looking at the History in the Updater Editor.

Unfortunately, this will only happen the first time you start Hippo CMS after creating the file. On subsequent startups nothing will happen. Judging from the behavior, it seems that updater scripts are treated as content although they are placed in the /hippo:configuration node. The placement of the registry.yaml file in the hcm-content folder instead of the hcm-config folder might also be an indicator of that.

To force the script to be executed on every startup, I had to resort to content actions. I created a hcm-actions.yaml file in the repository-data/application/src/main/resources folder with the following contents:

action-lists:
  - VERSION:
      /hippo:configuration/hippo:update/hippo:queue/MyUpdateScript: reload

I used the VERSION placeholder instead of a specific version so that I could replace it during build with the actual version that is currently being built. This way the action will be executed after every deploy of a new version because the version number will be higher than the previous one.

I used the maven-replacer-plugin for replacing the placeholder. I added the following configuration to the pom.xml file of the repository-data/application submodule:

<plugin>
  <groupId>com.google.code.maven-replacer-plugin</groupId>
  <artifactId>replacer</artifactId>
  <version>1.5.3</version>
  <executions>
    <execution>
      <phase>process-resources</phase>
      <goals>
        <goal>replace</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <includes>
      <include>${basedir}/target/classes/hcm-actions.yaml</include>
    </includes>
    <replacements>
      <replacement>
        <token>VERSION</token>
        <value>${version}</value>
      </replacement>
    </replacements>
  </configuration>
</plugin>

To keep the original file intact, I am replacing the placeholder in thetarget folder. I have to do it in the process-resources phase when the file from the src folder is already copied there.

I'm not sure this is the best (or the simplest) way for executing updater scripts on every startup. But after some initial testing it seems to work for me.

Copyright
Creative Commons License