This is an automated email from the ASF dual-hosted git repository. domgarguilo pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/main by this push: new 06c55fbea4 Create Gson singleton to use in place of new instances (#3516) 06c55fbea4 is described below commit 06c55fbea47f7ac376c7c93b48b76529e0d4a474 Author: Dom G <domgargu...@apache.org> AuthorDate: Thu Jun 22 15:26:36 2023 -0400 Create Gson singleton to use in place of new instances (#3516) * Create Gson singleton to use in place of new instances --------- Co-authored-by: Dave Marion <dlmar...@apache.org> --- .../core/clientImpl/bulk/BulkSerialize.java | 3 +- .../apache/accumulo/core/lock/ServiceLockData.java | 11 +++--- .../schema/ExternalCompactionFinalState.java | 8 ++-- .../schema/ExternalCompactionMetadata.java | 9 ++--- .../core/metadata/schema/RootTabletMetadata.java | 8 ++-- .../spi/compaction/DefaultCompactionPlanner.java | 6 +-- .../spi/scan/ConfigurableScanServerSelector.java | 7 ++-- .../apache/accumulo/core/util/GsonSingleton.java | 44 ++++++++++++++++++++++ .../accumulo/server/metadata/RootGcCandidates.java | 8 ++-- .../accumulo/manager/tableOps/TraceRepo.java | 5 +-- .../util/logging/AccumuloMonitorAppender.java | 6 +-- .../accumulo/test/CountNameNodeOpsBulkIT.java | 5 +-- 12 files changed, 75 insertions(+), 45 deletions(-) diff --git a/core/src/main/java/org/apache/accumulo/core/clientImpl/bulk/BulkSerialize.java b/core/src/main/java/org/apache/accumulo/core/clientImpl/bulk/BulkSerialize.java index 5c2771c3b5..bff210ee80 100644 --- a/core/src/main/java/org/apache/accumulo/core/clientImpl/bulk/BulkSerialize.java +++ b/core/src/main/java/org/apache/accumulo/core/clientImpl/bulk/BulkSerialize.java @@ -37,6 +37,7 @@ import org.apache.accumulo.core.clientImpl.bulk.Bulk.Files; import org.apache.accumulo.core.clientImpl.bulk.Bulk.Mapping; import org.apache.accumulo.core.data.TableId; import org.apache.accumulo.core.dataImpl.KeyExtent; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.core.util.json.ByteArrayToBase64TypeAdapter; import org.apache.hadoop.fs.Path; @@ -97,7 +98,7 @@ public class BulkSerialize { final Path renamingFile = new Path(bulkDir, Constants.BULK_RENAME_FILE); try (OutputStream fsOut = output.create(renamingFile); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fsOut))) { - new Gson().toJson(oldToNewNameMap, writer); + GsonSingleton.getInstance().toJson(oldToNewNameMap, writer); } } diff --git a/core/src/main/java/org/apache/accumulo/core/lock/ServiceLockData.java b/core/src/main/java/org/apache/accumulo/core/lock/ServiceLockData.java index 746d5b5ce5..ed624be642 100644 --- a/core/src/main/java/org/apache/accumulo/core/lock/ServiceLockData.java +++ b/core/src/main/java/org/apache/accumulo/core/lock/ServiceLockData.java @@ -29,14 +29,12 @@ import java.util.Set; import java.util.UUID; import org.apache.accumulo.core.util.AddressUtil; +import org.apache.accumulo.core.util.GsonSingleton; import com.google.common.net.HostAndPort; -import com.google.gson.Gson; public class ServiceLockData implements Comparable<ServiceLockData> { - private static final Gson gson = new Gson(); - /** * Thrift Service list */ @@ -119,7 +117,7 @@ public class ServiceLockData implements Comparable<ServiceLockData> { @Override public String toString() { - return gson.toJson(this); + return GsonSingleton.getInstance().toJson(this); } } @@ -195,7 +193,7 @@ public class ServiceLockData implements Comparable<ServiceLockData> { public byte[] serialize() { ServiceDescriptors sd = new ServiceDescriptors(); services.values().forEach(s -> sd.addService(s)); - return gson.toJson(sd).getBytes(UTF_8); + return GsonSingleton.getInstance().toJson(sd).getBytes(UTF_8); } @Override @@ -229,7 +227,8 @@ public class ServiceLockData implements Comparable<ServiceLockData> { if (data.isBlank()) { return Optional.empty(); } - return Optional.of(new ServiceLockData(gson.fromJson(data, ServiceDescriptors.class))); + return Optional.of( + new ServiceLockData(GsonSingleton.getInstance().fromJson(data, ServiceDescriptors.class))); } } diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionFinalState.java b/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionFinalState.java index 9212ccde9f..1ebf5c400c 100644 --- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionFinalState.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionFinalState.java @@ -22,16 +22,14 @@ import java.util.Base64; import org.apache.accumulo.core.data.TableId; import org.apache.accumulo.core.dataImpl.KeyExtent; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.core.util.TextUtil; import org.apache.hadoop.io.Text; import com.google.common.base.Preconditions; -import com.google.gson.Gson; public class ExternalCompactionFinalState { - private static final Gson GSON = new Gson(); - public enum FinalState { FINISHED, FAILED } @@ -123,11 +121,11 @@ public class ExternalCompactionFinalState { jd.fileSize = fileSize; jd.entries = fileEntries; jd.extent = new Extent(extent); - return GSON.toJson(jd); + return GsonSingleton.getInstance().toJson(jd); } public static ExternalCompactionFinalState fromJson(ExternalCompactionId ecid, String json) { - JsonData jd = GSON.fromJson(json, JsonData.class); + JsonData jd = GsonSingleton.getInstance().fromJson(json, JsonData.class); return new ExternalCompactionFinalState(ecid, jd.extent.toKeyExtent(), FinalState.valueOf(jd.state), jd.fileSize, jd.entries); } diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionMetadata.java b/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionMetadata.java index 2373160cfc..de617e5e03 100644 --- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionMetadata.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/ExternalCompactionMetadata.java @@ -29,15 +29,12 @@ import org.apache.accumulo.core.metadata.ReferencedTabletFile; import org.apache.accumulo.core.metadata.StoredTabletFile; import org.apache.accumulo.core.spi.compaction.CompactionExecutorId; import org.apache.accumulo.core.spi.compaction.CompactionKind; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.core.util.compaction.CompactionExecutorIdImpl; import org.apache.hadoop.fs.Path; -import com.google.gson.Gson; - public class ExternalCompactionMetadata { - private static final Gson GSON = new Gson(); - private final Set<StoredTabletFile> jobFiles; private final Set<StoredTabletFile> nextFiles; private final ReferencedTabletFile compactTmpName; @@ -140,11 +137,11 @@ public class ExternalCompactionMetadata { jData.propDels = propagateDeletes; jData.selectedAll = initiallySelectedAll; jData.compactionId = compactionId; - return GSON.toJson(jData); + return GsonSingleton.getInstance().toJson(jData); } public static ExternalCompactionMetadata fromJson(String json) { - GSonData jData = GSON.fromJson(json, GSonData.class); + GSonData jData = GsonSingleton.getInstance().fromJson(json, GSonData.class); return new ExternalCompactionMetadata( jData.inputs.stream().map(StoredTabletFile::new).collect(toSet()), diff --git a/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java b/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java index 3f01eed6c4..e0601f94a7 100644 --- a/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java +++ b/core/src/main/java/org/apache/accumulo/core/metadata/schema/RootTabletMetadata.java @@ -37,12 +37,11 @@ import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.metadata.RootTable; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.CurrentLocationColumnFamily; import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.FutureLocationColumnFamily; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.hadoop.io.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.Gson; - /** * This class is used to serialize and deserialize root tablet metadata using GSon. The only data * stored about the Root Table is the COLUMN_FAMILY, COLUMN_QUALIFIER and VALUE. @@ -93,12 +92,11 @@ public class RootTabletMetadata { } } - private final Gson gson = new Gson(); private final Data data; public RootTabletMetadata(String json) { log.trace("Creating root tablet metadata from stored JSON: {}", json); - this.data = gson.fromJson(json, Data.class); + this.data = GsonSingleton.getInstance().fromJson(json, Data.class); checkArgument(data.version == VERSION, "Invalid Root Table Metadata JSON version %s", data.version); data.columnValues.forEach((fam, qualVals) -> { @@ -164,7 +162,7 @@ public class RootTabletMetadata { * @return a JSON representation of the root tablet's data. */ public String toJson() { - return gson.toJson(data); + return GsonSingleton.getInstance().toJson(data); } } diff --git a/core/src/main/java/org/apache/accumulo/core/spi/compaction/DefaultCompactionPlanner.java b/core/src/main/java/org/apache/accumulo/core/spi/compaction/DefaultCompactionPlanner.java index 11feb5c60e..f8a0cbd90d 100644 --- a/core/src/main/java/org/apache/accumulo/core/spi/compaction/DefaultCompactionPlanner.java +++ b/core/src/main/java/org/apache/accumulo/core/spi/compaction/DefaultCompactionPlanner.java @@ -31,10 +31,10 @@ import java.util.Set; import org.apache.accumulo.core.client.admin.compaction.CompactableFile; import org.apache.accumulo.core.conf.ConfigurationTypeHelper; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.core.util.compaction.CompactionJobPrioritizer; import com.google.common.base.Preconditions; -import com.google.gson.Gson; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -145,8 +145,8 @@ public class DefaultCompactionPlanner implements CompactionPlanner { justification = "Field is written by Gson") @Override public void init(InitParameters params) { - ExecutorConfig[] execConfigs = - new Gson().fromJson(params.getOptions().get("executors"), ExecutorConfig[].class); + ExecutorConfig[] execConfigs = GsonSingleton.getInstance() + .fromJson(params.getOptions().get("executors"), ExecutorConfig[].class); List<Executor> tmpExec = new ArrayList<>(); diff --git a/core/src/main/java/org/apache/accumulo/core/spi/scan/ConfigurableScanServerSelector.java b/core/src/main/java/org/apache/accumulo/core/spi/scan/ConfigurableScanServerSelector.java index 2e792180cc..cb2848cef2 100644 --- a/core/src/main/java/org/apache/accumulo/core/spi/scan/ConfigurableScanServerSelector.java +++ b/core/src/main/java/org/apache/accumulo/core/spi/scan/ConfigurableScanServerSelector.java @@ -35,13 +35,13 @@ import java.util.function.Supplier; import org.apache.accumulo.core.conf.ConfigurationTypeHelper; import org.apache.accumulo.core.data.TabletId; +import org.apache.accumulo.core.util.GsonSingleton; import com.google.common.base.Preconditions; import com.google.common.base.Suppliers; import com.google.common.collect.Sets; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; -import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -263,9 +263,8 @@ public class ConfigurableScanServerSelector implements ScanServerSelector { private void parseProfiles(Map<String,String> options) { Type listType = new TypeToken<ArrayList<Profile>>() {}.getType(); - Gson gson = new Gson(); - List<Profile> profList = - gson.fromJson(options.getOrDefault("profiles", PROFILES_DEFAULT), listType); + List<Profile> profList = GsonSingleton.getInstance() + .fromJson(options.getOrDefault("profiles", PROFILES_DEFAULT), listType); profiles = new HashMap<>(); defaultProfile = null; diff --git a/core/src/main/java/org/apache/accumulo/core/util/GsonSingleton.java b/core/src/main/java/org/apache/accumulo/core/util/GsonSingleton.java new file mode 100644 index 0000000000..44c7369305 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/util/GsonSingleton.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * https://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 org.apache.accumulo.core.util; + +import com.google.gson.Gson; + +/** + * This class provides access to a shared instance of Gson that uses its default configuration. Gson + * is thread-safe, so it should be safe to create and reuse a single instance. + * <p> + * If you need to use a Gson instance that is configured differently, if you want to configure + * TypeAdapters for example, then you should not use this. You should construct your own instance of + * Gson. + */ +public class GsonSingleton { + private static Gson gsonInstance = null; + + private GsonSingleton() { + // private to prevent direct instantiation + } + + public static Gson getInstance() { + if (gsonInstance == null) { + gsonInstance = new Gson(); + } + return gsonInstance; + } +} diff --git a/server/base/src/main/java/org/apache/accumulo/server/metadata/RootGcCandidates.java b/server/base/src/main/java/org/apache/accumulo/server/metadata/RootGcCandidates.java index 95874fc2be..3627024b68 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/metadata/RootGcCandidates.java +++ b/server/base/src/main/java/org/apache/accumulo/server/metadata/RootGcCandidates.java @@ -27,15 +27,13 @@ import java.util.TreeSet; import java.util.stream.Stream; import org.apache.accumulo.core.metadata.StoredTabletFile; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.hadoop.fs.Path; -import com.google.gson.Gson; - public class RootGcCandidates { // Version 1. Released with Accumulo version 2.1.0 private static final int VERSION = 1; - private final Gson gson = new Gson(); private final Data data; // This class is used to serialize and deserialize root tablet metadata using GSon. Any changes to @@ -63,7 +61,7 @@ public class RootGcCandidates { } public RootGcCandidates(String jsonString) { - this.data = gson.fromJson(jsonString, Data.class); + this.data = GsonSingleton.getInstance().fromJson(jsonString, Data.class); checkArgument(data.version == VERSION, "Invalid Root Table GC Candidates JSON version %s", data.version); data.candidates.forEach((parent, files) -> { @@ -95,7 +93,7 @@ public class RootGcCandidates { } public String toJson() { - return gson.toJson(data); + return GsonSingleton.getInstance().toJson(data); } } diff --git a/server/manager/src/main/java/org/apache/accumulo/manager/tableOps/TraceRepo.java b/server/manager/src/main/java/org/apache/accumulo/manager/tableOps/TraceRepo.java index a97f9d27ff..5c9045a072 100644 --- a/server/manager/src/main/java/org/apache/accumulo/manager/tableOps/TraceRepo.java +++ b/server/manager/src/main/java/org/apache/accumulo/manager/tableOps/TraceRepo.java @@ -21,10 +21,9 @@ package org.apache.accumulo.manager.tableOps; import org.apache.accumulo.core.clientImpl.thrift.TInfo; import org.apache.accumulo.core.fate.Repo; import org.apache.accumulo.core.trace.TraceUtil; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.manager.Manager; -import com.google.gson.Gson; - import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; @@ -106,6 +105,6 @@ public class TraceRepo<T> implements Repo<T> { // Inorder for Gson to work with generic types, the following passes repo.getClass() to Gson. // See the Gson javadoc for more info. - return repo.getClass() + " " + new Gson().toJson(repo, repo.getClass()); + return repo.getClass() + " " + GsonSingleton.getInstance().toJson(repo, repo.getClass()); } } diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/util/logging/AccumuloMonitorAppender.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/util/logging/AccumuloMonitorAppender.java index 7dfde0f3fa..ed14bb4f7d 100644 --- a/server/monitor/src/main/java/org/apache/accumulo/monitor/util/logging/AccumuloMonitorAppender.java +++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/util/logging/AccumuloMonitorAppender.java @@ -33,6 +33,7 @@ import java.util.function.Supplier; import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.conf.SiteConfiguration; import org.apache.accumulo.core.fate.zookeeper.ZooCache.ZcStat; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.core.util.Pair; import org.apache.accumulo.monitor.rest.logs.LogResource; import org.apache.accumulo.monitor.rest.logs.SingleLogEvent; @@ -46,8 +47,6 @@ import org.apache.logging.log4j.core.config.Property; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; -import com.google.gson.Gson; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -75,7 +74,6 @@ public class AccumuloMonitorAppender extends AbstractAppender { } - private final Gson gson = new Gson(); private final HttpClient httpClient = HttpClient.newHttpClient(); private final Supplier<Optional<URI>> monitorLocator; @@ -118,7 +116,7 @@ public class AccumuloMonitorAppender extends AbstractAppender { pojo.message = event.getMessage().getFormattedMessage(); pojo.stacktrace = throwableToStacktrace(event.getThrown()); - String jsonEvent = gson.toJson(pojo); + String jsonEvent = GsonSingleton.getInstance().toJson(pojo); var req = HttpRequest.newBuilder(uri).POST(BodyPublishers.ofString(jsonEvent, UTF_8)) .setHeader("Content-Type", "application/json").build(); diff --git a/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java b/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java index 4efdc52d22..10f01dfc14 100644 --- a/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java +++ b/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java @@ -46,6 +46,7 @@ import org.apache.accumulo.core.file.rfile.RFile; import org.apache.accumulo.core.manager.thrift.ManagerMonitorInfo; import org.apache.accumulo.core.metadata.UnreferencedTabletFile; import org.apache.accumulo.core.spi.crypto.NoCryptoServiceFactory; +import org.apache.accumulo.core.util.GsonSingleton; import org.apache.accumulo.minicluster.ServerType; import org.apache.accumulo.miniclusterImpl.MiniAccumuloConfigImpl; import org.apache.accumulo.test.functional.ConfigurableMacBase; @@ -56,8 +57,6 @@ import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.Text; import org.junit.jupiter.api.Test; -import com.google.gson.Gson; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** @@ -79,7 +78,7 @@ public class CountNameNodeOpsBulkIT extends ConfigurableMacBase { URL url = new URL(uri + "/jmx"); log.debug("Fetching web page " + url); String jsonString = FunctionalTestUtils.readWebPage(url).body(); - Map<?,?> jsonObject = new Gson().fromJson(jsonString, Map.class); + Map<?,?> jsonObject = GsonSingleton.getInstance().fromJson(jsonString, Map.class); List<?> beans = (List<?>) jsonObject.get("beans"); for (Object bean : beans) { Map<?,?> map = (Map<?,?>) bean;