Action async operations failed

Hi,
I am following the documentation to learn Actions.
In my case, I created an action to call entity’s create method and return the result.
In case of forward, it has no problem, but when in async mode, the call failed and the response from the entity is null.
please help

forward case works

  @PostMapping("/createWallet")
  public Effect<String> createWallet() {
    final String id = UUID.randomUUID().toString().replace("-", "");
    log.info(id);
    DeferredCall<Any, String> params =
        componentClient.forValueEntity(id).call(WalletEntity::create).params(id, 0);

    return effects().forward(params);
  }

async return null as result

  @PostMapping("/create")
  public Effect<String> initializeCart() {
    final String id = UUID.randomUUID().toString().replace("-", "");
    CompletionStage<String> walletCreate =
        componentClient.forValueEntity(id).call(WalletEntity::create).params(id, 0).execute();

    // transform response
    CompletionStage<Effect<String>> effect =
        walletCreate.handle(
            (result, error) -> {
              if (error == null) {
                return effects().reply(result);
              } else {
                return effects().error("Failed to create cart, please retry");
              }
            });

    return effects().asyncEffect(effect);
  }

Also, I wanna transform a result from a view in the action but the async does not return anything but below error

The server was not able to produce a timely response to your request.
Please try again in a short while!

code is

  @GetMapping("/{pid}")
  public Effect<ProductViewResult> getTotalQtyByProductId(@PathVariable String pid) {
    DeferredCall<Any, ProductViewResult> deferredCall =
        componentClient.forView().call(ProductQtyById::getProductQty).params(pid);
    CompletionStage<ProductViewResult> execute = deferredCall.execute();

    CompletionStage<Effect<ProductViewResult>> r = execute.handle((result, exce) -> {
      if (exce == null) {
        return effects().error("error");
      }
      return effects().reply(result.groupResult());
    });

    return effects().asyncEffect(r);
  }

Hi,

I might be missing something but I’m not seeing any obvious reason for that to happen.

For the code transforming the view result, I think there is a typo on if (exce == null) { which should probably be if (exce != null) {. I would not expect that to result in a timeout though.

If you want to share a complete sample and instructions to reproduce, that would help.

HI @kerberos

can you share the SDK version you are using?

Here is my example

Entity

@Slf4j
@TypeId("customer")
@Id("id")
@RequestMapping("/customer/{id}")
@Acl(allow = @Acl.Matcher(principal = Acl.Principal.ALL))
public class CustomerEntity extends ValueEntity<CustomerEntity.Customer> {
  @PostMapping()
  public Effect<String> create(@PathVariable String id) {
    return effects().updateState(new Customer(id)).thenReply("OK");
  }

  @GetMapping
  public Effect<String> get() {
    return Objects.isNull(currentState())
        ? effects().error("Not exist")
        : effects().reply(currentState().toString());
  }

  public record Customer(String id) {}
}

Action:

@Slf4j
@RequestMapping("/customer/action")
@Acl(allow = @Acl.Matcher(principal = Acl.Principal.ALL))
public class CustomerAction extends Action {
  private final ComponentClient componentClient;

  public CustomerAction(ComponentClient componentClient) {
    this.componentClient = componentClient;
  }

  @PostMapping("/create/forward")
  public Effect<String> createForward() {
    String id = UUID.randomUUID().toString();
    log.info(id);
    DeferredCall<Any, String> call =
        componentClient.forValueEntity(id).call(CustomerEntity::create).params(id);
    return effects().forward(call);
  }

  @PostMapping("/create/async")
  public Effect<String> createForwardAsync() {
    String id = UUID.randomUUID().toString();
    log.info(id);
    CompletionStage<String> future =
        componentClient.forValueEntity(id).call(CustomerEntity::create).params(id).execute();

    CompletionStage<Effect<String>> effect =
        future.handle(
            (result, error) -> {
              if (error == null) {
                return effects().reply(result);
              } else {
                return effects().error("Failed to create customer, please retry");
              }
            });

    return effects().asyncEffect(effect);
  }
}

Everything is following the document and no issue with entity’s create and get method also no issue with action’s createForward, but the createForwardAsync returns below error

ERROR k.javasdk.impl.action.ActionsImpl - Failure during handling of command com.example.reproduce.CustomerAction.CreateForwardAsync
kalix.javasdk.impl.NullSerializationException$: Don't know how to serialize object of type null.

Hi ,
I am using 1.3.7

I wasn’t able to reproduce it locally. In my case it works in both cases:

⋊> ~/p/k/k/s/java-spring-valueentity-counter on code-first-http-body ⨯ curl -i -X POST "http://0.0.0.0:9000/customer/action/create/forward"                                                                         10:51:51
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Server: akka-http/10.6.0
Date: Fri, 05 Jan 2024 09:52:15 GMT
Content-Type: application/json
Content-Length: 4

"OK"⏎                 
⋊> ~/p/k/k/s/java-spring-valueentity-counter on code-first-http-body ⨯ curl -i -X POST "http://0.0.0.0:9000/customer/action/create/async"                                                                           10:52:15
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Server: akka-http/10.6.0
Date: Fri, 05 Jan 2024 09:52:26 GMT
Content-Type: application/json
Content-Length: 8

"\"OK\""⏎  

How do you start the application? Can you share the logs?

Whole log is below

mvn kalix:runAll
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.bitness: 64
[INFO] os.detected.version: 13.4
[INFO] os.detected.version.major: 13
[INFO] os.detected.version.minor: 4
[INFO] os.detected.classifier: osx-x86_64
[INFO] 
[INFO] ----------------------< com.example:shoppingcart >----------------------
[INFO] Building shoppingcart 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] >>> kalix:1.3.7:runAll (default-cli) > compile @ shoppingcart >>>
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ shoppingcart ---
[INFO] Copying 3 resources from src/main/resources to target/classes
[INFO] 
[INFO] --- compiler:3.11.0:compile (default-compile) @ shoppingcart ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] <<< kalix:1.3.7:runAll (default-cli) < compile @ shoppingcart <<<
[INFO] 
[INFO] 
[INFO] --- kalix:1.3.7:runAll (default-cli) @ shoppingcart ---
10:34:50.262 INFO  com.example.Main - Starting Kalix Application
10:34:50.542 WARN  o.s.b.l.logback.LogbackLoggingSystem - Ignoring 'logback.configurationFile' system property. Please use 'logging.config' instead.
10:34:50.638 INFO  com.example.Main - Starting Main using Java 21.0.1 with PID 72072 (/Users/yiye/workspace/shoppingcart/target/classes started by yiye in /Users/yiye/workspace/shoppingcart)
10:34:50.639 INFO  com.example.Main - No active profile set, falling back to 1 default profile: "default"
10:34:51.126 INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'kalix.spring.boot.KalixConfiguration' of type [kalix.spring.boot.KalixConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
10:34:51.565 INFO  k.spring.impl.KalixSpringApplication - Registering EventSourcedEntity provider for [com.example.api.ShoppingCartEntity]
10:34:51.659 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/cart/{cartId}/add),json_body,,Vector(),UnknownFieldSet(Map()))]
10:34:51.677 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/cart/{cartId}/checkout),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.678 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/cart/{cartId}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.678 INFO  k.spring.impl.KalixSpringApplication - Registering Action provider for [com.example.hello.HelloWorld]
10:34:51.704 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/hello),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.704 INFO  k.spring.impl.KalixSpringApplication - Registering Action provider for [com.example.actions.ProductTotalQtyAction]
10:34:51.709 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/product/createWallet),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.710 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/product/{pid}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.710 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/product/create),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.711 INFO  k.spring.impl.KalixSpringApplication - Registering ValueEntity provider for [com.example.api.WalletEntity]
10:34:51.723 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/wallet/{id}/create/{initBalance}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.724 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Patch(/wallet/{id}/deposit/{amount}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.725 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/wallet/{id}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.726 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Patch(/wallet/{id}/withdraw/{amount}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.726 INFO  k.spring.impl.KalixSpringApplication - Registering Action provider for [com.example.reproduce.CustomerAction]
10:34:51.729 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/action/create/forward),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.729 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/action/create/async),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.730 INFO  k.spring.impl.KalixSpringApplication - Registering Workflow provider for [com.example.workflow.TransferWorkflow]
10:34:51.735 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/transfer/{transferId}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.736 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Put(/transfer/{transferId}),json_body,,Vector(),UnknownFieldSet(Map()))]
10:34:51.736 INFO  k.spring.impl.KalixSpringApplication - Registering ValueEntity provider for [com.example.reproduce.CustomerEntity]
10:34:51.738 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/{id}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.739 INFO  k.spring.impl.KalixSpringApplication - Registering View provider for [com.example.view.ProductQtyById]
10:34:51.809 INFO  k.j.i.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/view_product_qty_by_id/{product_id}),,,Vector(),UnknownFieldSet(Map()))]
10:34:51.853 INFO  k.s.b.KalixReactiveWebServerFactory - Instantiating Kalix ReactiveWebServer
10:34:52.285 INFO  k.s.b.KalixReactiveWebServerFactory - Starting Kalix ReactiveWebServer...
10:34:52.286 INFO  k.spring.impl.KalixSpringApplication - Starting Kalix Application...
 Container shoppingcart  Created
Attaching to shoppingcart
shoppingcart  | Picked up JAVA_TOOL_OPTIONS: 
10:34:53.007 INFO  com.example.Main - Started Main in 2.668 seconds (process running for 3.126)
shoppingcart  | 18:34:53.582 INFO  kalix.proxy.KalixRuntimeMain - Persistence mode disabled
shoppingcart  | 18:34:54.575 INFO  kalix.proxy.KalixRuntimeMain - Starting Kalix Runtime version [1.1.27]
shoppingcart  | 18:34:55.270 INFO  kalix.proxy.DiscoveryManager - Connecting to [host.docker.internal:8081] to discover the user service specification
10:34:55.787 INFO  kalix.javasdk.impl.DiscoveryImpl - Received discovery call from [kalix-proxy-core 1.1.27] at [localhost]:[9000] supporting Kalix protocol 1.1
shoppingcart  | 18:34:55.884 INFO  kalix.proxy.DiscoveryManager - Received Spec from user service: service name: [], service version: [], service runtime: [OpenJDK Runtime Environment 21.0.1], protocol version: [1.1], sdk: [kalix-java-sdk-spring-1.3.7], proxy version [1.1.27], 
shoppingcart  | 18:34:55.888 INFO  kalix.proxy.DiscoveryManager - Protocol version compatibility is configured to be ignored
shoppingcart  | 18:34:55.923 INFO  kalix.proxy.DiscoveryManager - Service components: Actions: [3], ValueEntities: [2], EventSourcedEntities: [1], Views: [1], WorkflowEntities: [1]
shoppingcart  | 18:34:55.960 INFO  kalix.proxy.DiscoveryManager - User hooks found: Vector()
shoppingcart  | 18:34:56.006 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/wallet/{id}/create/{initBalance}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.046 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Patch(/wallet/{id}/deposit/{amount}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.049 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/wallet/{id}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.051 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Patch(/wallet/{id}/withdraw/{amount}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.111 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/transfer/{transferId}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.112 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Put(/transfer/{transferId}),json_body,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.139 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/{id}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.143 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/view_product_qty_by_id/{product_id}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.144 INFO  k.p.h.HttpEndpointMethodDefinition - Using generated HTTP API endpoint using [HttpRule(com.example.view.ProductQtyById.KalixSyntheticMethodOnESShoppingcart,Post(/com.example.view.ProductQtyById/KalixSyntheticMethodOnESShoppingcart),*,,List(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.311 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/cart/{cartId}/add),json_body,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.312 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/cart/{cartId}/checkout),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.313 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/cart/{cartId}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.324 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/product/createWallet),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.325 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/product/{pid}),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.326 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/product/create),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.333 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Get(/hello),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.334 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/action/create/forward),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.335 INFO  k.p.h.HttpEndpointMethodDefinition - Using configured HTTP API endpoint using [HttpRule(,Post(/customer/action/create/async),,,Vector(),UnknownFieldSet(Map()))]
shoppingcart  | 18:34:56.477 WARN  kalix.proxy.VersionCheck - Failure checking the latest [java-spring] SDK on [https://docs.kalix.io/java-spring/_attachments/latest-version.txt]. Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
shoppingcart  | 18:34:56.512 INFO  kalix.proxy.DiscoveryManager - Kalix Runtime started at 0.0.0.0:9000
shoppingcart  | 18:34:56.513 INFO  kalix.proxy.DiscoveryManager - gRPC proxy started at 0.0.0.0:9000
10:34:56.534 INFO  kalix.javasdk.impl.DiscoveryImpl - Info reported from Kalix system:  Service started and reachable at 0.0.0.0:9000
10:35:58.511 INFO  c.example.reproduce.CustomerAction - b081ad27-6e12-4e29-84f7-471c7af16f4c
10:36:00.930 ERROR k.javasdk.impl.action.ActionsImpl - Failure during handling of command com.example.reproduce.CustomerAction.CreateForwardAsync
kalix.javasdk.impl.NullSerializationException$: Don't know how to serialize object of type null.
        at kalix.javasdk.impl.NullSerializationException$.<clinit>(AnySupport.scala:478)
        at kalix.javasdk.impl.JsonMessageCodec.encodeScala(JsonMessageCodec.scala:46)
        at kalix.javasdk.impl.action.ActionsImpl.effectToResponse(ActionsImpl.scala:143)
        at kalix.javasdk.impl.action.ActionsImpl.$anonfun$effectToResponse$2(ActionsImpl.scala:173)
        at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:470)
        at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:63)
        at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:100)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
        at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:94)
        at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:100)
        at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:49)
        at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)

I was not able to reproduce it on my machine :confused: Do you have some specific firewall or protection configuration, because I can see a warning:

shoppingcart  | 18:34:56.477 WARN  kalix.proxy.VersionCheck - Failure checking the latest [java-spring] SDK on [https://docs.kalix.io/java-spring/_attachments/latest-version.txt]. Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

hmmm…maybe because of the VPN on my laptop?
But I am not sure how it impacts the async call.

Async call is basically just an http call to itself. Can you share more details about your setup, like your operating system? Also I have one more idea. Can you edit logback-dev-mode.xml file, change it to:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="akka.http.impl.engine.http2.Http2ServerDemux" level="INFO"/>

    <root level="TRACE">
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

and provide logs when calling an action endpoint with an async reply?

I am on mac 13.4.1 with Intel CPU.
Login kalix account with kalix auth login --use-grpc-web due to company VPN

Will try the changes you suggested.

I don’t think it’s a VPN issue. I have VPN as well. It feels like some corporate SSL certificate/security issue. Calling https://docs.kalix.io/java-spring/_attachments/latest-version.txt should work, but somehow the request fails (warning statement).