This is an automated email from the ASF dual-hosted git repository. He-Pin pushed a commit to branch add-jspecify-remaining-modules in repository https://gitbox.apache.org/repos/asf/pekko.git
commit 06e1db7a02b506d3e57db948827197a99e4e6077 Author: 虎鸣 <[email protected]> AuthorDate: Sat Jul 25 22:07:49 2026 +0800 feat: add jspecify null-safety annotations to actor-typed, cluster-sharding-typed, and testkit javadsl Motivation: Extend jspecify coverage to remaining Java DSL modules (#2563), following the pattern established in streams (#2617) and persistence (#2850). Modification: - Add @NullMarked package-info.java for actor-typed, cluster-sharding-typed, and testkit javadsl packages - Add @Nullable to Behaviors.withMdc staticMdc and mdcForMessage parameters (both explicitly checked for null in implementation) - Add @Nullable to Entity.with* methods in ClusterSharding (all wrapped in Optional.ofNullable, explicitly accepting null) - Add jspecify dependency to actorTyped, testkit, and clusterShardingTyped modules Result: Java consumers get null-safety signals via JSpecify annotations for actor-typed, cluster-sharding-typed, and testkit Java DSLs. Tests: - sbt actor-typed/compile testkit/compile cluster-sharding-typed/compile - sbt actor-typed-tests/testOnly org.apache.pekko.actor.typed.javadsl.* - sbt actor-typed/mimaReportBinaryIssues testkit/mimaReportBinaryIssues cluster-sharding-typed/mimaReportBinaryIssues - sbt actor-typed/headerCheck testkit/headerCheck cluster-sharding-typed/headerCheck - scalafmt --mode diff-ref=origin/main - git diff --check References: Refs #2563 --- .../pekko/actor/typed/javadsl/package-info.java | 25 ++++++++++++++++++++++ .../pekko/actor/typed/javadsl/Behaviors.scala | 6 ++++-- build.sbt | 1 + .../sharding/typed/javadsl/package-info.java | 25 ++++++++++++++++++++++ .../sharding/typed/javadsl/ClusterSharding.scala | 16 ++++++++------ project/Dependencies.scala | 5 ++++- .../apache/pekko/testkit/javadsl/package-info.java | 25 ++++++++++++++++++++++ 7 files changed, 94 insertions(+), 9 deletions(-) diff --git a/actor-typed/src/main/java/org/apache/pekko/actor/typed/javadsl/package-info.java b/actor-typed/src/main/java/org/apache/pekko/actor/typed/javadsl/package-info.java new file mode 100644 index 0000000000..04216dd906 --- /dev/null +++ b/actor-typed/src/main/java/org/apache/pekko/actor/typed/javadsl/package-info.java @@ -0,0 +1,25 @@ +/* + * 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 + * + * 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. + */ + +/** + * Java API for Pekko Actor Typed. + * + * <p>This package contains the Java DSL for Pekko Actor Typed. For the Scala DSL see {@code + * org.apache.pekko.actor.typed.scaladsl}. + */ [email protected] +package org.apache.pekko.actor.typed.javadsl; diff --git a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala index 41e8a8b678..6353ea1856 100644 --- a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala +++ b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/javadsl/Behaviors.scala @@ -20,6 +20,8 @@ import scala.annotation.nowarn import scala.jdk.CollectionConverters._ import scala.reflect.ClassTag +import org.jspecify.annotations.Nullable + import org.apache.pekko import pekko.actor.typed._ import pekko.actor.typed.internal.{ BehaviorImpl, StashBufferImpl, TimerSchedulerImpl, WithMdcBehaviorInterceptor } @@ -402,8 +404,8 @@ object Behaviors { */ def withMdc[T]( interceptMessageClass: Class[T], - staticMdc: java.util.Map[String, String], - mdcForMessage: pekko.japi.function.Function[T, java.util.Map[String, String]], + @Nullable staticMdc: java.util.Map[String, String], + @Nullable mdcForMessage: pekko.japi.function.Function[T, java.util.Map[String, String]], behavior: Behavior[T]): Behavior[T] = { def asScalaMap(m: java.util.Map[String, String]): Map[String, String] = { diff --git a/build.sbt b/build.sbt index b283f1f66e..0d5f03cc68 100644 --- a/build.sbt +++ b/build.sbt @@ -575,6 +575,7 @@ lazy val clusterShardingTyped = pekkoModule("cluster-sharding-typed") remoteTests % "test->test", remoteTests % "test->test;multi-jvm->multi-jvm", jackson % "test->test") + .settings(Dependencies.clusterShardingTyped) .settings(javacOptions += "-parameters") // for Jackson .settings(AutomaticModuleName.settings("pekko.cluster.sharding.typed")) // To be able to import ContainerFormats.proto diff --git a/cluster-sharding-typed/src/main/java/org/apache/pekko/cluster/sharding/typed/javadsl/package-info.java b/cluster-sharding-typed/src/main/java/org/apache/pekko/cluster/sharding/typed/javadsl/package-info.java new file mode 100644 index 0000000000..19ef9b5860 --- /dev/null +++ b/cluster-sharding-typed/src/main/java/org/apache/pekko/cluster/sharding/typed/javadsl/package-info.java @@ -0,0 +1,25 @@ +/* + * 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 + * + * 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. + */ + +/** + * Java API for Pekko Cluster Sharding Typed. + * + * <p>This package contains the Java DSL for Pekko Cluster Sharding Typed. For the Scala DSL see + * {@code org.apache.pekko.cluster.sharding.typed.scaladsl}. + */ [email protected] +package org.apache.pekko.cluster.sharding.typed.javadsl; diff --git a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/javadsl/ClusterSharding.scala b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/javadsl/ClusterSharding.scala index dcdd8b36be..b9ebc34d7f 100644 --- a/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/javadsl/ClusterSharding.scala +++ b/cluster-sharding-typed/src/main/scala/org/apache/pekko/cluster/sharding/typed/javadsl/ClusterSharding.scala @@ -21,6 +21,8 @@ import java.util.concurrent.CompletionStage import scala.annotation.nowarn import scala.jdk.OptionConverters._ +import org.jspecify.annotations.Nullable + import org.apache.pekko import pekko.actor.typed.ActorRef import pekko.actor.typed.ActorSystem @@ -279,7 +281,7 @@ final class Entity[M, E] private ( /** * Additional settings, typically loaded from configuration. */ - def withSettings(newSettings: ClusterShardingSettings): Entity[M, E] = + def withSettings(@Nullable newSettings: ClusterShardingSettings): Entity[M, E] = copy(settings = Optional.ofNullable(newSettings)) /** @@ -288,7 +290,7 @@ final class Entity[M, E] private ( * It can be useful to define a custom stop message if the entity needs to perform * some asynchronous cleanup or interactions before stopping. */ - def withStopMessage(newStopMessage: M): Entity[M, E] = + def withStopMessage(@Nullable newStopMessage: M): Entity[M, E] = copy(stopMessage = Optional.ofNullable(newStopMessage)) /** @@ -298,7 +300,8 @@ final class Entity[M, E] private ( * shards is then defined by `numberOfShards` in `ClusterShardingSettings`, which by default * is configured with `pekko.cluster.sharding.number-of-shards`. */ - def withMessageExtractor[Envelope](newExtractor: ShardingMessageExtractor[Envelope, M]): Entity[M, Envelope] = + def withMessageExtractor[Envelope]( + @Nullable newExtractor: ShardingMessageExtractor[Envelope, M]): Entity[M, Envelope] = new Entity( createBehavior, typeKey, @@ -313,7 +316,7 @@ final class Entity[M, E] private ( /** * Run the Entity actors on nodes with the given role. */ - def withRole(role: String): Entity[M, E] = + def withRole(@Nullable role: String): Entity[M, E] = copy(role = Optional.ofNullable(role)) /** @@ -322,13 +325,14 @@ final class Entity[M, E] private ( * dataCenter does not match the data center of the current node the `ShardRegion` will be started * in proxy mode. */ - def withDataCenter(newDataCenter: String): Entity[M, E] = copy(dataCenter = Optional.ofNullable(newDataCenter)) + def withDataCenter(@Nullable newDataCenter: String): Entity[M, E] = + copy(dataCenter = Optional.ofNullable(newDataCenter)) /** * Allocation strategy which decides on which nodes to allocate new shards, * [[ClusterSharding#defaultShardAllocationStrategy]] is used if this is not specified. */ - def withAllocationStrategy(newAllocationStrategy: ShardAllocationStrategy): Entity[M, E] = + def withAllocationStrategy(@Nullable newAllocationStrategy: ShardAllocationStrategy): Entity[M, E] = copy(allocationStrategy = Optional.ofNullable(newAllocationStrategy)) private def copy( diff --git a/project/Dependencies.scala b/project/Dependencies.scala index c496833ab2..d491208e45 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -214,13 +214,14 @@ object Dependencies { lazy val actor = l ++= Seq(config) - val actorTyped = l ++= Seq(slf4jApi) + val actorTyped = l ++= Seq(slf4jApi, jspecify) val discovery = l ++= Seq(TestDependencies.junit, TestDependencies.scalatest) val coordination = l ++= Seq(TestDependencies.junit, TestDependencies.scalatest) val testkit = l ++= Seq( + jspecify, TestDependencies.junit, TestDependencies.junit6, TestDependencies.junitPlatformLauncher, @@ -278,6 +279,8 @@ object Dependencies { TestDependencies.commonsIo, TestDependencies.ycsb) + lazy val clusterShardingTyped = l ++= Seq(jspecify) + lazy val clusterMetrics = l ++= Seq( Provided.sigarLoader, TestDependencies.slf4jJul, diff --git a/testkit/src/main/java/org/apache/pekko/testkit/javadsl/package-info.java b/testkit/src/main/java/org/apache/pekko/testkit/javadsl/package-info.java new file mode 100644 index 0000000000..2050f72546 --- /dev/null +++ b/testkit/src/main/java/org/apache/pekko/testkit/javadsl/package-info.java @@ -0,0 +1,25 @@ +/* + * 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 + * + * 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. + */ + +/** + * Java API for Pekko TestKit. + * + * <p>This package contains the Java DSL for Pekko TestKit. For the Scala DSL see {@code + * org.apache.pekko.testkit}. + */ [email protected] +package org.apache.pekko.testkit.javadsl; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
