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]

Reply via email to