This is an automated email from the ASF dual-hosted git repository.
He-Pin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git
The following commit(s) were added to refs/heads/main by this push:
new 6ad445271c refactor: use StandardCharsets.UTF_8 with
URLEncoder/URLDecoder (#3147)
6ad445271c is described below
commit 6ad445271cb756d7bee92166d4064d1f79115c9c
Author: He-Pin(kerr) <[email protected]>
AuthorDate: Tue Jun 23 18:44:03 2026 +0800
refactor: use StandardCharsets.UTF_8 with URLEncoder/URLDecoder (#3147)
* refactor: use StandardCharsets.UTF_8 with URLEncoder/URLDecoder
Motivation:
Multiple files pass charset as a String ("utf-8") or via
ByteString.UTF_8 (which is StandardCharsets.UTF_8.name()) to
URLEncoder.encode and URLDecoder.decode. JDK 10 added overloads
that accept a Charset object directly, avoiding the checked
UnsupportedEncodingException declaration.
Modification:
Replace "utf-8" and ByteString.UTF_8 string arguments with
StandardCharsets.UTF_8 Charset object in 17 call sites across
8 files. Remove 4 unused ByteString imports.
Result:
Type-safe charset specification, no UnsupportedEncodingException
declaration needed, removes ByteString dependency where it was
only used for charset name constants.
Tests:
sbt "cluster-sharding/compile" "cluster-sharding-typed/compile"
"cluster-tools/compile" "persistence-query/compile"
"stream/compile" — all passed
References:
Refs #3136
* refactor: also migrate URLEncoder/URLDecoder in actor/remote/persistence
Motivation:
Initial PR only covered cluster-sharding, cluster-sharding-typed,
cluster-tools, persistence-query, and stream modules. Internal review
identified three additional production sites that still passed
`ByteString.UTF_8` (a `String = "UTF-8"` alias) or
`import pekko.util.ByteString.UTF_8` to `URLEncoder.encode` /
`URLDecoder.decode`:
- `actor/src/main/.../pattern/AskSupport.scala` — used on every
`?`/ask call to encode the actor path prefix into the temporary
actor name.
- `remote/src/main/.../Remoting.scala` — `AddressUrlEncoder` used
when encoding remote addresses for logging and transport.
- `persistence/src/main/.../snapshot/local/LocalSnapshotStore.scala`
— used for snapshot file name encoding/decoding. Two neighboring
sites (lines 200, 211) intentionally retain
`defaultSystemEncoding` for backwards compatibility with existing
on-disk snapshot files and are left untouched.
Modification:
Replace `ByteString.UTF_8` / `pekko.util.ByteString.UTF_8` with
`java.nio.charset.StandardCharsets.UTF_8` (the JDK `Charset` object
overload of `URLEncoder.encode` / `URLDecoder.decode`, available
since JDK 10). Remove the now-unused `ByteString` imports.
Result:
All production `URLEncoder`/`URLDecoder` call sites now use the
`Charset`-typed overload, eliminating the per-call
`Charset.forName("UTF-8")` lookup and removing dead
`UnsupportedEncodingException` declarations.
Tests:
sbt "actor/compile" "remote/compile" "persistence/compile"
"cluster-sharding/compile" "cluster-tools/compile"
"cluster-sharding-typed/compile" "persistence-query/compile" --
all passed.
References:
Discovered during internal review of PR #3147.
---
.../main/scala/org/apache/pekko/pattern/AskSupport.scala | 7 ++++---
.../sharding/typed/internal/ClusterShardingImpl.scala | 7 ++++---
.../apache/pekko/cluster/sharding/ClusterSharding.scala | 14 +++++++-------
.../scala/org/apache/pekko/cluster/sharding/Shard.scala | 3 ++-
.../org/apache/pekko/cluster/sharding/ShardRegion.scala | 3 ++-
.../org/apache/pekko/cluster/client/ClusterClient.scala | 3 ++-
.../pekko/cluster/pubsub/DistributedPubSubMediator.scala | 5 +++--
.../journal/leveldb/scaladsl/LeveldbReadJournal.scala | 6 +++---
.../persistence/snapshot/local/LocalSnapshotStore.scala | 6 +++---
.../src/main/scala/org/apache/pekko/remote/Remoting.scala | 4 ++--
.../main/scala/org/apache/pekko/stream/Attributes.scala | 4 ++--
11 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
index 8c85c4eff0..b3d8333505 100644
--- a/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
+++ b/actor/src/main/scala/org/apache/pekko/pattern/AskSupport.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.pattern
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.util.concurrent.TimeoutException
import scala.annotation.{ nowarn, tailrec }
@@ -28,7 +29,7 @@ import org.apache.pekko
import pekko.actor._
import pekko.annotation.{ InternalApi, InternalStableApi }
import pekko.dispatch.sysmsg._
-import pekko.util.{ ByteString, Timeout }
+import pekko.util.Timeout
/**
* This is what is used to complete a Future that is returned from an ask/?
call,
@@ -457,7 +458,7 @@ final class AskableActorSelection(val actorSel:
ActorSelection) extends AnyVal {
if (timeout.duration.length <= 0)
Future.failed[Any](AskableActorRef.negativeTimeoutException(actorSel, message,
sender))
else {
- val refPrefix = URLEncoder.encode(actorSel.pathString.replace("/",
"_"), ByteString.UTF_8)
+ val refPrefix = URLEncoder.encode(actorSel.pathString.replace("/",
"_"), StandardCharsets.UTF_8)
PromiseActorRef(ref.provider, timeout, targetName = actorSel,
message.getClass.getName, refPrefix, sender)
.ask(actorSel, message, timeout)
}
@@ -486,7 +487,7 @@ final class ExplicitlyAskableActorSelection(val actorSel:
ActorSelection) extend
val message = messageFactory(ref.provider.deadLetters)
Future.failed[Any](AskableActorRef.negativeTimeoutException(actorSel, message,
sender))
} else {
- val refPrefix = URLEncoder.encode(actorSel.pathString.replace("/",
"_"), ByteString.UTF_8)
+ val refPrefix = URLEncoder.encode(actorSel.pathString.replace("/",
"_"), StandardCharsets.UTF_8)
val a = PromiseActorRef(ref.provider, timeout, targetName =
actorSel, "unknown", refPrefix, sender)
val message = messageFactory(a)
a.messageClassName = message.getClass.getName
diff --git
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/internal/ClusterShardingImpl.scala
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/internal/ClusterShardingImpl.scala
index df01f21032..1794da8b86 100644
---
a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/internal/ClusterShardingImpl.scala
+++
b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/internal/ClusterShardingImpl.scala
@@ -15,6 +15,7 @@ package org.apache.pekko.cluster.sharding.typed
package internal
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.time.Duration
import java.util.concurrent.CompletionStage
import java.util.concurrent.ConcurrentHashMap
@@ -52,7 +53,7 @@ import pekko.japi.function.{ Function => JFunction }
import pekko.pattern.AskTimeoutException
import pekko.pattern.PromiseActorRef
import pekko.pattern.StatusReply
-import pekko.util.{ ByteString, Timeout }
+import pekko.util.Timeout
/**
* INTERNAL API
@@ -196,7 +197,7 @@ import pekko.util.{ ByteString, Timeout }
override def apply(t: String):
ActorRef[scaladsl.ClusterSharding.ShardCommand] = {
system.systemActorOf(
ShardCommandActor.behavior(stopMessage.getOrElse(PoisonPill)),
- URLEncoder.encode(typeKey.name, ByteString.UTF_8) +
"ShardCommandDelegator")
+ URLEncoder.encode(typeKey.name, StandardCharsets.UTF_8) +
"ShardCommandDelegator")
}
})
@@ -334,7 +335,7 @@ import pekko.util.{ ByteString, Timeout }
case _ => false
}
- override val refPrefix = URLEncoder.encode(s"${typeKey.name}-$entityId",
ByteString.UTF_8)
+ override val refPrefix = URLEncoder.encode(s"${typeKey.name}-$entityId",
StandardCharsets.UTF_8)
override def tell(msg: M): Unit =
shardRegion ! ShardingEnvelope(entityId, msg)
diff --git
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterSharding.scala
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterSharding.scala
index bb393b299a..d22984c178 100755
---
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterSharding.scala
+++
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ClusterSharding.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.cluster.sharding
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.util.Optional
import java.util.concurrent.ConcurrentHashMap
@@ -50,7 +51,6 @@ import pekko.cluster.singleton.ClusterSingletonManager
import pekko.event.Logging
import pekko.pattern.BackoffOpts
import pekko.pattern.ask
-import pekko.util.ByteString
/**
* This extension provides sharding functionality of actors in a cluster.
@@ -754,7 +754,7 @@ private[pekko] class ClusterShardingGuardian extends Actor {
case Some(ref) => ref
case None =>
val name = role match {
- case Some(r) => URLEncoder.encode(r, ByteString.UTF_8) + "Replicator"
+ case Some(r) => URLEncoder.encode(r, StandardCharsets.UTF_8) +
"Replicator"
case None => "replicator"
}
val ref = context.actorOf(Replicator.props(replicatorSettings(role,
settings)), name)
@@ -799,7 +799,7 @@ private[pekko] class ClusterShardingGuardian extends Actor {
settings: ClusterShardingSettings): Unit = {
import settings.tuningParameters.coordinatorFailureBackoff
- val encName = URLEncoder.encode(typeName, ByteString.UTF_8)
+ val encName = URLEncoder.encode(typeName, StandardCharsets.UTF_8)
val cName = coordinatorSingletonManagerName(encName)
if (settings.shouldHostCoordinator(cluster) &&
context.child(cName).isEmpty) {
val coordinatorProps =
@@ -848,7 +848,7 @@ private[pekko] class ClusterShardingGuardian extends Actor {
allocationStrategy,
handOffStopMessage) =>
try {
- val encName = URLEncoder.encode(typeName, ByteString.UTF_8)
+ val encName = URLEncoder.encode(typeName, StandardCharsets.UTF_8)
val cPath = coordinatorPath(encName)
val shardRegion = context.child(encName).getOrElse {
val remEntitiesStoreProvider =
rememberEntitiesStoreProvider(typeName, settings)
@@ -880,12 +880,12 @@ private[pekko] class ClusterShardingGuardian extends
Actor {
case StartProxy(typeName, dataCenter, settings, extractEntityId,
extractShardId) =>
try {
- val encName = URLEncoder.encode(s"${typeName}Proxy", ByteString.UTF_8)
- val cPath = coordinatorPath(URLEncoder.encode(typeName,
ByteString.UTF_8))
+ val encName = URLEncoder.encode(s"${typeName}Proxy",
StandardCharsets.UTF_8)
+ val cPath = coordinatorPath(URLEncoder.encode(typeName,
StandardCharsets.UTF_8))
// it must be possible to start several proxies, one per data center
val actorName = dataCenter match {
case None => encName
- case Some(t) => URLEncoder.encode(typeName + "-" + t,
ByteString.UTF_8)
+ case Some(t) => URLEncoder.encode(typeName + "-" + t,
StandardCharsets.UTF_8)
}
val shardRegion = context.child(actorName).getOrElse {
context.actorOf(
diff --git
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/Shard.scala
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/Shard.scala
index 2d4b1165db..b45ba8e870 100644
---
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/Shard.scala
+++
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/Shard.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.cluster.sharding
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.util
import scala.annotation.nowarn
@@ -1128,7 +1129,7 @@ private[pekko] class Shard(
entities.entity(id) match {
case OptionVal.Some(child) => child
case _ =>
- val name = URLEncoder.encode(id, "utf-8")
+ val name = URLEncoder.encode(id, StandardCharsets.UTF_8)
val a = context.actorOf(entityProps(id), name)
context.watchWith(a, EntityTerminated(a))
log.debug("{}: Started entity [{}] with entity id [{}] in shard [{}]",
typeName, a, id, shardId)
diff --git
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
index 86dd77d8c5..b5bd7f5cc5 100644
---
a/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
+++
b/cluster-sharding/src/main/scala/org/apache/pekko/cluster/sharding/ShardRegion.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.cluster.sharding
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import scala.annotation.tailrec
import scala.collection.immutable
@@ -1341,7 +1342,7 @@ private[pekko] class ShardRegion(
.orElse(entityProps match {
case Some(props) if !shardsByRef.values.exists(_ == id) =>
log.debug(ShardingLogMarker.shardStarted(typeName, id), "{}:
Starting shard [{}] in region", typeName, id)
- val name = URLEncoder.encode(id, "utf-8")
+ val name = URLEncoder.encode(id, StandardCharsets.UTF_8)
val shard = context.watch(
context.actorOf(
Shard
diff --git
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
index 1b617b9f13..8e787a14bf 100644
---
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
+++
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/client/ClusterClient.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.cluster.client
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import scala.collection.immutable
import scala.collection.immutable.{ HashMap, HashSet }
@@ -1007,7 +1008,7 @@ final class ClusterReceptionist(pubSubMediator: ActorRef,
settings: ClusterRecep
def matchingRole(m: Member): Boolean = role.forall(m.hasRole)
def responseTunnel(client: ActorRef): ActorRef = {
- val encName = URLEncoder.encode(client.path.toSerializationFormat, "utf-8")
+ val encName = URLEncoder.encode(client.path.toSerializationFormat,
StandardCharsets.UTF_8)
context.child(encName) match {
case Some(tunnel) => tunnel
case None =>
diff --git
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
index 09dfef508c..11dadf53fb 100644
---
a/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
+++
b/cluster-tools/src/main/scala/org/apache/pekko/cluster/pubsub/DistributedPubSubMediator.scala
@@ -15,6 +15,7 @@ package org.apache.pekko.cluster.pubsub
import java.net.URLDecoder
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.util.concurrent.ThreadLocalRandom
import scala.collection.immutable
@@ -341,7 +342,7 @@ object DistributedPubSubMediator {
override def message = msg
}
- def encName(s: String) = URLEncoder.encode(s, "utf-8")
+ def encName(s: String) = URLEncoder.encode(s, StandardCharsets.UTF_8)
def mkKey(ref: ActorRef): String = mkKey(ref.path)
@@ -845,7 +846,7 @@ class DistributedPubSubMediator(settings:
DistributedPubSubSettings)
if key.startsWith(topicPrefix)
topic = key.substring(topicPrefix.length + 1)
if !topic.contains('/') // exclude group topics
- } yield URLDecoder.decode(topic, "utf-8")).toSet
+ } yield URLDecoder.decode(topic, StandardCharsets.UTF_8)).toSet
}
def registerTopic(ref: ActorRef): Unit = {
diff --git
a/persistence-query/src/main/scala/org/apache/pekko/persistence/query/journal/leveldb/scaladsl/LeveldbReadJournal.scala
b/persistence-query/src/main/scala/org/apache/pekko/persistence/query/journal/leveldb/scaladsl/LeveldbReadJournal.scala
index e5aeb0032d..39db8071d9 100644
---
a/persistence-query/src/main/scala/org/apache/pekko/persistence/query/journal/leveldb/scaladsl/LeveldbReadJournal.scala
+++
b/persistence-query/src/main/scala/org/apache/pekko/persistence/query/journal/leveldb/scaladsl/LeveldbReadJournal.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.persistence.query.journal.leveldb.scaladsl
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import scala.concurrent.duration._
@@ -31,7 +32,6 @@ import
pekko.persistence.query.journal.leveldb.EventsByTagStage
import pekko.persistence.query.scaladsl._
import pekko.persistence.query.scaladsl.ReadJournal
import pekko.stream.scaladsl.Source
-import pekko.util.ByteString
import com.typesafe.config.Config
@@ -245,7 +245,7 @@ class LeveldbReadJournal(system: ExtendedActorSystem,
config: Config)
writeJournalPluginId,
refreshInterval,
mat))
- .named("eventsByTag-" + URLEncoder.encode(tag, ByteString.UTF_8))
+ .named("eventsByTag-" + URLEncoder.encode(tag,
StandardCharsets.UTF_8))
case NoOffset => eventsByTag(tag, Sequence(0L)) // recursive
case _ =>
@@ -268,7 +268,7 @@ class LeveldbReadJournal(system: ExtendedActorSystem,
config: Config)
Source
.fromGraph(
new EventsByTagStage(tag, seq.value, maxBufSize,
Long.MaxValue, writeJournalPluginId, None, mat))
- .named("currentEventsByTag-" + URLEncoder.encode(tag,
ByteString.UTF_8))
+ .named("currentEventsByTag-" + URLEncoder.encode(tag,
StandardCharsets.UTF_8))
case NoOffset => currentEventsByTag(tag, Sequence(0L))
case _ =>
throw new IllegalArgumentException(
diff --git
a/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/local/LocalSnapshotStore.scala
b/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/local/LocalSnapshotStore.scala
index f2aff5d56b..aa6082fc9d 100644
---
a/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/local/LocalSnapshotStore.scala
+++
b/persistence/src/main/scala/org/apache/pekko/persistence/snapshot/local/LocalSnapshotStore.scala
@@ -15,6 +15,7 @@ package org.apache.pekko.persistence.snapshot.local
import java.io._
import java.net.{ URLDecoder, URLEncoder }
+import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.NoSuchFileException
@@ -28,7 +29,6 @@ import pekko.persistence._
import pekko.persistence.serialization._
import pekko.persistence.snapshot._
import pekko.serialization.SerializationExtension
-import pekko.util.ByteString.UTF_8
import com.typesafe.config.Config
@@ -158,7 +158,7 @@ private[persistence] class LocalSnapshotStore(config:
Config) extends SnapshotSt
protected def snapshotFileForWrite(metadata: SnapshotMetadata, extension:
String = ""): File =
new File(
snapshotDir(),
- s"snapshot-${URLEncoder.encode(metadata.persistenceId,
UTF_8)}-${metadata.sequenceNr}-${metadata.timestamp}$extension")
+ s"snapshot-${URLEncoder.encode(metadata.persistenceId,
StandardCharsets.UTF_8)}-${metadata.sequenceNr}-${metadata.timestamp}$extension")
private def snapshotMetadatas(
persistenceId: String,
@@ -170,7 +170,7 @@ private[persistence] class LocalSnapshotStore(config:
Config) extends SnapshotSt
.map(_.getName)
.flatMap { filename =>
extractMetadata(filename).map {
- case (pid, snr, tms) => SnapshotMetadata(URLDecoder.decode(pid,
UTF_8), snr, tms)
+ case (pid, snr, tms) => SnapshotMetadata(URLDecoder.decode(pid,
StandardCharsets.UTF_8), snr, tms)
}
}
.filter(md => criteria.matches(md) && !saving.contains(md))
diff --git a/remote/src/main/scala/org/apache/pekko/remote/Remoting.scala
b/remote/src/main/scala/org/apache/pekko/remote/Remoting.scala
index ef6e78f8ac..2aca007491 100644
--- a/remote/src/main/scala/org/apache/pekko/remote/Remoting.scala
+++ b/remote/src/main/scala/org/apache/pekko/remote/Remoting.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.remote
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeoutException
@@ -39,7 +40,6 @@ import pekko.remote.Remoting.TransportSupervisor
import pekko.remote.transport._
import pekko.remote.transport.PekkoPduCodec.Message
import pekko.remote.transport.Transport.{ ActorAssociationEventListener,
AssociationEventListener, InboundAssociation }
-import pekko.util.ByteString.UTF_8
import pekko.util.OptionVal
import com.typesafe.config.Config
@@ -48,7 +48,7 @@ import com.typesafe.config.Config
* INTERNAL API
*/
private[remote] object AddressUrlEncoder {
- def apply(address: Address): String = URLEncoder.encode(address.toString,
UTF_8)
+ def apply(address: Address): String = URLEncoder.encode(address.toString,
StandardCharsets.UTF_8)
}
/**
diff --git a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
index 4f6d346c31..5cb9235886 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
@@ -14,6 +14,7 @@
package org.apache.pekko.stream
import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
import java.time.Duration
import java.util.Optional
@@ -33,7 +34,6 @@ import pekko.annotation.InternalApi
import pekko.event.Logging
import pekko.japi.function
import pekko.stream.impl.TraversalBuilder
-import pekko.util.ByteString
import pekko.util.Helpers
import pekko.util.LineNumbers
@@ -242,7 +242,7 @@ final class Attributes private[pekko] (
}
@InternalApi private[pekko] def nameForActorRef(default: String =
"unnamed"): String = {
- getName().map(name => URLEncoder.encode(name,
ByteString.UTF_8)).getOrElse(default)
+ getName().map(name => URLEncoder.encode(name,
StandardCharsets.UTF_8)).getOrElse(default)
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]