From 18a9155e89a19fa274a9386d9634e30b3773ea64 Mon Sep 17 00:00:00 2001 From: Andras Slemmer Date: Mon, 4 Jun 2018 18:42:40 +0100 Subject: [PATCH] Add java samples --- .../contributing-flow-state-machines.rst | 20 +++++++++ docs/source/example-code/build.gradle | 5 +++ .../java/TutorialFlowAsyncOperationTest.java | 42 +++++++++++++++++++ .../flowstatemachines/ExampleSummingFlow.java | 19 +++++++++ .../flowstatemachines/SummingOperation.java | 32 ++++++++++++++ .../SummingOperationThrowing.java | 31 ++++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java create mode 100644 docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/ExampleSummingFlow.java create mode 100644 docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperation.java create mode 100644 docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperationThrowing.java diff --git a/docs/source/contributing-flow-state-machines.rst b/docs/source/contributing-flow-state-machines.rst index a78b945890..7f5a9a37c8 100644 --- a/docs/source/contributing-flow-state-machines.rst +++ b/docs/source/contributing-flow-state-machines.rst @@ -33,6 +33,11 @@ implement ``FlowAsyncOperation``: :start-after: DOCSTART SummingOperation :end-before: DOCEND SummingOperation + .. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperation.java + :language: java + :start-after: DOCSTART SummingOperation + :end-before: DOCEND SummingOperation + As we can see the constructor of ``SummingOperation`` takes the two numbers, and the ``execute`` function simply returns a future that is immediately completed by the result of summing the numbers. Note how we don't use ``@Suspendable`` on ``execute``, this is because we'll never suspend inside this function, the suspension will happen before we're calling @@ -62,6 +67,11 @@ flow: :start-after: DOCSTART ExampleSummingFlow :end-before: DOCEND ExampleSummingFlow + .. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/ExampleSummingFlow.java + :language: java + :start-after: DOCSTART ExampleSummingFlow + :end-before: DOCEND ExampleSummingFlow + That's it! Obviously this is a mostly useless example, but this is the basic code structure one could extend for heavier computations/other IO. For example the function could call into a ``CordaService`` or something similar. One thing to note is that the operation executed in ``execute`` must be redoable(= "idempotent") in case the node fails before the @@ -80,6 +90,11 @@ flow with a full node. :start-after: DOCSTART summingWorks :end-before: DOCEND summingWorks + .. literalinclude:: ../../docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java + :language: java + :start-after: DOCSTART summingWorks + :end-before: DOCEND summingWorks + The above will spin up a node and run our example flow. How to debug issues @@ -94,6 +109,11 @@ Let's assume we made a mistake in our summing operation: :start-after: DOCSTART SummingOperationThrowing :end-before: DOCEND SummingOperationThrowing + .. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperationThrowing.java + :language: java + :start-after: DOCSTART SummingOperationThrowing + :end-before: DOCEND SummingOperationThrowing + The operation now throws a rude exception. If we modify the example flow to use this and run the same test we will get a lot of logs about the error condition (as we are in dev mode). The interesting bit looks like this: diff --git a/docs/source/example-code/build.gradle b/docs/source/example-code/build.gradle index e45425686a..54c5ad53de 100644 --- a/docs/source/example-code/build.gradle +++ b/docs/source/example-code/build.gradle @@ -24,6 +24,11 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/integration-test/java') + } } } diff --git a/docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java new file mode 100644 index 0000000000..410f2fcf73 --- /dev/null +++ b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java @@ -0,0 +1,42 @@ +package net.corda.docs.java; + +import kotlin.Unit; +import net.corda.client.rpc.CordaRPCClient; +import net.corda.core.messaging.CordaRPCOps; +import net.corda.core.utilities.KotlinUtilsKt; +import net.corda.docs.java.tutorial.flowstatemachines.ExampleSummingFlow; +import net.corda.node.services.Permissions; +import net.corda.testing.driver.*; +import net.corda.testing.node.User; +import org.junit.Test; + +import java.util.Collections; +import java.util.HashSet; +import java.util.concurrent.Future; + +import static net.corda.testing.core.TestConstants.ALICE_NAME; +import static org.junit.Assert.assertEquals; + +public final class TutorialFlowAsyncOperationTest { + // DOCSTART summingWorks + @Test + public final void summingWorks() { + Driver.driver(new DriverParameters(), (DriverDSL dsl) -> { + User aliceUser = new User("aliceUser", "testPassword1", + new HashSet<>(Collections.singletonList(Permissions.all())) + ); + Future aliceFuture = dsl.startNode(new NodeParameters() + .withProvidedName(ALICE_NAME) + .withRpcUsers(Collections.singletonList(aliceUser)) + ); + NodeHandle alice = KotlinUtilsKt.getOrThrow(aliceFuture, null); + CordaRPCClient aliceClient = new CordaRPCClient(alice.getRpcAddress()); + CordaRPCOps aliceProxy = aliceClient.start("aliceUser", "testPassword1").getProxy(); + Future answerFuture = aliceProxy.startFlowDynamic(ExampleSummingFlow.class).getReturnValue(); + int answer = KotlinUtilsKt.getOrThrow(answerFuture, null); + assertEquals(3, answer); + return Unit.INSTANCE; + }); + } + // DOCEND summingWorks +} diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/ExampleSummingFlow.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/ExampleSummingFlow.java new file mode 100644 index 0000000000..c8e93d7025 --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/ExampleSummingFlow.java @@ -0,0 +1,19 @@ +package net.corda.docs.java.tutorial.flowstatemachines; + +import co.paralleluniverse.fibers.Suspendable; +import net.corda.core.flows.FlowLogic; +import net.corda.core.flows.StartableByRPC; +import net.corda.core.internal.FlowAsyncOperationKt; +import org.jetbrains.annotations.NotNull; + +// DOCSTART ExampleSummingFlow +@StartableByRPC +public final class ExampleSummingFlow extends FlowLogic { + @Suspendable + @NotNull + @Override + public Integer call() { + return FlowAsyncOperationKt.executeAsync(this, new SummingOperation(1, 2), false); + } +} +// DOCEND ExampleSummingFlow diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperation.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperation.java new file mode 100644 index 0000000000..d313fdb8ce --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperation.java @@ -0,0 +1,32 @@ +package net.corda.docs.java.tutorial.flowstatemachines; + +import net.corda.core.concurrent.CordaFuture; +import net.corda.core.internal.FlowAsyncOperation; +import net.corda.core.internal.concurrent.CordaFutureImplKt; +import org.jetbrains.annotations.NotNull; + +// DOCSTART SummingOperation +public final class SummingOperation implements FlowAsyncOperation { + private final int a; + private final int b; + + @NotNull + @Override + public CordaFuture execute() { + return CordaFutureImplKt.doneFuture(this.a + this.b); + } + + public final int getA() { + return this.a; + } + + public final int getB() { + return this.b; + } + + public SummingOperation(int a, int b) { + this.a = a; + this.b = b; + } +} +// DOCEND SummingOperation diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperationThrowing.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperationThrowing.java new file mode 100644 index 0000000000..1a759074b0 --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/flowstatemachines/SummingOperationThrowing.java @@ -0,0 +1,31 @@ +package net.corda.docs.java.tutorial.flowstatemachines; + +import net.corda.core.concurrent.CordaFuture; +import net.corda.core.internal.FlowAsyncOperation; +import org.jetbrains.annotations.NotNull; + +// DOCSTART SummingOperationThrowing +public final class SummingOperationThrowing implements FlowAsyncOperation { + private final int a; + private final int b; + + @NotNull + @Override + public CordaFuture execute() { + throw new IllegalStateException("You shouldn't be calling me"); + } + + public final int getA() { + return this.a; + } + + public final int getB() { + return this.b; + } + + public SummingOperationThrowing(int a, int b) { + this.a = a; + this.b = b; + } +} +// DOCEND SummingOperationThrowing