From 51a5eb77a0028827c7202831ecd5432101d76e4e Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Wed, 15 Mar 2017 11:18:14 +0000 Subject: [PATCH] Added @Suspendable to UntrustworthyData.unwrap to allow Java flows to do I/O inside unwrap --- .../corda/core/utilities/UntrustworthyData.kt | 3 + .../net/corda/core/flows/FlowsInJavaTest.java | 74 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 core/src/test/java/net/corda/core/flows/FlowsInJavaTest.java diff --git a/core/src/main/kotlin/net/corda/core/utilities/UntrustworthyData.kt b/core/src/main/kotlin/net/corda/core/utilities/UntrustworthyData.kt index 7db3d496df..48ecc3da4e 100644 --- a/core/src/main/kotlin/net/corda/core/utilities/UntrustworthyData.kt +++ b/core/src/main/kotlin/net/corda/core/utilities/UntrustworthyData.kt @@ -1,5 +1,6 @@ package net.corda.core.utilities +import co.paralleluniverse.fibers.Suspendable import net.corda.core.flows.FlowException /** @@ -18,6 +19,7 @@ class UntrustworthyData(private val fromUntrustedWorld: T) { @Deprecated("Accessing the untrustworthy data directly without validating it first is a bad idea") get() = fromUntrustedWorld + @Suspendable @Throws(FlowException::class) fun unwrap(validator: Validator) = validator.validate(fromUntrustedWorld) @@ -26,6 +28,7 @@ class UntrustworthyData(private val fromUntrustedWorld: T) { inline fun validate(validator: (T) -> R) = validator(data) interface Validator { + @Suspendable @Throws(FlowException::class) fun validate(data: T): R } diff --git a/core/src/test/java/net/corda/core/flows/FlowsInJavaTest.java b/core/src/test/java/net/corda/core/flows/FlowsInJavaTest.java new file mode 100644 index 0000000000..eebabbd7f5 --- /dev/null +++ b/core/src/test/java/net/corda/core/flows/FlowsInJavaTest.java @@ -0,0 +1,74 @@ +package net.corda.core.flows; + +import co.paralleluniverse.fibers.Suspendable; +import net.corda.core.crypto.Party; +import net.corda.testing.node.MockNetwork; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.Future; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class FlowsInJavaTest { + + private final MockNetwork net = new MockNetwork(); + private MockNetwork.MockNode node1; + private MockNetwork.MockNode node2; + + @Before + public void setUp() { + MockNetwork.BasketOfNodes someNodes = net.createSomeNodes(2); + node1 = someNodes.getPartyNodes().get(0); + node2 = someNodes.getPartyNodes().get(1); + net.runNetwork(); + } + + @After + public void cleanUp() { + net.stopNodes(); + } + + @Test + public void suspendableActionInsideUnwrap() throws Exception { + node2.getServices().registerFlowInitiator(SendInUnwrapFlow.class, (otherParty) -> new OtherFlow(otherParty, "Hello")); + Future result = node1.getServices().startFlow(new SendInUnwrapFlow(node2.getInfo().getLegalIdentity())).getResultFuture(); + net.runNetwork(); + assertThat(result.get()).isEqualTo("Hello"); + } + + private static class SendInUnwrapFlow extends FlowLogic { + private final Party otherParty; + + private SendInUnwrapFlow(Party otherParty) { + this.otherParty = otherParty; + } + + @Suspendable + @Override + public String call() throws FlowException { + return receive(String.class, otherParty).unwrap(data -> { + send(otherParty, "Something"); + return data; + }); + } + } + + private static class OtherFlow extends FlowLogic { + private final Party otherParty; + private final String payload; + + private OtherFlow(Party otherParty, String payload) { + this.otherParty = otherParty; + this.payload = payload; + } + + @Suspendable + @Override + public String call() throws FlowException { + return sendAndReceive(String.class, otherParty, payload).unwrap(data -> data); + } + } + +}