Dear Experts,
I get a confusing runtime error trying to exercise a choice through java bindings. Any ideas where I might be going wrong?
STACK TRACE:
io.grpc.StatusRuntimeException: CANCELLED: Failed to read message.
at io.grpc.Status.asRuntimeException(Status.java:534)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:553)
at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:68)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:739)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:718)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Missing field: value
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:262)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:243)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:156)
at com.daml.ledger.api.v1.CommandSubmissionServiceGrpc$CommandSubmissionServiceBlockingStub.submit(CommandSubmissionServiceGrpc.java:233)
at com.daml.TraderApp.MyTrader.processTransaction(MyTrader.java:241)
at com.daml.TraderApp.MyTrader.access$100(MyTrader.java:81)
at com.daml.TraderApp.MyTrader$1.lambda$onNext$0(MyTrader.java:197)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1087)
at com.daml.TraderApp.MyTrader$1.onNext(MyTrader.java:197)
at com.daml.TraderApp.MyTrader$1.onNext(MyTrader.java:194)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onMessage(ClientCalls.java:465)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInternal(ClientCallImpl.java:652)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:637)
MY REQUEST OUTPUT AS TEXT
commands {
ledger_id: “35a409dc-c9f1-4404-8608-a283354da555”
workflow_id: “MarketData-TradeCommunity-1”
application_id: “TraderApp”
command_id: “50374723-6dc3-4844-ab92-af52d905bc89”
party: “TradeCommunity”
commands {
exercise {
template_id {
package_id: “be19f03385255b49b3e7b5573a111cc65d91b3a7456e2d1e7987de4b5ab5aaa6”
module_name: “MarketData”
entity_name: “MarketData”
}
contract_id: “008d4d00738332caa22d1f714465d4bf1cf44c29c2d6e9a8cdf542314c3d6bed45”
choice: “MakeTrade”
}
}
}
JAVA CODE
private void processTransaction(Transaction tx) {
List<Command> commands = tx.getEventsList().stream()
.filter(Event::hasCreated).map(Event::getCreated)
.flatMap(e -> processEvent(tx.getWorkflowId(), e))
.collect(Collectors.toList());
if (!commands.isEmpty()) {
SubmitRequest request = SubmitRequest.newBuilder()
.setCommands(Commands.newBuilder()
.setCommandId(UUID.randomUUID().toString())
.setWorkflowId(tx.getWorkflowId())
.setLedgerId(ledgerId)
.setParty(party)
.setApplicationId("TraderApp")
.addAllCommands(commands)
.build())
.build();
submissionService.submit(request);
}
}
private Stream processEvent(String workflowId, CreatedEvent event) {
Identifier template = event.getTemplateId();
boolean isMarketDataModule = template.getModuleName().equals("MarketData");
if (!isMarketDataModule) return Stream.empty();
String contractId = event.getContractId();
String choice = "MakeTrade";
// assemble the exercise command
Command cmd = Command
.newBuilder()
.setExercise(ExerciseCommand
.newBuilder()
.setTemplateId(template)
.setContractId(contractId)
.setChoice(choice))
.build();
return Stream.of(cmd);
}
DAML TEMPLATES
module MarketData where
import Trade
type MarketDataCid = ContractId MarketData
template MarketData
with
buyer : Party
seller : Party
volume: Decimal
price: Decimal
timestamp: Datetime
observers : [Party]
where
signatory buyer
observer observers
nonconsuming choice MakeTrade : TradeCid
controller buyer
do
create Trade with
buyer = this.buyer
seller = this.seller
volume = this.volume
price = this.price
timestamp = this.timestamp
observers = this.observers
module Trade where
type TradeCid = ContractId Trade
template Trade
with
buyer : Party
seller : Party
volume: Decimal
price: Decimal
timestamp: Datetime
observers : [Party]
where
signatory buyer
observer observers