]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-560: Initial implementation of ES reindexing event listener.
authorRay Lee <rhlee@berkeley.edu>
Thu, 3 Jan 2019 22:35:39 +0000 (14:35 -0800)
committerRay Lee <rhlee@berkeley.edu>
Thu, 3 Jan 2019 22:35:39 +0000 (14:35 -0800)
3rdparty/nuxeo/nuxeo-platform-listener/build.xml
3rdparty/nuxeo/nuxeo-platform-listener/pom.xml
3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.properties [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/pom.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/META-INF/MANIFEST.MF [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/deployment-fragment.xml [new file with mode: 0644]
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/event-contrib.xml [new file with mode: 0644]

index f5d1eb238fd540900b721e13c0c958f9f0824b06..87dd0d928fe8beff353ed13d4e6dd8ee3160550a 100644 (file)
 
     <target name="deploy" depends="package"
             description="deploy nuxeo server libs to ${jee.server.cspace}">
+        <ant antfile="reindex/build.xml" target="deploy" inheritall="false"/>
         <ant antfile="updateobjectlocationonmove/build.xml" target="deploy" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="deploy" inheritall="false"/>
         <ant antfile="updateimagederivatives/build.xml" target="deploy" inheritall="false"/>
         <ant antfile="naturalhistory/build.xml" target="deploy" inheritall="false"/>
-        <ant antfile="botgarden/build.xml" target="deploy" inheritall="false"/>        
+        <ant antfile="botgarden/build.xml" target="deploy" inheritall="false"/>
     </target>
 
     <target name="undeploy"
             description="undeploy nuxeo server libs from ${jee.server.cspace}">
+        <ant antfile="reindex/build.xml" target="undeploy" inheritall="false"/>
         <ant antfile="updateobjectlocationonmove/build.xml" target="undeploy" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="undeploy" inheritall="false"/>
         <ant antfile="updateimagederivatives/build.xml" target="undeploy" inheritall="false"/>
         <ant antfile="naturalhistory/build.xml" target="undeploy" inheritall="false"/>
-        <ant antfile="botgarden/build.xml" target="undeploy" inheritall="false"/>        
+        <ant antfile="botgarden/build.xml" target="undeploy" inheritall="false"/>
     </target>
 
     <target name="dist"
             description="generate distribution for nuxeo server libs" depends="package">
+        <ant antfile="reindex/build.xml" target="dist" inheritall="false"/>
         <ant antfile="updateobjectlocationonmove/build.xml" target="dist" inheritall="false"/>
         <ant antfile="updaterelationsondelete/build.xml" target="dist" inheritall="false"/>
         <ant antfile="updateimagederivatives/build.xml" target="dist" inheritall="false"/>
         <ant antfile="naturalhistory/build.xml" target="dist" inheritall="false"/>
-        <ant antfile="botgarden/build.xml" target="dist" inheritall="false"/>        
+        <ant antfile="botgarden/build.xml" target="dist" inheritall="false"/>
     </target>
 
 </project>
index 913bdb8c523727ad2d44e1645380af2eefaabc3e..093c67f3935f1d520b1ae4ebe81417a7bd88d6db 100644 (file)
@@ -13,6 +13,7 @@
     <name>services.3rdparty.nuxeo.listener</name>
 
     <modules>
+        <module>reindex</module>
         <module>updateobjectlocationonmove</module>
         <module>updaterelationsondelete</module>
         <module>updateimagederivatives</module>
@@ -34,7 +35,7 @@
         <dependency>
             <groupId>org.nuxeo.ecm.platform</groupId>
             <artifactId>nuxeo-platform-filemanager-api</artifactId>
-            <version>${nuxeo.platform.version}</version>    
+            <version>${nuxeo.platform.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.properties b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.properties
new file mode 100644 (file)
index 0000000..ee625cf
--- /dev/null
@@ -0,0 +1 @@
+listener.module.name=reindex
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.xml b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/build.xml
new file mode 100644 (file)
index 0000000..c8b2ee1
--- /dev/null
@@ -0,0 +1,104 @@
+<project name="org.collectionspace.services.3rdparty.nuxeo.listener.reindex">
+  <description>
+    CollectionSpace Nuxeo listener component type
+  </description>
+  <!-- Set global properties for this build -->
+  <property name="services.trunk" value="../../../.."/>
+  <!-- Environment should be declared before reading build.properties -->
+  <property environment="env" />
+  <!-- Set global properties for this build -->
+  <property file="${services.trunk}/build.properties" />
+  <!-- Set local properties for this build -->
+  <property file="build.properties" />
+  <property name="mvn.opts" value="-V" />
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="dist"  location="dist"/>
+
+  <!-- module.name variable is set in the local properties file -->
+  <property name="jar.name"
+    value="org.collectionspace.services.listener.${listener.module.name}-${cspace.release}.jar"/>
+
+  <property name="jar.all"
+    value="org.collectionspace.services.listener.${listener.module.name}-*.jar"/>
+  
+  <condition property="osfamily-unix">
+    <os family="unix" />
+  </condition>
+  <condition property="osfamily-windows">
+    <os family="windows" />
+  </condition>
+  
+  <target name="init" >
+    <!-- Create the time stamp -->
+    <tstamp/>
+    <!-- Create the build directory structure used by compile -->
+    <mkdir dir="${build}"/>
+  </target>
+  
+  <target name="package" depends="package-unix,package-windows"
+    description="Package CollectionSpace Services" />
+  <target name="package-unix" if="osfamily-unix">
+    <exec executable="mvn" failonerror="true">
+      <arg value="package" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  <target name="package-windows" if="osfamily-windows">
+    <exec executable="cmd" failonerror="true">
+      <arg value="/c" />
+      <arg value="mvn" />
+      <arg value="package" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  
+  <target name="install" depends="install-unix,install-windows"
+    description="Install" />
+  <target name="install-unix" if="osfamily-unix">
+    <exec executable="mvn" failonerror="true">
+      <arg value="install" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  <target name="install-windows" if="osfamily-windows">
+    <exec executable="cmd" failonerror="true">
+      <arg value="/c" />
+      <arg value="mvn" />
+      <arg value="install" />
+      <arg value="-Dmaven.test.skip=true" />
+      <arg value="-f" />
+      <arg value="${basedir}/pom.xml" />
+      <arg value="-N" />
+      <arg value="${mvn.opts}" />
+    </exec>
+  </target>
+  
+  <target name="deploy" depends="install"
+    description="deploy collectionspace core doctype in ${jee.server.nuxeo}">
+    <copy file="${basedir}/target/${jar.name}"
+      todir="${jee.deploy.nuxeo.plugins}"/>
+  </target>
+  
+  <target name="undeploy"
+    description="undeploy collectionspace Thumbnail service from ${jee.server.nuxeo}">
+    <delete>
+      <fileset dir="${jee.deploy.nuxeo.plugins}">
+        <include name="${jar.all}"/>
+      </fileset>
+    </delete>
+  </target>
+  
+</project>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/pom.xml b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/pom.xml
new file mode 100644 (file)
index 0000000..0fd43ef
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>org.collectionspace.services.3rdparty.nuxeo.listener</artifactId>
+        <groupId>org.collectionspace.services</groupId>
+        <version>5.2-SNAPSHOT</version>
+    </parent>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <artifactId>org.collectionspace.services.listener.reindex</artifactId>
+    <name>org.collectionspace.services.listener.reindex</name>
+    <url>http://maven.apache.org</url>
+
+
+   <dependencies>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile> src/main/resources/META-INF/MANIFEST.MF </manifestFile>
+                        <manifestEntries>
+                            <Bundle-Version>${eclipseVersion}</Bundle-Version>
+                            <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java
new file mode 100644 (file)
index 0000000..285ffea
--- /dev/null
@@ -0,0 +1,115 @@
+package org.collectionspace.services.listener;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.collections.ListUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.LifeCycleConstants;
+import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
+import org.nuxeo.ecm.core.event.Event;
+import org.nuxeo.ecm.core.event.EventBundle;
+import org.nuxeo.ecm.core.event.PostCommitEventListener;
+import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
+import org.nuxeo.elasticsearch.ElasticSearchComponent;
+import org.nuxeo.elasticsearch.api.ElasticSearchService;
+import org.nuxeo.runtime.api.Framework;
+
+/**
+ * Event listener that triggers reindexing of records in Elasticsearch when an associated record
+ * is created/updated/deleted. When a record is created or updated Nuxeo will automatically
+ * reindex it in ElasticSearch, but Nuxeo does not know about other records that may also need to
+ * be reindexed; for example, if a related record denormalizes data from the updated record at
+ * index time.
+ */
+public class Reindex implements PostCommitEventListener {
+    // FIXME: This listener runs asynchronously post-commit, so that reindexing records after a
+    // save does not hold up the save. In order to make it async, this class does not extend
+    // AbstractCSEventListenerImpl, because AbstractCSEventListenerImpl does not implement
+    // PostCommitEventListener (DRYD-477). Therefore this listener is not able to use the
+    // isRegistered method of AbstractCSEventListenerImpl to determine if it has been registered to
+    // run for the current tenant. Instead, it relies on the ReindexSupport listener, which does
+    // extend AbstractCSEventListenerImpl, to set a property in the event context that is used to
+    // determine if this listener should run. This means that this listener will be considered to
+    // be registered if and only if the ReindexSupport listener is registered.
+
+    public static final String IS_REGISTERED_KEY = "Reindex.IS_REGISTERED";
+    public static final String PREV_COVERAGE_KEY = "Reindex.PREV_COVERAGE";
+    public static final String PREV_PUBLISH_TO_KEY = "Reindex.PREV_PUBLISH_TO";
+
+    @Override
+    public void handleEvent(EventBundle events) {
+        // When a media record is created, reindex the material item that is referenced by its
+        // coverage field.
+        
+        // When a media record is updated and the coverage changed, reindex both the old and new
+        // referenced material items.
+
+        // When a media record is deleted, reindex the material item that was referenced by its
+        // coverage field.
+        
+        // TODO: Make this configurable. This is currently hardcoded to the needs of the material
+        // profile/Material Order application.
+
+        if (Framework.isBooleanPropertyTrue("elasticsearch.enabled") && events.size() > 0) {
+            Iterator<Event> iter = events.iterator();
+
+            while (iter.hasNext()) {
+                Event event = iter.next();
+                DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
+                Boolean isRegistered = (Boolean) eventContext.getProperty(IS_REGISTERED_KEY);
+
+                if (isRegistered != null && isRegistered == true) {
+                    DocumentModel doc = eventContext.getSourceDocument();
+                    String docType = doc.getType();
+                    String eventName = event.getName();
+    
+                    if (docType.startsWith("Media")) {
+                        if (
+                            eventName.equals(DocumentEventTypes.DOCUMENT_CREATED) ||
+                            eventName.equals(DocumentEventTypes.DOCUMENT_UPDATED)
+                        ) {
+                            String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
+                            String coverage = (String) doc.getProperty("media_common", "coverage");
+    
+                            List<String> prevPublishTo = (List<String>) eventContext.getProperty(PREV_PUBLISH_TO_KEY);
+                            List<String> publishTo = (List<String>) doc.getProperty("media_materials", "publishToList");
+    
+                            if (doc.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) {
+                                reindex(doc.getRepositoryName(), coverage);
+                            }
+                            else if (
+                                !ListUtils.isEqualList(prevPublishTo, publishTo) ||
+                                !StringUtils.equals(prevCoverage, coverage)
+                            ) {
+                                if (!StringUtils.equals(prevCoverage, coverage)) {
+                                    reindex(doc.getRepositoryName(), prevCoverage);
+                                }
+    
+                                reindex(doc.getRepositoryName(), coverage);
+                            }
+                        }
+                        else if (eventName.equals(DocumentEventTypes.DOCUMENT_REMOVED)) {
+                            String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
+    
+                            reindex(doc.getRepositoryName(), prevCoverage);
+                        }
+                    }    
+                }
+            }
+        }
+    }
+
+    private void reindex(String repositoryName, String refName) {
+        if (StringUtils.isEmpty(refName)) {
+            return;
+        }
+
+        String escapedRefName = refName.replace("'", "\\'");
+        String query = String.format("SELECT ecm:uuid FROM Materialitem WHERE collectionspace_core:refName = '%s'", escapedRefName);
+
+        ElasticSearchComponent es = (ElasticSearchComponent) Framework.getService(ElasticSearchService.class);
+        es.runReindexingWorker(repositoryName, query);
+    }
+}
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java
new file mode 100644 (file)
index 0000000..313e227
--- /dev/null
@@ -0,0 +1,71 @@
+package org.collectionspace.services.listener;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.event.CoreEventConstants;
+import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
+import org.nuxeo.ecm.core.event.Event;
+import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
+import org.nuxeo.runtime.api.Framework;
+
+/**
+ * Event listener that stores the values of fields of interest before documents are updated or
+ * deleted. This is necessary because the previous/deleted doument model will not be available
+ * to a post-modification/deletion event listener. Storing the previous/deleted values allows
+ * the post-modification/deletion event listener to take action if a field value was changed,
+ * or if a document was deleted that had a certain field value.
+ * 
+ * This is a separate class from the Reindex listener, because the Reindex listener should be
+ * async and post-commit, so it must implement PostCommitEventListener. This listener must be
+ * synchronous and pre-commit, so it must implement EventListener. Nuxeo does not support 
+ * a single class that implements both PostCommitEventListener and EventListener (such a listener
+ * will only run synchronously).
+ */
+public class ReindexSupport extends AbstractCSEventListenerImpl {
+
+    @Override
+    public void handleEvent(Event event) {
+        // When a media record is about to be updated, store the value of the coverage and
+        // publishToList fields.
+
+        // When a media record is about to be removed, store the value of the coverage field.
+
+        // TODO: Make this configurable. This is currently hardcoded to the needs of the material
+        // profile/Material Order application.
+
+        if (isRegistered(event)) {
+            DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
+
+            // Set a property if this listener is registered for the current tenant. This allows
+            // the Reindex listener to determine if it should run (since it is async, it cannot
+            // extend AbstractCSEventListenerImpl, so it cannot use the isRegistered method).
+            
+            eventContext.setProperty(Reindex.IS_REGISTERED_KEY, true);
+
+            if (Framework.isBooleanPropertyTrue("elasticsearch.enabled")) {
+                DocumentModel doc = eventContext.getSourceDocument();
+                String docType = doc.getType();
+                String eventName = event.getName();
+        
+                if (docType.startsWith("Media")) {
+                    if (eventName.equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) {
+                        DocumentModel previousDoc = (DocumentModel) eventContext.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL);
+                        String coverage = (String) previousDoc.getProperty("media_common", "coverage");
+                        List<String> publishTo = (List<String>) previousDoc.getProperty("media_materials", "publishToList");
+        
+                        eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage);
+                        eventContext.setProperty(Reindex.PREV_PUBLISH_TO_KEY, (Serializable) publishTo);
+                    }
+                    else if (eventName.equals(DocumentEventTypes.ABOUT_TO_REMOVE)) {
+                        String coverage = (String) doc.getProperty("media_common", "coverage");
+        
+                        eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/META-INF/MANIFEST.MF b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..932d325
--- /dev/null
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0 
+Bundle-ManifestVersion: 1 
+Bundle-Name: org.collectionspace.services.listener.reindex
+Bundle-SymbolicName: org.collectionspace.services.listener.reindex;singleton:=true 
+Bundle-Version: 1.0.0
+Bundle-Localization: plugin
+Bundle-Vendor: Nuxeo
+Require-Bundle: org.nuxeo.runtime, 
+ org.nuxeo.ecm.core.api,
+ org.nuxeo.ecm.core,
+ org.nuxeo.ecm.webapp.core
+Provide-Package: org.collectionspace.services.listener.reindex
+Nuxeo-Component: OSGI-INF/event-contrib.xml
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/deployment-fragment.xml b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/deployment-fragment.xml
new file mode 100644 (file)
index 0000000..270abbd
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<fragment>
+
+  <extension target="application#MODULE">
+    <module>
+      <java>${bundle.fileName}</java>
+    </module>
+  </extension>
+  
+</fragment>
diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/event-contrib.xml b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/resources/OSGI-INF/event-contrib.xml
new file mode 100644 (file)
index 0000000..3be10bf
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<component name="org.collectionspace.services.listener.reindex">
+    <extension target="org.nuxeo.ecm.core.event.EventServiceComponent" point="listener">
+        <listener name="reindexlistener" async="true" postCommit="true"
+                  class="org.collectionspace.services.listener.Reindex">
+            <event>documentCreated</event>
+            <event>documentModified</event>
+            <event>documentRemoved</event>
+        </listener>
+    </extension>
+    <extension target="org.nuxeo.ecm.core.event.EventServiceComponent" point="listener">
+        <listener name="reindexsupportlistener" async="false" postCommit="false"
+                  class="org.collectionspace.services.listener.ReindexSupport">
+            <event>aboutToCreate</event>
+            <event>aboutToRemove</event>
+            <event>beforeDocumentModification</event>
+        </listener>
+    </extension>
+</component>