EventGsonProvider: Register generic event serializer adapter This custom serializer is only needed if instance is created in one plugin, but the serialization takes place in another plugin. If the class is reachable from the same classpath loader where the event instance was instantiated, then it will work without this change. This will simplify multi-site plugin setup, that is using inter-plugin communication: o multi-site plugin, that is using events-broker o events-broker libModule, that provides BrokerApi abstraction o events-kafka plugin, that is using Apache Kafka event streaming backend and is used by events-broker's DynamicItem o events-gcloud-pubsub plugin, that is using GCloud's PubSub event streaming backend and is used by events-broker's DynamicItem o events-aws-kinesis plugin, that is using AWS's Kinesis event streaming backend and is used by events-broker's DynamicItem This change would allow us to drop EventGsonProvider fork in multi-site plugin. Change-Id: I7dc6e6a859152ee3e30a90075ddd34814720eba1 (cherry picked from commit 89f7a75dbaebdb7bba92ae1f11c7505ec80dcfc2)
diff --git a/java/com/google/gerrit/server/events/EventGsonProvider.java b/java/com/google/gerrit/server/events/EventGsonProvider.java index 72cf7be..27be2f3 100644 --- a/java/com/google/gerrit/server/events/EventGsonProvider.java +++ b/java/com/google/gerrit/server/events/EventGsonProvider.java
@@ -25,6 +25,7 @@ @Override public Gson get() { return new GsonBuilder() + .registerTypeAdapter(Event.class, new EventSerializer()) .registerTypeAdapter(Event.class, new EventDeserializer()) .registerTypeAdapter(Supplier.class, new SupplierSerializer()) .registerTypeAdapter(Supplier.class, new SupplierDeserializer())
diff --git a/java/com/google/gerrit/server/events/EventSerializer.java b/java/com/google/gerrit/server/events/EventSerializer.java new file mode 100644 index 0000000..7322ef3 --- /dev/null +++ b/java/com/google/gerrit/server/events/EventSerializer.java
@@ -0,0 +1,37 @@ +// Copyright (C) 2021 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.google.gerrit.server.events; + +import com.google.gerrit.common.UsedAt; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; + +@UsedAt(UsedAt.Project.PLUGIN_MULTI_SITE) +class EventSerializer implements JsonSerializer<Event> { + @Override + public JsonElement serialize(Event src, Type typeOfSrc, JsonSerializationContext context) { + String type = src.getType(); + + Class<?> cls = EventTypes.getClass(type); + if (cls == null) { + throw new JsonParseException("Unknown event type: " + type); + } + + return context.serialize(src, cls); + } +}
diff --git a/javatests/com/google/gerrit/server/events/EventJsonTest.java b/javatests/com/google/gerrit/server/events/EventJsonTest.java index 9ca60ca..8e4f436 100644 --- a/javatests/com/google/gerrit/server/events/EventJsonTest.java +++ b/javatests/com/google/gerrit/server/events/EventJsonTest.java
@@ -78,6 +78,19 @@ } @Test + public void customEventSimulateClassloaderIssue() { + EventTypes.register(CustomEvent.TYPE, CustomEvent.class); + CustomEvent event = new CustomEvent(); + event.customField = "customValue"; + // Need to serialise using the Event interface instead of json.getClass() + // for simulating the serialisation of an object owned by another class loader + String json = gson.toJson(event, Event.class); + CustomEvent resullt = gson.fromJson(json, CustomEvent.class); + assertThat(resullt.type).isEqualTo(CustomEvent.TYPE); + assertThat(resullt.customField).isEqualTo(event.customField); + } + + @Test public void refUpdatedEvent() { RefUpdatedEvent event = new RefUpdatedEvent();