Harmonize how REST API handlers get a JSON body

Give the ability to any handler to get a JSON body which
can contain more information about the event. The indexing
is given a proper event object with the timestamp of when the event
was generated on the source node.

Preparation work to be able to automatically detect inconsistencies
between the object to be indexed and the real status of NoteDb.

Change-Id: I966cf259d68605a7acc54c47bf872b2ed2296162
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/AccountReindexRunnable.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/AccountReindexRunnable.java
index 68a8c14..487f3da 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/AccountReindexRunnable.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/AccountReindexRunnable.java
@@ -58,7 +58,7 @@
       Timestamp accountTs = a.getRegisteredOn();
       if (accountTs.after(sinceTs)) {
         log.info("Index {}/{}/{}/{}", a.getId(), a.getFullName(), a.getPreferredEmail(), accountTs);
-        accountIdx.index(a.getId(), Operation.INDEX);
+        accountIdx.index(a.getId(), Operation.INDEX, Optional.empty());
         return Optional.of(accountTs);
       }
     } catch (IOException | OrmException e) {
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/ChangeReindexRunnable.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/ChangeReindexRunnable.java
index f9a83a7..62a9792 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/ChangeReindexRunnable.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/ChangeReindexRunnable.java
@@ -103,7 +103,7 @@
       if (changeTs.after(sinceTs)) {
         log.info(
             "Index {}/{}/{} was updated after {}", c.getProject(), c.getId(), changeTs, sinceTs);
-        changeIdx.index(c.getProject() + "~" + c.getId(), Operation.INDEX);
+        changeIdx.index(c.getProject() + "~" + c.getId(), Operation.INDEX, Optional.empty());
         return Optional.of(changeTs);
       }
     } catch (OrmException | IOException e) {
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
index 9e3ddc9..d14b5da 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
@@ -76,7 +76,7 @@
 
       if (groupLastTs.isPresent() && groupLastTs.get().after(sinceTs)) {
         log.info("Index {}/{}/{}", g.getGroupUUID(), g.getName(), groupLastTs.get());
-        indexer.index(g.getGroupUUID(), Operation.INDEX);
+        indexer.index(g.getGroupUUID(), Operation.INDEX, Optional.empty());
         return groupLastTs;
       }
     } catch (OrmException | IOException e) {
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandler.java
index 42d2123..c68e058 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandler.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandler.java
@@ -20,6 +20,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.util.Optional;
 
 /**
  * Index an account using {@link AccountIndexer}. This class is meant to be used on the receiving
@@ -37,13 +38,14 @@
   }
 
   @Override
-  protected void doIndex(Account.Id id) throws IOException, OrmException {
+  protected void doIndex(Account.Id id, Optional<IndexEvent> indexEvent)
+      throws IOException, OrmException {
     indexer.index(id);
     log.debug("Account {} successfully indexed", id);
   }
 
   @Override
-  protected void doDelete(Account.Id id) {
+  protected void doDelete(Account.Id id, Optional<IndexEvent> indexEvent) {
     throw new UnsupportedOperationException("Delete from account index not supported");
   }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandler.java
index c455233..1bd1847 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandler.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandler.java
@@ -26,6 +26,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.util.Optional;
 
 /**
  * Index a change using {@link ChangeIndexer}. This class is meant to be used on the receiving side
@@ -48,7 +49,8 @@
   }
 
   @Override
-  protected void doIndex(String id) throws IOException, OrmException {
+  protected void doIndex(String id, Optional<IndexEvent> indexEvent)
+      throws IOException, OrmException {
     ChangeNotes change = null;
     try (ReviewDb db = schemaFactory.open()) {
       change = changeFinder.findOne(id);
@@ -70,7 +72,7 @@
   }
 
   @Override
-  protected void doDelete(String id) throws IOException {
+  protected void doDelete(String id, Optional<IndexEvent> indexEvent) throws IOException {
     indexer.delete(parseChangeId(id));
     log.debug("Change {} successfully deleted from index", id);
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandler.java
index c518484..7305ae6 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandler.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandler.java
@@ -20,6 +20,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.util.Optional;
 
 /**
  * Index a group using {@link GroupIndexer}. This class is meant to be used on the receiving side of
@@ -37,13 +38,14 @@
   }
 
   @Override
-  protected void doIndex(AccountGroup.UUID uuid) throws IOException, OrmException {
+  protected void doIndex(AccountGroup.UUID uuid, Optional<IndexEvent> indexEvent)
+      throws IOException, OrmException {
     indexer.index(uuid);
     log.debug("Group {} successfully indexed", uuid);
   }
 
   @Override
-  protected void doDelete(AccountGroup.UUID uuid) {
+  protected void doDelete(AccountGroup.UUID uuid, Optional<IndexEvent> indexEvent) {
     throw new UnsupportedOperationException("Delete from group index not supported");
   }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexingHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexingHandler.java
index e64d97b..f419216 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexingHandler.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexingHandler.java
@@ -17,6 +17,7 @@
 import com.google.common.util.concurrent.Striped;
 import com.google.gwtorm.server.OrmException;
 import java.io.IOException;
+import java.util.Optional;
 import java.util.concurrent.locks.Lock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,20 +43,23 @@
 
   private final Striped<Lock> idLocks = Striped.lock(10);
 
-  protected abstract void doIndex(T id) throws IOException, OrmException;
+  protected abstract void doIndex(T id, Optional<IndexEvent> indexEvent)
+      throws IOException, OrmException;
 
-  protected abstract void doDelete(T id) throws IOException;
+  protected abstract void doDelete(T id, Optional<IndexEvent> indexEvent) throws IOException;
 
   /**
    * Index an item in the local node, indexing will not be forwarded to the other node.
    *
    * @param id The id to index.
    * @param operation The operation to do; index or delete
+   * @param indexEvent The index event details.
    * @throws IOException If an error occur while indexing.
    * @throws OrmException If an error occur while retrieving a change related to the item to index
    */
-  public void index(T id, Operation operation) throws IOException, OrmException {
-    log.debug("{} {}", operation, id);
+  public void index(T id, Operation operation, Optional<IndexEvent> indexEvent)
+      throws IOException, OrmException {
+    log.debug("{} {} {}", operation, id, indexEvent);
     try {
       Context.setForwardedEvent(true);
       Lock idLock = idLocks.get(id);
@@ -63,10 +67,10 @@
       try {
         switch (operation) {
           case INDEX:
-            doIndex(id);
+            doIndex(id, indexEvent);
             break;
           case DELETE:
-            doDelete(id);
+            doDelete(id, indexEvent);
             break;
           default:
             log.error("unexpected operation: {}", operation);
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/Forwarder.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/Forwarder.java
index ab09b65..b156563 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/Forwarder.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/Forwarder.java
@@ -23,34 +23,38 @@
    * Forward a account indexing event to the other master.
    *
    * @param accountId the account to index.
+   * @param indexEvent the details of the index event.
    * @return true if successful, otherwise false.
    */
-  boolean indexAccount(int accountId);
+  boolean indexAccount(int accountId, IndexEvent indexEvent);
 
   /**
    * Forward a change indexing event to the other master.
    *
    * @param projectName the project of the change to index.
    * @param changeId the change to index.
+   * @param indexEvent the details of the index event.
    * @return true if successful, otherwise false.
    */
-  boolean indexChange(String projectName, int changeId);
+  boolean indexChange(String projectName, int changeId, IndexEvent indexEvent);
 
   /**
    * Forward a delete change from index event to the other master.
    *
    * @param changeId the change to remove from the index.
+   * @param indexEvent the details of the index event.
    * @return rue if successful, otherwise false.
    */
-  boolean deleteChangeFromIndex(int changeId);
+  boolean deleteChangeFromIndex(int changeId, IndexEvent indexEvent);
 
   /**
    * Forward a group indexing event to the other master.
    *
    * @param uuid the group to index.
+   * @param indexEvent the details of the index event.
    * @return true if successful, otherwise false.
    */
-  boolean indexGroup(String uuid);
+  boolean indexGroup(String uuid, IndexEvent indexEvent);
 
   /**
    * Forward a stream event to the other master.
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/IndexEvent.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/IndexEvent.java
new file mode 100644
index 0000000..f6f24a7
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/IndexEvent.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.ericsson.gerrit.plugins.highavailability.forwarder;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+public class IndexEvent {
+  public long eventCreatedOn = System.currentTimeMillis() / 1000;
+
+  @Override
+  public String toString() {
+    return "IndexEvent@"
+        + LocalDateTime.ofEpochSecond(eventCreatedOn, 0, ZoneOffset.UTC)
+            .format(DateTimeFormatter.ISO_DATE_TIME);
+  }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/AbstractIndexRestApiServlet.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/AbstractIndexRestApiServlet.java
index 7349ca5..8c429de 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/AbstractIndexRestApiServlet.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/AbstractIndexRestApiServlet.java
@@ -21,13 +21,20 @@
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler.Operation;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
+import com.google.common.base.Charsets;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.gwtorm.server.OrmException;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Optional;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 public abstract class AbstractIndexRestApiServlet<T> extends AbstractRestApiServlet {
   private static final long serialVersionUID = -1L;
+  private static final Gson gson = new GsonBuilder().create();
 
   private final ForwardedIndexingHandler<T> forwardedIndexingHandler;
   private final IndexName indexName;
@@ -80,7 +87,7 @@
     String path = req.getRequestURI();
     T id = parse(path.substring(path.lastIndexOf('/') + 1));
     try {
-      forwardedIndexingHandler.index(id, operation);
+      forwardedIndexingHandler.index(id, operation, parseBody(req));
       rsp.setStatus(SC_NO_CONTENT);
     } catch (IOException e) {
       sendError(rsp, SC_CONFLICT, e.getMessage());
@@ -91,4 +98,14 @@
       log.debug(msg, e);
     }
   }
+
+  protected Optional<IndexEvent> parseBody(HttpServletRequest req) throws IOException {
+    String contentType = req.getContentType();
+    if (contentType != null && contentType.contains("application/json")) {
+      return Optional.ofNullable(
+          gson.fromJson(
+              new InputStreamReader(req.getInputStream(), Charsets.UTF_8), IndexEvent.class));
+    }
+    return Optional.empty();
+  }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/HttpSession.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/HttpSession.java
index d3fce97..253dca7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/HttpSession.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/HttpSession.java
@@ -16,14 +16,19 @@
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.HttpResponseHandler.HttpResult;
 import com.ericsson.gerrit.plugins.highavailability.peers.PeerInfo;
-import com.google.common.base.Strings;
+import com.google.common.base.Supplier;
 import com.google.common.net.MediaType;
+import com.google.gerrit.server.events.SupplierSerializer;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.io.IOException;
+import java.net.URI;
 import java.nio.charset.StandardCharsets;
 import java.util.Optional;
 import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
@@ -31,6 +36,8 @@
 class HttpSession {
   private final CloseableHttpClient httpClient;
   private final Provider<Optional<PeerInfo>> peerInfo;
+  private final Gson gson =
+      new GsonBuilder().registerTypeAdapter(Supplier.class, new SupplierSerializer()).create();
 
   @Inject
   HttpSession(CloseableHttpClient httpClient, Provider<Optional<PeerInfo>> peerInfo) {
@@ -42,18 +49,14 @@
     return post(endpoint, null);
   }
 
-  HttpResult post(String endpoint, String content) throws IOException {
+  HttpResult post(String endpoint, Object content) throws IOException {
     HttpPost post = new HttpPost(getPeerInfo().getDirectUrl() + endpoint);
-    if (!Strings.isNullOrEmpty(content)) {
-      post.addHeader("Content-Type", MediaType.JSON_UTF_8.toString());
-      post.setEntity(new StringEntity(content, StandardCharsets.UTF_8));
-    }
+    setContent(post, content);
     return httpClient.execute(post, new HttpResponseHandler());
   }
 
   HttpResult delete(String endpoint) throws IOException {
-    return httpClient.execute(
-        new HttpDelete(getPeerInfo().getDirectUrl() + endpoint), new HttpResponseHandler());
+    return delete(endpoint, null);
   }
 
   private PeerInfo getPeerInfo() throws PeerInfoNotAvailableException {
@@ -63,4 +66,35 @@
     }
     return info;
   }
+
+  HttpResult delete(String endpoint, Object content) throws IOException {
+    HttpDeleteWithBody delete = new HttpDeleteWithBody(getPeerInfo().getDirectUrl() + endpoint);
+    setContent(delete, content);
+    return httpClient.execute(delete, new HttpResponseHandler());
+  }
+
+  private void setContent(HttpEntityEnclosingRequestBase request, Object content) {
+    if (content != null) {
+      request.addHeader("Content-Type", MediaType.JSON_UTF_8.toString());
+      request.setEntity(new StringEntity(jsonEncode(content), StandardCharsets.UTF_8));
+    }
+  }
+
+  private String jsonEncode(Object content) {
+    if (content instanceof String) {
+      return (String) content;
+    }
+    return gson.toJson(content);
+  }
+
+  private class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
+    @Override
+    public String getMethod() {
+      return HttpDelete.METHOD_NAME;
+    }
+
+    private HttpDeleteWithBody(String uri) {
+      setURI(URI.create(uri));
+    }
+  }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
index 3f596ce..1e9e931 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarder.java
@@ -17,14 +17,12 @@
 import com.ericsson.gerrit.plugins.highavailability.Configuration;
 import com.ericsson.gerrit.plugins.highavailability.cache.Constants;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.HttpResponseHandler.HttpResult;
 import com.google.common.base.Joiner;
-import com.google.common.base.Supplier;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.restapi.Url;
 import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.SupplierSerializer;
-import com.google.gson.GsonBuilder;
 import com.google.inject.Inject;
 import java.io.IOException;
 import javax.net.ssl.SSLException;
@@ -48,42 +46,43 @@
   }
 
   @Override
-  public boolean indexAccount(final int accountId) {
+  public boolean indexAccount(final int accountId, IndexEvent event) {
     return new Request("index account", accountId) {
       @Override
       HttpResult send() throws IOException {
         return httpSession.post(
-            Joiner.on("/").join(pluginRelativePath, "index/account", accountId));
+            Joiner.on("/").join(pluginRelativePath, "index/account", accountId), event);
       }
     }.execute();
   }
 
   @Override
-  public boolean indexChange(final String projectName, final int changeId) {
+  public boolean indexChange(String projectName, int changeId, IndexEvent event) {
     return new Request("index change", changeId) {
       @Override
       HttpResult send() throws IOException {
-        return httpSession.post(buildIndexEndpoint(projectName, changeId));
+        return httpSession.post(buildIndexEndpoint(projectName, changeId), event);
       }
     }.execute();
   }
 
   @Override
-  public boolean deleteChangeFromIndex(final int changeId) {
+  public boolean deleteChangeFromIndex(final int changeId, IndexEvent event) {
     return new Request("delete change", changeId) {
       @Override
       HttpResult send() throws IOException {
-        return httpSession.delete(buildIndexEndpoint(changeId));
+        return httpSession.delete(buildIndexEndpoint(changeId), event);
       }
     }.execute();
   }
 
   @Override
-  public boolean indexGroup(final String uuid) {
+  public boolean indexGroup(final String uuid, IndexEvent event) {
     return new Request("index group", uuid) {
       @Override
       HttpResult send() throws IOException {
-        return httpSession.post(Joiner.on("/").join(pluginRelativePath, "index/group", uuid));
+        return httpSession.post(
+            Joiner.on("/").join(pluginRelativePath, "index/group", uuid), event);
       }
     }.execute();
   }
@@ -103,12 +102,7 @@
     return new Request("send event", event.type) {
       @Override
       HttpResult send() throws IOException {
-        String serializedEvent =
-            new GsonBuilder()
-                .registerTypeAdapter(Supplier.class, new SupplierSerializer())
-                .create()
-                .toJson(event);
-        return httpSession.post(Joiner.on("/").join(pluginRelativePath, "event"), serializedEvent);
+        return httpSession.post(Joiner.on("/").join(pluginRelativePath, "event"), event);
       }
     }.execute();
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java
index 175eaaf..106422d 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java
@@ -16,6 +16,7 @@
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Context;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
 import com.google.common.base.Objects;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.events.AccountIndexedListener;
@@ -82,6 +83,12 @@
   }
 
   abstract class IndexTask implements Runnable {
+    protected final IndexEvent indexEvent;
+
+    IndexTask() {
+      indexEvent = new IndexEvent();
+    }
+
     @Override
     public void run() {
       queuedTasks.remove(this);
@@ -105,9 +112,9 @@
     @Override
     public void execute() {
       if (deleted) {
-        forwarder.deleteChangeFromIndex(changeId);
+        forwarder.deleteChangeFromIndex(changeId, indexEvent);
       } else {
-        forwarder.indexChange(projectName, changeId);
+        forwarder.indexChange(projectName, changeId, indexEvent);
       }
     }
 
@@ -140,7 +147,7 @@
 
     @Override
     public void execute() {
-      forwarder.indexAccount(accountId);
+      forwarder.indexAccount(accountId, indexEvent);
     }
 
     @Override
@@ -172,7 +179,7 @@
 
     @Override
     public void execute() {
-      forwarder.indexGroup(groupUUID);
+      forwarder.indexGroup(groupUUID, indexEvent);
     }
 
     @Override
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandlerTest.java
index 0a96776..b159570 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandlerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexAccountHandlerTest.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.index.account.AccountIndexer;
 import java.io.IOException;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,7 +49,7 @@
 
   @Test
   public void testSuccessfulIndexing() throws Exception {
-    handler.index(id, Operation.INDEX);
+    handler.index(id, Operation.INDEX, Optional.empty());
     verify(indexerMock).index(id);
   }
 
@@ -56,7 +57,7 @@
   public void deleteIsNotSupported() throws Exception {
     exception.expect(UnsupportedOperationException.class);
     exception.expectMessage("Delete from account index not supported");
-    handler.index(id, Operation.DELETE);
+    handler.index(id, Operation.DELETE, Optional.empty());
   }
 
   @Test
@@ -73,7 +74,7 @@
         .index(id);
 
     assertThat(Context.isForwardedEvent()).isFalse();
-    handler.index(id, Operation.INDEX);
+    handler.index(id, Operation.INDEX, Optional.empty());
     assertThat(Context.isForwardedEvent()).isFalse();
 
     verify(indexerMock).index(id);
@@ -92,7 +93,7 @@
 
     assertThat(Context.isForwardedEvent()).isFalse();
     try {
-      handler.index(id, Operation.INDEX);
+      handler.index(id, Operation.INDEX, Optional.empty());
       fail("should have thrown an IOException");
     } catch (IOException e) {
       assertThat(e.getMessage()).isEqualTo("someMessage");
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
index 000bfdb..942f530 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
@@ -34,6 +34,7 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.SchemaFactory;
 import java.io.IOException;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -78,20 +79,20 @@
   @Test
   public void changeIsIndexed() throws Exception {
     setupChangeAccessRelatedMocks(CHANGE_EXISTS);
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
     verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
   }
 
   @Test
   public void changeIsDeletedFromIndex() throws Exception {
-    handler.index(TEST_CHANGE_ID, Operation.DELETE);
+    handler.index(TEST_CHANGE_ID, Operation.DELETE, Optional.empty());
     verify(indexerMock, times(1)).delete(id);
   }
 
   @Test
   public void changeToIndexDoesNotExist() throws Exception {
     setupChangeAccessRelatedMocks(CHANGE_DOES_NOT_EXIST);
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
     verify(indexerMock, times(1)).delete(id);
   }
 
@@ -99,13 +100,13 @@
   public void schemaThrowsExceptionWhenLookingUpForChange() throws Exception {
     setupChangeAccessRelatedMocks(CHANGE_EXISTS, THROW_ORM_EXCEPTION);
     exception.expect(OrmException.class);
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
   }
 
   @Test
   public void indexerThrowsNoSuchChangeExceptionTryingToPostChange() throws Exception {
     doThrow(new NoSuchChangeException(id)).when(schemaFactoryMock).open();
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
     verify(indexerMock, times(1)).delete(id);
   }
 
@@ -113,7 +114,7 @@
   public void indexerThrowsNestedNoSuchChangeExceptionTryingToPostChange() throws Exception {
     OrmException e = new OrmException("test", new NoSuchChangeException(id));
     doThrow(e).when(schemaFactoryMock).open();
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
     verify(indexerMock, times(1)).delete(id);
   }
 
@@ -121,7 +122,7 @@
   public void indexerThrowsIOExceptionTryingToIndexChange() throws Exception {
     setupChangeAccessRelatedMocks(CHANGE_EXISTS, DO_NOT_THROW_ORM_EXCEPTION, THROW_IO_EXCEPTION);
     exception.expect(IOException.class);
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
   }
 
   @Test
@@ -139,7 +140,7 @@
         .index(any(ReviewDb.class), any(Change.class));
 
     assertThat(Context.isForwardedEvent()).isFalse();
-    handler.index(TEST_CHANGE_ID, Operation.INDEX);
+    handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
     assertThat(Context.isForwardedEvent()).isFalse();
 
     verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
@@ -159,7 +160,7 @@
 
     assertThat(Context.isForwardedEvent()).isFalse();
     try {
-      handler.index(TEST_CHANGE_ID, Operation.INDEX);
+      handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
       fail("should have thrown an IOException");
     } catch (IOException e) {
       assertThat(e.getMessage()).isEqualTo("someMessage");
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandlerTest.java
index d2387d9..103fd84 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandlerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexGroupHandlerTest.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.index.group.GroupIndexer;
 import java.io.IOException;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,7 +49,7 @@
 
   @Test
   public void testSuccessfulIndexing() throws Exception {
-    handler.index(uuid, Operation.INDEX);
+    handler.index(uuid, Operation.INDEX, Optional.empty());
     verify(indexerMock).index(uuid);
   }
 
@@ -56,7 +57,7 @@
   public void deleteIsNotSupported() throws Exception {
     exception.expect(UnsupportedOperationException.class);
     exception.expectMessage("Delete from group index not supported");
-    handler.index(uuid, Operation.DELETE);
+    handler.index(uuid, Operation.DELETE, Optional.empty());
   }
 
   @Test
@@ -73,7 +74,7 @@
         .index(uuid);
 
     assertThat(Context.isForwardedEvent()).isFalse();
-    handler.index(uuid, Operation.INDEX);
+    handler.index(uuid, Operation.INDEX, Optional.empty());
     assertThat(Context.isForwardedEvent()).isFalse();
 
     verify(indexerMock).index(uuid);
@@ -92,7 +93,7 @@
 
     assertThat(Context.isForwardedEvent()).isFalse();
     try {
-      handler.index(uuid, Operation.INDEX);
+      handler.index(uuid, Operation.INDEX, Optional.empty());
       fail("should have thrown an IOException");
     } catch (IOException e) {
       assertThat(e.getMessage()).isEqualTo("someMessage");
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexAccountRestApiServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexAccountRestApiServletTest.java
index c41a4a9..4622a17 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexAccountRestApiServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexAccountRestApiServletTest.java
@@ -17,6 +17,8 @@
 import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
 import static javax.servlet.http.HttpServletResponse.SC_METHOD_NOT_ALLOWED;
 import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -57,7 +59,7 @@
   @Test
   public void accountIsIndexed() throws Exception {
     servlet.doPost(requestMock, responseMock);
-    verify(handlerMock, times(1)).index(id, Operation.INDEX);
+    verify(handlerMock, times(1)).index(eq(id), eq(Operation.INDEX), any());
     verify(responseMock).setStatus(SC_NO_CONTENT);
   }
 
@@ -69,14 +71,14 @@
 
   @Test
   public void indexerThrowsIOExceptionTryingToIndexAccount() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(id, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(eq(id), eq(Operation.INDEX), any());
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
   }
 
   @Test
   public void sendErrorThrowsIOException() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(id, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(eq(id), eq(Operation.INDEX), any());
     doThrow(new IOException("someError")).when(responseMock).sendError(SC_CONFLICT, IO_ERROR);
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexChangeRestApiServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexChangeRestApiServletTest.java
index 7fccc21..c1fa765 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexChangeRestApiServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexChangeRestApiServletTest.java
@@ -17,6 +17,8 @@
 import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
 import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
 import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -58,34 +60,40 @@
   @Test
   public void changeIsIndexed() throws Exception {
     servlet.doPost(requestMock, responseMock);
-    verify(handlerMock, times(1)).index(CHANGE_ID, Operation.INDEX);
+    verify(handlerMock, times(1)).index(eq(CHANGE_ID), eq(Operation.INDEX), any());
     verify(responseMock).setStatus(SC_NO_CONTENT);
   }
 
   @Test
   public void changeIsDeletedFromIndex() throws Exception {
     servlet.doDelete(requestMock, responseMock);
-    verify(handlerMock, times(1)).index(CHANGE_ID, Operation.DELETE);
+    verify(handlerMock, times(1)).index(eq(CHANGE_ID), eq(Operation.DELETE), any());
     verify(responseMock).setStatus(SC_NO_CONTENT);
   }
 
   @Test
   public void indexerThrowsIOExceptionTryingToIndexChange() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(CHANGE_ID, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR))
+        .when(handlerMock)
+        .index(eq(CHANGE_ID), eq(Operation.INDEX), any());
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
   }
 
   @Test
   public void indexerThrowsOrmExceptionTryingToIndexChange() throws Exception {
-    doThrow(new OrmException("some message")).when(handlerMock).index(CHANGE_ID, Operation.INDEX);
+    doThrow(new OrmException("some message"))
+        .when(handlerMock)
+        .index(eq(CHANGE_ID), eq(Operation.INDEX), any());
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_NOT_FOUND, "Error trying to find change");
   }
 
   @Test
   public void sendErrorThrowsIOException() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(CHANGE_ID, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR))
+        .when(handlerMock)
+        .index(eq(CHANGE_ID), eq(Operation.INDEX), any());
     doThrow(new IOException("someError")).when(responseMock).sendError(SC_CONFLICT, IO_ERROR);
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexGroupRestApiServletTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexGroupRestApiServletTest.java
index f03727e..6291142 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexGroupRestApiServletTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/IndexGroupRestApiServletTest.java
@@ -17,6 +17,8 @@
 import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
 import static javax.servlet.http.HttpServletResponse.SC_METHOD_NOT_ALLOWED;
 import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -56,7 +58,7 @@
   @Test
   public void groupIsIndexed() throws Exception {
     servlet.doPost(requestMock, responseMock);
-    verify(handlerMock, times(1)).index(uuid, Operation.INDEX);
+    verify(handlerMock, times(1)).index(eq(uuid), eq(Operation.INDEX), any());
     verify(responseMock).setStatus(SC_NO_CONTENT);
   }
 
@@ -68,14 +70,18 @@
 
   @Test
   public void indexerThrowsIOExceptionTryingToIndexGroup() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(uuid, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR))
+        .when(handlerMock)
+        .index(eq(uuid), eq(Operation.INDEX), any());
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
   }
 
   @Test
   public void sendErrorThrowsIOException() throws Exception {
-    doThrow(new IOException(IO_ERROR)).when(handlerMock).index(uuid, Operation.INDEX);
+    doThrow(new IOException(IO_ERROR))
+        .when(handlerMock)
+        .index(eq(uuid), eq(Operation.INDEX), any());
     doThrow(new IOException("someError")).when(responseMock).sendError(SC_CONFLICT, IO_ERROR);
     servlet.doPost(requestMock, responseMock);
     verify(responseMock).sendError(SC_CONFLICT, IO_ERROR);
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderTest.java
index f49f2a3..fd2aa52 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderTest.java
@@ -15,13 +15,16 @@
 package com.ericsson.gerrit.plugins.highavailability.forwarder.rest;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import com.ericsson.gerrit.plugins.highavailability.Configuration;
 import com.ericsson.gerrit.plugins.highavailability.cache.Constants;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.HttpResponseHandler.HttpResult;
 import com.google.common.base.Joiner;
 import com.google.gerrit.reviewdb.client.Account;
@@ -64,7 +67,6 @@
   // Event
   private static final String EVENT_ENDPOINT = Joiner.on("/").join(PLUGINS, PLUGIN_NAME, "event");
   private static Event event = new Event("test-event") {};
-  private static String eventJson = new GsonBuilder().create().toJson(event);
 
   private RestForwarder forwarder;
   private HttpSession httpSessionMock;
@@ -80,99 +82,100 @@
 
   @Test
   public void testIndexAccountOK() throws Exception {
-    when(httpSessionMock.post(INDEX_ACCOUNT_ENDPOINT))
+    when(httpSessionMock.post(eq(INDEX_ACCOUNT_ENDPOINT), any()))
         .thenReturn(new HttpResult(SUCCESSFUL, EMPTY_MSG));
-    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER)).isTrue();
+    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER, new IndexEvent())).isTrue();
   }
 
   @Test
   public void testIndexAccountFailed() throws Exception {
-    when(httpSessionMock.post(INDEX_ACCOUNT_ENDPOINT))
+    when(httpSessionMock.post(eq(INDEX_ACCOUNT_ENDPOINT), any()))
         .thenReturn(new HttpResult(FAILED, EMPTY_MSG));
-    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER)).isFalse();
+    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testIndexAccountThrowsException() throws Exception {
-    doThrow(new IOException()).when(httpSessionMock).post(INDEX_ACCOUNT_ENDPOINT);
-    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER)).isFalse();
+    doThrow(new IOException()).when(httpSessionMock).post(eq(INDEX_ACCOUNT_ENDPOINT), any());
+    assertThat(forwarder.indexAccount(ACCOUNT_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testIndexGroupOK() throws Exception {
-    when(httpSessionMock.post(INDEX_GROUP_ENDPOINT))
+    when(httpSessionMock.post(eq(INDEX_GROUP_ENDPOINT), any()))
         .thenReturn(new HttpResult(SUCCESSFUL, EMPTY_MSG));
-    assertThat(forwarder.indexGroup(UUID)).isTrue();
+    assertThat(forwarder.indexGroup(UUID, new IndexEvent())).isTrue();
   }
 
   @Test
   public void testIndexGroupFailed() throws Exception {
-    when(httpSessionMock.post(INDEX_GROUP_ENDPOINT)).thenReturn(new HttpResult(FAILED, EMPTY_MSG));
-    assertThat(forwarder.indexGroup(UUID)).isFalse();
+    when(httpSessionMock.post(eq(INDEX_GROUP_ENDPOINT), any()))
+        .thenReturn(new HttpResult(FAILED, EMPTY_MSG));
+    assertThat(forwarder.indexGroup(UUID, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testIndexGroupThrowsException() throws Exception {
-    doThrow(new IOException()).when(httpSessionMock).post(INDEX_GROUP_ENDPOINT);
-    assertThat(forwarder.indexGroup(UUID)).isFalse();
+    doThrow(new IOException()).when(httpSessionMock).post(eq(INDEX_GROUP_ENDPOINT), any());
+    assertThat(forwarder.indexGroup(UUID, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testIndexChangeOK() throws Exception {
-    when(httpSessionMock.post(INDEX_CHANGE_ENDPOINT))
+    when(httpSessionMock.post(eq(INDEX_CHANGE_ENDPOINT), any()))
         .thenReturn(new HttpResult(SUCCESSFUL, EMPTY_MSG));
-    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER)).isTrue();
+    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER, new IndexEvent())).isTrue();
   }
 
   @Test
   public void testIndexChangeFailed() throws Exception {
-    when(httpSessionMock.post(INDEX_CHANGE_ENDPOINT)).thenReturn(new HttpResult(FAILED, EMPTY_MSG));
-    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER)).isFalse();
+    when(httpSessionMock.post(eq(INDEX_CHANGE_ENDPOINT), any()))
+        .thenReturn(new HttpResult(FAILED, EMPTY_MSG));
+    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testIndexChangeThrowsException() throws Exception {
-    doThrow(new IOException()).when(httpSessionMock).post(INDEX_CHANGE_ENDPOINT);
-    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER)).isFalse();
+    doThrow(new IOException()).when(httpSessionMock).post(eq(INDEX_CHANGE_ENDPOINT), any());
+    assertThat(forwarder.indexChange(PROJECT_NAME, CHANGE_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testChangeDeletedFromIndexOK() throws Exception {
-    when(httpSessionMock.delete(DELETE_CHANGE_ENDPOINT))
+    when(httpSessionMock.delete(eq(DELETE_CHANGE_ENDPOINT), any()))
         .thenReturn(new HttpResult(SUCCESSFUL, EMPTY_MSG));
-    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER)).isTrue();
+    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER, new IndexEvent())).isTrue();
   }
 
   @Test
   public void testChangeDeletedFromIndexFailed() throws Exception {
-    when(httpSessionMock.delete(DELETE_CHANGE_ENDPOINT))
+    when(httpSessionMock.delete(eq(DELETE_CHANGE_ENDPOINT), any()))
         .thenReturn(new HttpResult(FAILED, EMPTY_MSG));
-    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER)).isFalse();
+    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testChangeDeletedFromThrowsException() throws Exception {
-    doThrow(new IOException()).when(httpSessionMock).delete(DELETE_CHANGE_ENDPOINT);
-    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER)).isFalse();
+    doThrow(new IOException()).when(httpSessionMock).delete(eq(DELETE_CHANGE_ENDPOINT), any());
+    assertThat(forwarder.deleteChangeFromIndex(CHANGE_NUMBER, new IndexEvent())).isFalse();
   }
 
   @Test
   public void testEventSentOK() throws Exception {
-    when(httpSessionMock.post(EVENT_ENDPOINT, eventJson))
+    when(httpSessionMock.post(EVENT_ENDPOINT, event))
         .thenReturn(new HttpResult(SUCCESSFUL, EMPTY_MSG));
     assertThat(forwarder.send(event)).isTrue();
   }
 
   @Test
   public void testEventSentFailed() throws Exception {
-    when(httpSessionMock.post(EVENT_ENDPOINT, eventJson))
-        .thenReturn(new HttpResult(FAILED, EMPTY_MSG));
+    when(httpSessionMock.post(EVENT_ENDPOINT, event)).thenReturn(new HttpResult(FAILED, EMPTY_MSG));
     assertThat(forwarder.send(event)).isFalse();
   }
 
   @Test
   public void testEventSentThrowsException() throws Exception {
-    doThrow(new IOException()).when(httpSessionMock).post(EVENT_ENDPOINT, eventJson);
+    doThrow(new IOException()).when(httpSessionMock).post(EVENT_ENDPOINT, event);
     assertThat(forwarder.send(event)).isFalse();
   }
 
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java
index 39d7128..43c2fd7 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java
@@ -15,6 +15,8 @@
 package com.ericsson.gerrit.plugins.highavailability.index;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -63,25 +65,25 @@
   @Test
   public void shouldIndexInRemoteOnChangeIndexedEvent() throws Exception {
     indexEventHandler.onChangeIndexed(PROJECT_NAME, changeId.get());
-    verify(forwarder).indexChange(PROJECT_NAME, CHANGE_ID);
+    verify(forwarder).indexChange(eq(PROJECT_NAME), eq(CHANGE_ID), any());
   }
 
   @Test
   public void shouldIndexInRemoteOnAccountIndexedEvent() throws Exception {
     indexEventHandler.onAccountIndexed(accountId.get());
-    verify(forwarder).indexAccount(ACCOUNT_ID);
+    verify(forwarder).indexAccount(eq(ACCOUNT_ID), any());
   }
 
   @Test
   public void shouldDeleteFromIndexInRemoteOnChangeDeletedEvent() throws Exception {
     indexEventHandler.onChangeDeleted(changeId.get());
-    verify(forwarder).deleteChangeFromIndex(CHANGE_ID);
+    verify(forwarder).deleteChangeFromIndex(eq(CHANGE_ID), any());
   }
 
   @Test
   public void shouldIndexInRemoteOnGroupIndexedEvent() throws Exception {
     indexEventHandler.onGroupIndexed(accountGroupUUID.get());
-    verify(forwarder).indexGroup(UUID);
+    verify(forwarder).indexGroup(eq(UUID), any());
   }
 
   @Test