This is an automated email from the ASF dual-hosted git repository. ctubbsii 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 838e6f477b Make instantiating Gson singletons easier (#3531) 838e6f477b is described below commit 838e6f477ba0ea1ecd6d4efe5f79267f6ecdb298 Author: Christopher Tubbs <ctubb...@apache.org> AuthorDate: Fri Jun 23 17:12:59 2023 -0400 Make instantiating Gson singletons easier (#3531) * Create LazySingletons class to host singleton suppliers * Add lazy GSON singleton supplier * Replace GsonSingleton class from #3516 with this --- .../core/clientImpl/bulk/BulkSerialize.java | 4 +-- .../apache/accumulo/core/lock/ServiceLockData.java | 9 +++---- .../schema/ExternalCompactionFinalState.java | 7 ++--- .../schema/ExternalCompactionMetadata.java | 6 ++--- .../core/metadata/schema/RootTabletMetadata.java | 6 ++--- .../spi/compaction/DefaultCompactionPlanner.java | 7 ++--- .../spi/scan/ConfigurableScanServerSelector.java | 6 ++--- .../{GsonSingleton.java => LazySingletons.java} | 30 ++++++++++------------ pom.xml | 4 +++ .../accumulo/server/metadata/RootGcCandidates.java | 6 ++--- .../accumulo/manager/tableOps/TraceRepo.java | 5 ++-- .../util/logging/AccumuloMonitorAppender.java | 4 +-- .../accumulo/test/CountNameNodeOpsBulkIT.java | 4 +-- 13 files changed, 50 insertions(+), 48 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 bff210ee80..533a43c237 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 @@ -19,6 +19,7 @@ package org.apache.accumulo.core.clientImpl.bulk; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -37,7 +38,6 @@ 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; @@ -98,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))) { - GsonSingleton.getInstance().toJson(oldToNewNameMap, writer); + GSON.get().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 ed624be642..736a36f0fe 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 @@ -20,6 +20,7 @@ package org.apache.accumulo.core.lock; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Objects.requireNonNull; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.util.Collections; import java.util.EnumMap; @@ -29,7 +30,6 @@ 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; @@ -117,7 +117,7 @@ public class ServiceLockData implements Comparable<ServiceLockData> { @Override public String toString() { - return GsonSingleton.getInstance().toJson(this); + return GSON.get().toJson(this); } } @@ -193,7 +193,7 @@ public class ServiceLockData implements Comparable<ServiceLockData> { public byte[] serialize() { ServiceDescriptors sd = new ServiceDescriptors(); services.values().forEach(s -> sd.addService(s)); - return GsonSingleton.getInstance().toJson(sd).getBytes(UTF_8); + return GSON.get().toJson(sd).getBytes(UTF_8); } @Override @@ -227,8 +227,7 @@ public class ServiceLockData implements Comparable<ServiceLockData> { if (data.isBlank()) { return Optional.empty(); } - return Optional.of( - new ServiceLockData(GsonSingleton.getInstance().fromJson(data, ServiceDescriptors.class))); + return Optional.of(new ServiceLockData(GSON.get().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 1ebf5c400c..421a707d75 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 @@ -18,11 +18,12 @@ */ package org.apache.accumulo.core.metadata.schema; +import static org.apache.accumulo.core.util.LazySingletons.GSON; + 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; @@ -121,11 +122,11 @@ public class ExternalCompactionFinalState { jd.fileSize = fileSize; jd.entries = fileEntries; jd.extent = new Extent(extent); - return GsonSingleton.getInstance().toJson(jd); + return GSON.get().toJson(jd); } public static ExternalCompactionFinalState fromJson(ExternalCompactionId ecid, String json) { - JsonData jd = GsonSingleton.getInstance().fromJson(json, JsonData.class); + JsonData jd = GSON.get().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 de617e5e03..5eef8c3d5d 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 @@ -20,6 +20,7 @@ package org.apache.accumulo.core.metadata.schema; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.util.List; import java.util.Objects; @@ -29,7 +30,6 @@ 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; @@ -137,11 +137,11 @@ public class ExternalCompactionMetadata { jData.propDels = propagateDeletes; jData.selectedAll = initiallySelectedAll; jData.compactionId = compactionId; - return GsonSingleton.getInstance().toJson(jData); + return GSON.get().toJson(jData); } public static ExternalCompactionMetadata fromJson(String json) { - GSonData jData = GsonSingleton.getInstance().fromJson(json, GSonData.class); + GSonData jData = GSON.get().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 e0601f94a7..7ea03a19a4 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 @@ -20,6 +20,7 @@ package org.apache.accumulo.core.metadata.schema; import static com.google.common.base.Preconditions.checkArgument; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.nio.ByteBuffer; import java.nio.charset.CharacterCodingException; @@ -37,7 +38,6 @@ 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; @@ -96,7 +96,7 @@ public class RootTabletMetadata { public RootTabletMetadata(String json) { log.trace("Creating root tablet metadata from stored JSON: {}", json); - this.data = GsonSingleton.getInstance().fromJson(json, Data.class); + this.data = GSON.get().fromJson(json, Data.class); checkArgument(data.version == VERSION, "Invalid Root Table Metadata JSON version %s", data.version); data.columnValues.forEach((fam, qualVals) -> { @@ -162,7 +162,7 @@ public class RootTabletMetadata { * @return a JSON representation of the root tablet's data. */ public String toJson() { - return GsonSingleton.getInstance().toJson(data); + return GSON.get().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 f8a0cbd90d..1b5b662957 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 @@ -18,6 +18,8 @@ */ package org.apache.accumulo.core.spi.compaction; +import static org.apache.accumulo.core.util.LazySingletons.GSON; + import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -31,7 +33,6 @@ 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; @@ -145,8 +146,8 @@ public class DefaultCompactionPlanner implements CompactionPlanner { justification = "Field is written by Gson") @Override public void init(InitParameters params) { - ExecutorConfig[] execConfigs = GsonSingleton.getInstance() - .fromJson(params.getOptions().get("executors"), ExecutorConfig[].class); + ExecutorConfig[] execConfigs = + GSON.get().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 cb2848cef2..a90936832c 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 @@ -19,6 +19,7 @@ package org.apache.accumulo.core.spi.scan; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.lang.reflect.Type; import java.security.SecureRandom; @@ -35,7 +36,6 @@ 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; @@ -263,8 +263,8 @@ public class ConfigurableScanServerSelector implements ScanServerSelector { private void parseProfiles(Map<String,String> options) { Type listType = new TypeToken<ArrayList<Profile>>() {}.getType(); - List<Profile> profList = GsonSingleton.getInstance() - .fromJson(options.getOrDefault("profiles", PROFILES_DEFAULT), listType); + List<Profile> profList = + GSON.get().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/LazySingletons.java similarity index 56% rename from core/src/main/java/org/apache/accumulo/core/util/GsonSingleton.java rename to core/src/main/java/org/apache/accumulo/core/util/LazySingletons.java index 44c7369305..ac476cc687 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/GsonSingleton.java +++ b/core/src/main/java/org/apache/accumulo/core/util/LazySingletons.java @@ -18,27 +18,23 @@ */ package org.apache.accumulo.core.util; +import java.util.function.Supplier; + +import com.google.common.base.Suppliers; 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. + * This class provides easy access to global, immutable, lazily-instantiated, and thread-safe + * singleton resources. These should be used with static imports. */ -public class GsonSingleton { - private static Gson gsonInstance = null; +public class LazySingletons { + + // prevent instantiating this utility class + private LazySingletons() {} - private GsonSingleton() { - // private to prevent direct instantiation - } + /** + * A Gson instance constructed with defaults. Construct your own if you need custom settings. + */ + public static final Supplier<Gson> GSON = Suppliers.memoize(Gson::new); - public static Gson getInstance() { - if (gsonInstance == null) { - gsonInstance = new Gson(); - } - return gsonInstance; - } } diff --git a/pom.xml b/pom.xml index ad11c9e535..6d2275bef7 100644 --- a/pom.xml +++ b/pom.xml @@ -1144,6 +1144,10 @@ <property name="format" value="junit[.]framework[.]TestCase" /> <property name="message" value="Use JUnit4+ @Test annotation instead of TestCase" /> </module> + <module name="RegexpSinglelineJava"> + <property name="format" value="import org[.]apache[.]accumulo[.]core[.]util[.]LazySingletons;" /> + <property name="message" value="Use static imports for LazySingletons for consistency" /> + </module> <module name="RegexpSinglelineJava"> <property name="format" value="import org[.]junit[.]Assert;" /> <property name="message" value="Use static imports for Assert.* methods for consistency" /> 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 3627024b68..e65813fd4c 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 @@ -19,6 +19,7 @@ package org.apache.accumulo.server.metadata; import static com.google.common.base.Preconditions.checkArgument; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.util.SortedMap; import java.util.SortedSet; @@ -27,7 +28,6 @@ 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; public class RootGcCandidates { @@ -61,7 +61,7 @@ public class RootGcCandidates { } public RootGcCandidates(String jsonString) { - this.data = GsonSingleton.getInstance().fromJson(jsonString, Data.class); + this.data = GSON.get().fromJson(jsonString, Data.class); checkArgument(data.version == VERSION, "Invalid Root Table GC Candidates JSON version %s", data.version); data.candidates.forEach((parent, files) -> { @@ -93,7 +93,7 @@ public class RootGcCandidates { } public String toJson() { - return GsonSingleton.getInstance().toJson(data); + return GSON.get().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 5c9045a072..752bc90d44 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 @@ -18,10 +18,11 @@ */ package org.apache.accumulo.manager.tableOps; +import static org.apache.accumulo.core.util.LazySingletons.GSON; + 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 io.opentelemetry.api.trace.Span; @@ -105,6 +106,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() + " " + GsonSingleton.getInstance().toJson(repo, repo.getClass()); + return repo.getClass() + " " + GSON.get().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 ed14bb4f7d..dce3917910 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 @@ -19,6 +19,7 @@ package org.apache.accumulo.monitor.util.logging; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import java.io.PrintWriter; import java.io.StringWriter; @@ -33,7 +34,6 @@ 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; @@ -116,7 +116,7 @@ public class AccumuloMonitorAppender extends AbstractAppender { pojo.message = event.getMessage().getFormattedMessage(); pojo.stacktrace = throwableToStacktrace(event.getThrown()); - String jsonEvent = GsonSingleton.getInstance().toJson(pojo); + String jsonEvent = GSON.get().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 10f01dfc14..ba9bf2edbd 100644 --- a/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java +++ b/test/src/main/java/org/apache/accumulo/test/CountNameNodeOpsBulkIT.java @@ -20,6 +20,7 @@ package org.apache.accumulo.test; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; +import static org.apache.accumulo.core.util.LazySingletons.GSON; import static org.junit.jupiter.api.Assertions.assertEquals; import java.net.URL; @@ -46,7 +47,6 @@ 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; @@ -78,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 = GsonSingleton.getInstance().fromJson(jsonString, Map.class); + Map<?,?> jsonObject = GSON.get().fromJson(jsonString, Map.class); List<?> beans = (List<?>) jsonObject.get("beans"); for (Object bean : beans) { Map<?,?> map = (Map<?,?>) bean;