Refactoring: move command classes from jgroups to commands package

Since the command (de)serialization is now moved out of the jgroups
package to to commands package we also rename JGroupsGson to
CommandsGson and also move type adapters to the commands package.

Change-Id: Ib6420f4bd9c03973471d9e69286647fee24f3413
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
index 6a90e73..095adee 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
@@ -18,6 +18,7 @@
 import com.ericsson.gerrit.plugins.highavailability.cache.CacheModule;
 import com.ericsson.gerrit.plugins.highavailability.event.EventModule;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwarderModule;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups.JGroupsForwarderModule;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.RestForwarderModule;
 import com.ericsson.gerrit.plugins.highavailability.index.IndexModule;
@@ -55,6 +56,7 @@
         install(new PeerInfoModule(config.peerInfo().strategy()));
         break;
       case JGROUPS:
+        install(new ForwarderCommandsModule());
         install(new JGroupsForwarderModule());
         break;
       default:
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/AddToProjectList.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/AddToProjectList.java
similarity index 93%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/AddToProjectList.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/AddToProjectList.java
index 6f47da3..4883dda 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/AddToProjectList.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/AddToProjectList.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/Command.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/Command.java
similarity index 92%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/Command.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/Command.java
index 3abad1e..1b7b86e 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/Command.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/Command.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializer.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializer.java
similarity index 97%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializer.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializer.java
index cdd217c..1100284 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializer.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializer.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import com.google.gson.JsonDeserializationContext;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessor.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java
similarity index 88%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessor.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java
index 489e070..ca30de7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessor.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.CacheEntry;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Context;
@@ -25,23 +25,20 @@
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedProjectListUpdateHandler;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetrics;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetricsRegistry;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.events.Event;
-import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Optional;
-import org.jgroups.Message;
-import org.jgroups.blocks.RequestHandler;
 
 @Singleton
-public class MessageProcessor implements RequestHandler {
+public class CommandProcessor {
   private static final FluentLogger log = FluentLogger.forEnclosingClass();
 
-  private final Gson gson;
   private final ForwardedIndexChangeHandler indexChangeHandler;
   private final ForwardedIndexBatchChangeHandler indexBatchChangeHandler;
   private final ForwardedIndexAccountHandler indexAccountHandler;
@@ -51,8 +48,8 @@
   private final ProcessorMetricsRegistry metricRegistry;
 
   @Inject
-  MessageProcessor(
-      @JGroupsGson Gson gson,
+  @VisibleForTesting
+  public CommandProcessor(
       ForwardedIndexChangeHandler indexChangeHandler,
       ForwardedIndexBatchChangeHandler indexBatchChangeHandler,
       ForwardedIndexAccountHandler indexAccountHandler,
@@ -60,7 +57,6 @@
       ForwardedEventHandler eventHandler,
       ForwardedProjectListUpdateHandler projectListUpdateHandler,
       ProcessorMetricsRegistry metricRegistry) {
-    this.gson = gson;
     this.indexChangeHandler = indexChangeHandler;
     this.indexBatchChangeHandler = indexBatchChangeHandler;
     this.indexAccountHandler = indexAccountHandler;
@@ -70,9 +66,7 @@
     this.metricRegistry = metricRegistry;
   }
 
-  @Override
-  public Object handle(Message msg) {
-    Command cmd = getCommand(msg);
+  public boolean handle(Command cmd) {
     ProcessorMetrics metrics = metricRegistry.get(cmd.type);
     Instant startTime = Instant.now();
     boolean success = false;
@@ -117,7 +111,7 @@
       } else if (cmd instanceof PostEvent) {
         Event event = ((PostEvent) cmd).getEvent();
         eventHandler.dispatch(event);
-
+        log.atFine().log("Dispatching event %s done", event);
       } else if (cmd instanceof AddToProjectList) {
         String projectName = ((AddToProjectList) cmd).getProjectName();
         projectListUpdateHandler.update(projectName, false);
@@ -145,15 +139,4 @@
       throw new IllegalArgumentException("Unknown type of IndexChange command " + cmd.getClass());
     }
   }
-
-  private Command getCommand(Message msg) {
-    try {
-      String s = (String) msg.getObject();
-      log.atFine().log("Received message: %s", s);
-      return gson.fromJson(s, Command.class);
-    } catch (RuntimeException e) {
-      log.atSevere().withCause(e).log("Error parsing message %s", msg.getObject());
-      throw e;
-    }
-  }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsGson.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandsGson.java
similarity index 87%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsGson.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandsGson.java
index a4ca15a..d381402 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsGson.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandsGson.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
@@ -21,4 +21,4 @@
 
 @BindingAnnotation
 @Retention(RUNTIME)
-public @interface JGroupsGson {}
+public @interface CommandsGson {}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/DeleteAllProjectChangesFromIndex.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/DeleteAllProjectChangesFromIndex.java
similarity index 86%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/DeleteAllProjectChangesFromIndex.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/DeleteAllProjectChangesFromIndex.java
index 81ce445..532708b 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/DeleteAllProjectChangesFromIndex.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/DeleteAllProjectChangesFromIndex.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import com.google.gerrit.entities.Project;
@@ -23,7 +23,7 @@
 
   private final Project.NameKey projectName;
 
-  protected DeleteAllProjectChangesFromIndex(Project.NameKey projectName, Instant createdOn) {
+  public DeleteAllProjectChangesFromIndex(Project.NameKey projectName, Instant createdOn) {
     super(TYPE, createdOn);
     this.projectName = projectName;
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/EvictCache.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/EvictCache.java
similarity index 82%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/EvictCache.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/EvictCache.java
index 9ca05f1..151b839 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/EvictCache.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/EvictCache.java
@@ -12,18 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
 
 public class EvictCache extends Command {
-  static final EventType TYPE = EventType.CACHE_EVICTION;
+  public static final EventType TYPE = EventType.CACHE_EVICTION;
 
   private final String cacheName;
   private final String keyJson;
 
-  protected EvictCache(String cacheName, String keyJson, Instant eventCreatedOn) {
+  public EvictCache(String cacheName, String keyJson, Instant eventCreatedOn) {
     super(TYPE, eventCreatedOn);
     this.cacheName = cacheName;
     this.keyJson = keyJson;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/ForwarderCommandsModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/ForwarderCommandsModule.java
new file mode 100644
index 0000000..7a1b039
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/ForwarderCommandsModule.java
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 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.commands;
+
+import com.ericsson.gerrit.plugins.highavailability.forwarder.InstantTypeAdapter;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.gerrit.server.events.EventGson;
+import com.google.gson.Gson;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+import java.time.Instant;
+
+public class ForwarderCommandsModule extends AbstractModule {
+  @Provides
+  @Singleton
+  @CommandsGson
+  @VisibleForTesting
+  public Gson buildCommandsGson(@EventGson Gson eventGson) {
+    return eventGson
+        .newBuilder()
+        .registerTypeAdapter(Command.class, new CommandDeserializer())
+        .registerTypeAdapter(Instant.class, new InstantTypeAdapter())
+        .create();
+  }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexAccount.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexAccount.java
similarity index 92%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexAccount.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexAccount.java
index 55cadda..6c95d1d 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexAccount.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexAccount.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexChange.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexChange.java
similarity index 96%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexChange.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexChange.java
index 075bfd7..990ae8e 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexChange.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexChange.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import com.google.common.base.Strings;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexGroup.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexGroup.java
similarity index 87%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexGroup.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexGroup.java
index 9f49060..3ae8458 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexGroup.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexGroup.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
@@ -22,7 +22,7 @@
 
   private final String uuid;
 
-  protected IndexGroup(String uuid, Instant eventCreatedOn) {
+  public IndexGroup(String uuid, Instant eventCreatedOn) {
     super(TYPE, eventCreatedOn);
     this.uuid = uuid;
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexProject.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexProject.java
similarity index 87%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexProject.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexProject.java
index 40e400d..7feffc4 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/IndexProject.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/IndexProject.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
@@ -22,7 +22,7 @@
 
   private String projectName;
 
-  protected IndexProject(String projectName, Instant eventCreatedOn) {
+  public IndexProject(String projectName, Instant eventCreatedOn) {
     super(TYPE, eventCreatedOn);
     this.projectName = projectName;
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/PostEvent.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/PostEvent.java
similarity index 88%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/PostEvent.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/PostEvent.java
index 3f50b0a..18c17c7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/PostEvent.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/PostEvent.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import com.google.gerrit.server.events.Event;
@@ -23,7 +23,7 @@
 
   private final Event event;
 
-  protected PostEvent(Event event, Instant eventCreatedOn) {
+  public PostEvent(Event event, Instant eventCreatedOn) {
     super(TYPE, eventCreatedOn);
     this.event = event;
   }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/RemoveFromProjectList.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/RemoveFromProjectList.java
similarity index 93%
rename from src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/RemoveFromProjectList.java
rename to src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/RemoveFromProjectList.java
index 1a43ac8..b1ee7df 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/RemoveFromProjectList.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/RemoveFromProjectList.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.EventType;
 import java.time.Instant;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarder.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarder.java
index 0bd8c5d..1c004f7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarder.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarder.java
@@ -19,6 +19,17 @@
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwarderMetricsRegistry;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.AddToProjectList;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.Command;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandsGson;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.DeleteAllProjectChangesFromIndex;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.EvictCache;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexAccount;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexChange;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexGroup;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexProject;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.PostEvent;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.RemoveFromProjectList;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.events.Event;
@@ -53,7 +64,7 @@
   JGroupsForwarder(
       MessageDispatcher dispatcher,
       Configuration cfg,
-      @JGroupsGson Gson gson,
+      @CommandsGson Gson gson,
       @JGroupsForwarderExecutor FailsafeExecutor<Result> executor,
       ForwarderMetricsRegistry metricsRegistry) {
     this.dispatcher = dispatcher;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java
index 0895088..98600f1 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java
@@ -16,17 +16,11 @@
 
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder.Result;
-import com.ericsson.gerrit.plugins.highavailability.forwarder.InstantTypeAdapter;
 import com.ericsson.gerrit.plugins.highavailability.peers.jgroups.JChannelProviderModule;
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.server.events.EventGson;
-import com.google.gson.Gson;
-import com.google.inject.Provides;
 import com.google.inject.Scopes;
-import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import dev.failsafe.FailsafeExecutor;
-import java.time.Instant;
 import org.jgroups.blocks.MessageDispatcher;
 import org.jgroups.blocks.RequestHandler;
 
@@ -36,7 +30,7 @@
   protected void configure() {
     bind(Forwarder.class).to(JGroupsForwarder.class);
     bind(MessageDispatcher.class).toProvider(MessageDispatcherProvider.class).in(Scopes.SINGLETON);
-    bind(RequestHandler.class).to(MessageProcessor.class);
+    bind(RequestHandler.class).to(JGroupsMessageProcessor.class);
     install(new JChannelProviderModule());
     listener().to(OnStartStop.class);
 
@@ -45,15 +39,4 @@
         .toProvider(FailsafeExecutorProvider.class)
         .in(Scopes.SINGLETON);
   }
-
-  @Provides
-  @Singleton
-  @JGroupsGson
-  Gson buildJGroupsGson(@EventGson Gson eventGson) {
-    return eventGson
-        .newBuilder()
-        .registerTypeAdapter(Command.class, new CommandDeserializer())
-        .registerTypeAdapter(Instant.class, new InstantTypeAdapter())
-        .create();
-  }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsMessageProcessor.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsMessageProcessor.java
new file mode 100644
index 0000000..ff091b9
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsMessageProcessor.java
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 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.jgroups;
+
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.Command;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessor;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandsGson;
+import com.google.common.flogger.FluentLogger;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.jgroups.Message;
+import org.jgroups.blocks.RequestHandler;
+
+@Singleton
+public class JGroupsMessageProcessor implements RequestHandler {
+  private static final FluentLogger log = FluentLogger.forEnclosingClass();
+
+  private final Gson gson;
+  private final CommandProcessor processor;
+
+  @Inject
+  JGroupsMessageProcessor(@CommandsGson Gson gson, CommandProcessor processor) {
+    this.gson = gson;
+    this.processor = processor;
+  }
+
+  @Override
+  public Object handle(Message msg) {
+    return processor.handle(getCommand(msg));
+  }
+
+  private Command getCommand(Message msg) {
+    try {
+      String s = (String) msg.getObject();
+      log.atFine().log("Received message: %s", s);
+      return gson.fromJson(s, Command.class);
+    } catch (RuntimeException e) {
+      log.atSevere().withCause(e).log("Error parsing message %s", msg.getObject());
+      throw e;
+    }
+  }
+}
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializerTest.java
similarity index 97%
rename from src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializerTest.java
rename to src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializerTest.java
index 7829a80..7c3a886 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/CommandDeserializerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandDeserializerTest.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups;
+package com.ericsson.gerrit.plugins.highavailability.forwarder.commands;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -35,7 +35,7 @@
   @Before
   public void setUp() {
     Gson eventGson = new EventGsonProvider().get();
-    this.gson = new JGroupsForwarderModule().buildJGroupsGson(eventGson);
+    this.gson = new ForwarderCommandsModule().buildCommandsGson(eventGson);
     this.cacheKeyParser = new CacheKeyJsonParser(eventGson);
   }
 
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderTest.java
index e7542b4..1a926bf 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderTest.java
@@ -27,6 +27,7 @@
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwarderMetrics;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwarderMetricsRegistry;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule;
 import com.google.gerrit.server.events.EventGsonProvider;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gson.Gson;
@@ -65,7 +66,7 @@
   @Before
   public void setUp() throws Exception {
     Gson eventGson = new EventGsonProvider().get();
-    Gson gson = new JGroupsForwarderModule().buildJGroupsGson(eventGson);
+    Gson gson = new ForwarderCommandsModule().buildCommandsGson(eventGson);
     Configuration cfg = mock(Configuration.class, RETURNS_DEEP_STUBS);
     when(cfg.jgroups().maxTries()).thenReturn(MAX_TRIES);
     when(cfg.jgroups().retryInterval()).thenReturn(Duration.ofMillis(1));
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java
index 91d291c..d17b3f1 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java
@@ -33,6 +33,14 @@
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedProjectListUpdateHandler;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetrics;
 import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetricsRegistry;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.AddToProjectList;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessor;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.EvictCache;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexAccount;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexChange;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.PostEvent;
+import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.RemoveFromProjectList;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.server.events.Event;
@@ -55,7 +63,7 @@
 @RunWith(org.mockito.junit.MockitoJUnitRunner.class)
 public class MessageProcessorTest {
 
-  private MessageProcessor processor;
+  private JGroupsMessageProcessor processor;
   private Gson gson;
 
   private ForwardedIndexChangeHandler indexChangeHandler;
@@ -74,7 +82,7 @@
   public void setUp() {
     when(metricsRegistry.get(any())).thenReturn(processorMetrics);
     Gson eventGson = new EventGsonProvider().get();
-    gson = new JGroupsForwarderModule().buildJGroupsGson(eventGson);
+    gson = new ForwarderCommandsModule().buildCommandsGson(eventGson);
 
     indexChangeHandler = createHandlerMock(ForwardedIndexChangeHandler.class);
     indexBatchChangeHandler = createHandlerMock(ForwardedIndexBatchChangeHandler.class);
@@ -84,15 +92,16 @@
     projectListUpdateHandler = createHandlerMock(ForwardedProjectListUpdateHandler.class);
 
     processor =
-        new MessageProcessor(
+        new JGroupsMessageProcessor(
             gson,
-            indexChangeHandler,
-            indexBatchChangeHandler,
-            indexAccountHandler,
-            cacheEvictionHandler,
-            eventHandler,
-            projectListUpdateHandler,
-            metricsRegistry);
+            new CommandProcessor(
+                indexChangeHandler,
+                indexBatchChangeHandler,
+                indexAccountHandler,
+                cacheEvictionHandler,
+                eventHandler,
+                projectListUpdateHandler,
+                metricsRegistry));
   }
 
   private <T> T createHandlerMock(Class<T> handlerClass) {