This is an automated email from the ASF dual-hosted git repository.
hepin 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 037b88ad29 Add StatusReply.fromCallable Java API for Try-like error
handling (#2812)
037b88ad29 is described below
commit 037b88ad29643299d451d3c9d2548a4997636cca
Author: He-Pin(kerr) <[email protected]>
AuthorDate: Sat Mar 28 19:35:34 2026 +0800
Add StatusReply.fromCallable Java API for Try-like error handling (#2812)
Provides Java-friendly equivalents of fromTry and fromTryKeepException
using java.util.concurrent.Callable instead of scala.util.Try.
Uses NonFatal to avoid catching InterruptedException, consistent with
how scala.util.Try.apply handles exceptions internally.
---
.../org/apache/pekko/pattern/StatusReplySpec.scala | 31 ++++++++++++++++++
.../org/apache/pekko/pattern/StatusReply.scala | 37 +++++++++++++++++++++-
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git
a/actor-tests/src/test/scala/org/apache/pekko/pattern/StatusReplySpec.scala
b/actor-tests/src/test/scala/org/apache/pekko/pattern/StatusReplySpec.scala
index 3356800eae..b014ea481c 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/pattern/StatusReplySpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/pattern/StatusReplySpec.scala
@@ -110,6 +110,37 @@ class StatusReplySpec extends PekkoSpec with ScalaFutures {
reply.isError should ===(true)
reply.getError.getMessage should ===("java.lang.RuntimeException")
}
+
+ "create from Callable success" in {
+ val reply = StatusReply.fromCallable[String](() => "woho")
+ reply.isSuccess should ===(true)
+ reply.getValue should ===("woho")
+ }
+
+ "create from Callable failure with message" in {
+ val reply = StatusReply.fromCallable[String](() => throw
TestException("boo"))
+ reply.isError should ===(true)
+ reply.getError.getMessage should ===("boo")
+ reply.getError shouldBe a[StatusReply.ErrorMessage]
+ }
+
+ "create from CallableKeepException success" in {
+ val reply = StatusReply.fromCallableKeepException[String](() => "woho")
+ reply.isSuccess should ===(true)
+ reply.getValue should ===("woho")
+ }
+
+ "create from CallableKeepException failure keeping exception" in {
+ val reply = StatusReply.fromCallableKeepException[String](() => throw
TestException("boo"))
+ reply.isError should ===(true)
+ reply.getError should ===(TestException("boo"))
+ }
+
+ "create from Callable failure with null message" in {
+ val reply = StatusReply.fromCallable[String](() => throw new
RuntimeException())
+ reply.isError should ===(true)
+ reply.getError.getMessage should ===("java.lang.RuntimeException")
+ }
}
"askWithStatus" should {
diff --git a/actor/src/main/scala/org/apache/pekko/pattern/StatusReply.scala
b/actor/src/main/scala/org/apache/pekko/pattern/StatusReply.scala
index a359038d78..31e274914b 100644
--- a/actor/src/main/scala/org/apache/pekko/pattern/StatusReply.scala
+++ b/actor/src/main/scala/org/apache/pekko/pattern/StatusReply.scala
@@ -18,7 +18,7 @@ import scala.concurrent.Future
import scala.util.{ Failure => ScalaFailure }
import scala.util.{ Success => ScalaSuccess }
import scala.util.Try
-import scala.util.control.NoStackTrace
+import scala.util.control.{ NoStackTrace, NonFatal }
import org.apache.pekko
import pekko.Done
@@ -137,6 +137,41 @@ object StatusReply {
*/
def fromTryKeepException[T](status: Try[T]): StatusReply[T] = new
StatusReply(status)
+ /**
+ * Java API: Convert the result of a [[java.util.concurrent.Callable]] into
a [[StatusReply]].
+ *
+ * If the callable completes successfully, wraps the result in a successful
reply.
+ * If it throws an exception, converts the exception message to an error
reply
+ * (discarding the original exception type, making it safe for remote
serialization).
+ *
+ * This is the Java-friendly equivalent of [[#fromTry]].
+ *
+ * @since 2.0.0
+ */
+ def fromCallable[T](callable: java.util.concurrent.Callable[T]):
StatusReply[T] =
+ try success(callable.call())
+ catch {
+ case NonFatal(e) =>
error[T](Option(e.getMessage).getOrElse(e.getClass.getName))
+ }
+
+ /**
+ * Java API: Convert the result of a [[java.util.concurrent.Callable]] into
a [[StatusReply]],
+ * keeping the original exception in case of failure.
+ *
+ * Unlike [[#fromCallable]], this preserves the full exception object. This
is useful when
+ * callers need to match on exception types, but requires that serializers
are configured
+ * for the exception types used when communicating with remote actors.
+ *
+ * This is the Java-friendly equivalent of [[#fromTryKeepException]].
+ *
+ * @since 2.0.0
+ */
+ def fromCallableKeepException[T](callable:
java.util.concurrent.Callable[T]): StatusReply[T] =
+ try success(callable.call())
+ catch {
+ case NonFatal(e) => error[T](e)
+ }
+
/**
* Carrier exception used for textual error descriptions.
*
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]