Starting a workflow with blockingStub().startWorkflowExecution (Java SDK)

Hi folks,
in my application I have a requirement of being able to launch a temporal workflow just by knowing its type (as a literal string). I’m using the Java SDK (1.0.6).
I think this is technically feasible since it’s possiblle to do so from tctl (CLI).

I was looking into the method:
client.getWorkflowServiceStubs().blockingStub().startWorkflowExecution(request)
But I got stuck in creating the request (StartWorkflowExecutionRequest), in particular with passing an input parameter, I see the builder has a setInput(), so I converted my input object (customer) into a ByteString and passed it like this:

ByteString data = ByteString.copyFrom(toByteArray(customer));
Payloads input = Payloads.newBuilder().setPayloads(1, Payload.newBuilder().setData(data)).build();

When I try to start the workflow I get the exception reported below.
I guess it’s something related to the way I’m trying to pass the input param, but I’m unable to find documentation on how to build a proper request with input.
I’m able to start the workflow in the “classical” way (with CreateCustomerWorkflow workflow = client.newWorkflowStub(CreateCustomerWorkflow.class, workflowOptions)

Anyone can help, or suggest some examples?
Thanks a lot
Regards
Andrea

09:52:18.166 [default-nioEventLoopGroup-1-3] ERROR i.m.h.s.netty.RoutingInBoundHandler

  • Unexpected error occurred: Index 1 out of bounds for length 0
    java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:372)
    at java.base/java.util.ArrayList.set(ArrayList.java:472)
    at io.temporal.api.common.v1.Payloads$Builder.setPayloads(Payloads.java:545)
    at com.jakala.jnext.poc.user.business.temporal.helper.TemporalWorkflow.createCustomer2(TemporalWorkflow.java:63)
    at com.jakala.jnext.poc.user.business.controller.CustomerController.create(CustomerController.java:26)
    at com.jakala.jnext.poc.user.business.controller.$CustomerControllerDefinition$$exec1.invokeInternal(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:146)
    at io.micronaut.context.DefaultBeanContext$4.invoke(DefaultBeanContext.java:474)
    at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:312)
    at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:118)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$10(RoutingInBoundHandler.java:1363)
    at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:35)
    at io.reactivex.Flowable.subscribe(Flowable.java:14918)
    at io.reactivex.Flowable.subscribe(Flowable.java:14865)
    at io.micronaut.http.server.context.ServerRequestContextFilter.lambda$doFilter$0(ServerRequestContextFilter.java:62)
    at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
    at io.reactivex.Flowable.subscribe(Flowable.java:14918)
    at io.reactivex.Flowable.subscribe(Flowable.java:14868)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildExecutableRoute$6(RoutingInBoundHandler.java:1068)
    at io.micronaut.web.router.DefaultUriRouteMatch$1.execute(DefaultUriRouteMatch.java:80)
    at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:118)
    at io.micronaut.http.server.netty.RoutingInBoundHandler$2.doOnComplete(RoutingInBoundHandler.java:994)
    at io.micronaut.core.async.subscriber.CompletionAwareSubscriber.onComplete(CompletionAwareSubscriber.java:71)
    at io.micronaut.http.server.netty.jackson.JsonContentProcessor$1.doOnComplete(JsonContentProcessor.java:140)
    at io.micronaut.core.async.subscriber.CompletionAwareSubscriber.onComplete(CompletionAwareSubscriber.java:71)
    at java.base/java.util.Optional.ifPresent(Optional.java:183)
    at io.micronaut.core.async.processor.SingleThreadedBufferingProcessor.doOnComplete(SingleThreadedBufferingProcessor.java:48)
    at io.micronaut.jackson.parser.JacksonProcessor.doOnComplete(JacksonProcessor.java:137)
    at io.micronaut.core.async.subscriber.SingleThreadedBufferingSubscriber.onComplete(SingleThreadedBufferingSubscriber.java:70)
    at io.micronaut.http.server.netty.jackson.JsonContentProcessor.doOnComplete(JsonContentProcessor.java:165)
    at io.micronaut.core.async.subscriber.CompletionAwareSubscriber.onComplete(CompletionAwareSubscriber.java:71)
    at io.micronaut.http.netty.reactive.HandlerPublisher.complete(HandlerPublisher.java:416)
    at io.micronaut.http.netty.reactive.HandlerPublisher.handlerRemoved(HandlerPublisher.java:403)
    at io.netty.channel.AbstractChannelHandlerContext.callHandlerRemoved(AbstractChannelHandlerContext.java:946)
    at io.netty.channel.DefaultChannelPipeline.callHandlerRemoved0(DefaultChannelPipeline.java:637)
    at io.netty.channel.DefaultChannelPipeline.remove(DefaultChannelPipeline.java:477)
    at io.netty.channel.DefaultChannelPipeline.remove(DefaultChannelPipeline.java:423)
    at io.micronaut.http.netty.stream.HttpStreamsHandler.removeHandlerIfActive(HttpStreamsHandler.java:429)
    at io.micronaut.http.netty.stream.HttpStreamsHandler.handleReadHttpContent(HttpStreamsHandler.java:294)
    at io.micronaut.http.netty.stream.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:257)
    at io.micronaut.http.netty.stream.HttpStreamsServerHandler.channelRead(HttpStreamsServerHandler.java:121)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
    at io.netty.handler.codec.http.HttpServerKeepAliveHandler.channelRead(HttpServerKeepAliveHandler.java:64)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:200)
    at io.netty.handler.flow.FlowControlHandler.read(FlowControlHandler.java:139)
    at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:686)
    at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:671)
    at io.micronaut.http.netty.reactive.HandlerPublisher.requestDemand(HandlerPublisher.java:163)
    at io.micronaut.http.netty.stream.HttpStreamsHandler$2.requestDemand(HttpStreamsHandler.java:248)
    at io.micronaut.http.netty.reactive.HandlerPublisher$ChannelSubscription.receivedDemand(HandlerPublisher.java:547)
    at io.micronaut.http.netty.reactive.HandlerPublisher$ChannelSubscription.lambda$request$0(HandlerPublisher.java:474)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)
    09:53:06.628 [Thread-7] INFO io.micronaut.runtime.Micronaut - Embedded Application shut
    ting down

Use untyped WorkflowStub instead:

WorklfowStub stub = workflowClient.newUntypedWorkflowStub("<workflowType>", workflowOptions);
stub.start(<args>);
1 Like

Thanks maxim, it works

Maxim, first of all thanks for your support (I’m still in the process of testing you suggestion in the propagate context thred).

I have anyway another small question for you, related to this topic of the untyped WorkflowStub.
Let’s say that after starting it, I have to send a signal (or query) the workflow.

Is there a way to get the stub using newUntypedWorkflowStub? I see the method in the client is overloaded with two other implementations, my need would be to get it by workflow id.
Thanks a lot for your patience
Andrea

Background:
I found a solution that is working to the above problem, by getting a workflow execution list of open workflows client.getWorkflowServiceStubs().blockingStub().listOpenWorkflowExecutions(request) and get the execution by searching the one with my workflow id.
Then I get the untyped WorkflowStub with:
client.newUntypedWorkflowStub(execution, null);
The above solution is working, still I’m getting the list of ALL open workflows in order to search for the one execution I need. Seems not very optimized :wink: Perhaps I can apply a filter, but I have a “feeling” there is a better way.

There is no need to list workflows to create a stub by a workflowId. The runId is optional and defaults to the runId of the currently running workflow.

So the following should work:

WorklfowStub stub = workflowClient.newUntypedWorkflowStub("<worfklowId>", Optional.empty(), Optional.of("<workflowType>"));
1 Like