Merge pull request #7 from corda/chrisbarratt/template-with-dp2-simulator

Chrisbarratt/template with dp2 simulator
This commit is contained in:
Chris Barratt 2022-10-20 08:10:35 +00:00 committed by GitHub
commit 0a7a8b2196
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 21 additions and 69 deletions

View File

@ -4,7 +4,7 @@ plugins {
id 'org.jetbrains.kotlin.jvm' id 'org.jetbrains.kotlin.jvm'
// Include the cordapp-cpb plugin. This automatically includes the cordapp-cpk plugin as well. // Include the cordapp-cpb plugin. This automatically includes the cordapp-cpk plugin as well.
// These extend existing build environment so that CPB and CPK files can be built. // These extend the existing build environment so that CPB and CPK files can be built.
// This includes a CorDapp DSL that allows the developer to supply metadata for the CorDapp // This includes a CorDapp DSL that allows the developer to supply metadata for the CorDapp
// required by Corda. // required by Corda.
id 'net.corda.plugins.cordapp-cpb2' id 'net.corda.plugins.cordapp-cpb2'
@ -45,36 +45,6 @@ cordapp {
} }
} }
/*
// Declare the set of Kotlin compiler options we need to build a CorDapp.
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
allWarningsAsErrors = false
// Specify the version of Kotlin that we are that we will be developing.
languageVersion = '1.7'
// Specify the Kotlin libraries that code is compatible with
apiVersion = '1.7'
// Note that we Need to use a version of Kotlin that will be compatible with the Corda API.
// Currently that is developed in Kotlin 1.7 so picking the same version ensures compatibility with that.
// Specify the version of Java to target.
jvmTarget = javaVersion
// Needed for reflection to work correctly.
javaParameters = true
// -Xjvm-default determines how Kotlin supports default methods.
// JetBrains currently recommends developers use -Xjvm-default=all
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-default/
freeCompilerArgs += [
"-Xjvm-default=all"
]
}
}
*/
// Declare the set of Kotlin compiler options we need to build a CorDapp. // Declare the set of Kotlin compiler options we need to build a CorDapp.
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
@ -84,8 +54,6 @@ tasks.withType(JavaCompile) {
] ]
} }
repositories { repositories {
// All dependencies are held in Maven Central // All dependencies are held in Maven Central
mavenCentral() mavenCentral()
@ -95,18 +63,11 @@ repositories {
// A cordaProvided declaration is required for anything that we use that the Corda API provides. // A cordaProvided declaration is required for anything that we use that the Corda API provides.
// This is required to allow us to build CorDapp modules as OSGi bundles that CPI and CPB files are built on. // This is required to allow us to build CorDapp modules as OSGi bundles that CPI and CPB files are built on.
dependencies { dependencies {
// We need a version of kotlin-stdlib-jdk8 built as an OSGi bundle, this is "kotlin-stdlib-jdk8-osgi".
// R3 builds kotlin-stdlib-jdk8-osgi from Kotlin's kotlin-stdlib-jdk8.
// NB:
// Kotlin's kotlin-osgi-bundle does not provide all of the Kotlin API that is required,
// There is no kotlin-stdlib-jdk11, but one is not needed even though we are targetting Java 11.
cordaProvided 'net.corda.kotlin:kotlin-stdlib-jdk8-osgi'
// Declare a "platform" so that we use the correct set of dependency versions for the version of the // Declare a "platform" so that we use the correct set of dependency versions for the version of the
// Corda API specified. // Corda API specified.
cordaProvided platform("net.corda:corda-api:$cordaApiVersion") cordaProvided platform("net.corda:corda-api:$cordaApiVersion")
// If using transistive dependencies this will provide most of Corda-API: // If using transistive dependencies this will provide most of the Corda-API:
// cordaProvided 'net.corda:corda-application' // cordaProvided 'net.corda:corda-application'
// Alternatively we can explicitly specify all our Corda-API dependencies: // Alternatively we can explicitly specify all our Corda-API dependencies:
@ -135,9 +96,7 @@ dependencies {
// Optional but used by exmaple tests. // Optional but used by exmaple tests.
testImplementation "org.mockito:mockito-core:$mockitoVersion" testImplementation "org.mockito:mockito-core:$mockitoVersion"
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion"
} }

View File

@ -3,15 +3,15 @@ package com.r3.developers.csdetemplate;
import net.corda.v5.base.annotations.CordaSerializable; import net.corda.v5.base.annotations.CordaSerializable;
import net.corda.v5.base.types.MemberX500Name; import net.corda.v5.base.types.MemberX500Name;
// // A class which will contain a message, It must be marked with @CordaSerializable for Corda // A class which will contain a message, It must be marked with @CordaSerializable for Corda
//// to be able to send from one virtual node to another. // to be able to send from one virtual node to another.
@CordaSerializable @CordaSerializable
public class Message { public class Message {
// public Message() {}
public Message(MemberX500Name sender, String message) { public Message(MemberX500Name sender, String message) {
this.sender = sender; this.sender = sender;
this.message = message; this.message = message;
} }
public MemberX500Name getSender() { public MemberX500Name getSender() {
return sender; return sender;
} }

View File

@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory;
// MyFirstFlow is an initiating flow, it's corresponding responder flow is called MyFirstFlowResponder (defined below) // MyFirstFlow is an initiating flow, it's corresponding responder flow is called MyFirstFlowResponder (defined below)
// to link the two sides of the flow together they need to have the same protocol. // to link the two sides of the flow together they need to have the same protocol.
@InitiatingFlow(protocol = "another-flow") @InitiatingFlow(protocol = "my-first-flow")
// MyFirstFlow should inherit from RPCStartableFlow, which tells Corda it can be started via an RPC call // MyFirstFlow should inherit from RPCStartableFlow, which tells Corda it can be started via an RPC call
public class MyFirstFlow implements RPCStartableFlow { public class MyFirstFlow implements RPCStartableFlow {
@ -26,27 +26,27 @@ public class MyFirstFlow implements RPCStartableFlow {
// JsonMarshallingService provides a Service for manipulating json // JsonMarshallingService provides a Service for manipulating json
@CordaInject @CordaInject
JsonMarshallingService jsonMarshallingService; public JsonMarshallingService jsonMarshallingService;
// FlowMessaging provides a service for establishing flow sessions between Virtual Nodes and // FlowMessaging provides a service for establishing flow sessions between Virtual Nodes and
// sending and receiving payloads between them // sending and receiving payloads between them
@CordaInject @CordaInject
FlowMessaging flowMessaging; public FlowMessaging flowMessaging;
// MemberLookup provides a service for looking up information about members of the Virtual Network which // MemberLookup provides a service for looking up information about members of the Virtual Network which
// this CorDapp is operating in. // this CorDapp is operating in.
@CordaInject @CordaInject
MemberLookup memberLookup; public MemberLookup memberLookup;
public MyFirstFlow() {} public MyFirstFlow() {}
// When a flow is invoked it's call() method is called. // When a flow is invoked its call() method is called.
// call() methods must be marked as @Suspendable, this allows Corda to pause mid-execution to wait // call() methods must be marked as @Suspendable, this allows Corda to pause mid-execution to wait
// for a response from the other flows and services // for a response from the other flows and services
@NotNull @NotNull
@Suspendable @Suspendable
@Override @Override
public String call(@NotNull RPCRequestData requestBody) { public String call(RPCRequestData requestBody) {
// Useful logging to follow what's happening in the console or logs // Useful logging to follow what's happening in the console or logs
log.info("MFF: MyFirstFlow.call() called"); log.info("MFF: MyFirstFlow.call() called");

View File

@ -11,9 +11,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
// MyFirstFlowResponder is a responder flow, it's corresponding initiating flow is called MyFirstFlow (defined above) // MyFirstFlowResponder is a responder flow, its corresponding initiating flow is called MyFirstFlow (defined in MyFirstFlow.java)
// to link the two sides of the flow together they need to have the same protocol. // to link the two sides of the flow together they need to have the same protocol.
@InitiatedBy(protocol = "another-flow") @InitiatedBy(protocol = "my-first-flow")
// Responder flows must inherit from ResponderFlow // Responder flows must inherit from ResponderFlow
public class MyFirstFlowResponder implements ResponderFlow { public class MyFirstFlowResponder implements ResponderFlow {
@ -23,14 +23,14 @@ public class MyFirstFlowResponder implements ResponderFlow {
// MemberLookup provides a service for looking up information about members of the Virtual Network which // MemberLookup provides a service for looking up information about members of the Virtual Network which
// this CorDapp is operating in. // this CorDapp is operating in.
@CordaInject @CordaInject
MemberLookup memberLookup; public MemberLookup memberLookup;
public MyFirstFlowResponder() {} public MyFirstFlowResponder() {}
// Responder flows are invoked when an initiating flow makes a call via a session set up with the Virtual // Responder flows are invoked when an initiating flow makes a call via a session set up with the Virtual
// node hosting the Responder flow. When a responder flow is invoked it's call() method is called. // node hosting the Responder flow. When a responder flow is invoked its call() method is called.
// call() methods must be marked as @Suspendable, this allows Corda to pause mid-execution to wait // call() methods must be marked as @Suspendable, this allows Corda to pause mid-execution to wait
// for a response from the other flows and services/ // for a response from the other flows and services.
// The Call method has the flow session passed in as a parameter by Corda so the session is available to // The Call method has the flow session passed in as a parameter by Corda so the session is available to
// responder flow code, you don't need to inject the FlowMessaging service. // responder flow code, you don't need to inject the FlowMessaging service.
@Suspendable @Suspendable

View File

@ -2,20 +2,14 @@ package com.r3.developers.csdetemplate;
import net.corda.v5.base.types.MemberX500Name; import net.corda.v5.base.types.MemberX500Name;
// // A class to hold the arguments required to start the flow // A class to hold the arguments required to start the flow
//class MyFirstFlowStartArgs(val otherMember: MemberX500Name)
public class MyFirstFlowStartArgs { public class MyFirstFlowStartArgs {
public MemberX500Name otherMember; public MemberX500Name otherMember;
public MemberX500Name getOtherMember() {
return otherMember;
}
public MyFirstFlowStartArgs(MemberX500Name otherMember) { public MyFirstFlowStartArgs(MemberX500Name otherMember) {
this.otherMember = otherMember; this.otherMember = otherMember;
} }
// Without the following we get // The JSON Marshalling Service, which handles serialisation, needs this constructor.
// "Cannot construct instance of `com.r3.developers.csdetemplate.MyFirstFlowStartArgs` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (String)\"{\"otherMember\":\"CN=Bob, OU=Test Dept, O=R3, L=London, C=GB\"}\"; line: 1, column: 2]"
public MyFirstFlowStartArgs() {} public MyFirstFlowStartArgs() {}
} }

View File

@ -1,6 +1,5 @@
package com.r3.developers.csdetemplate; package com.r3.developers.csdetemplate;
import net.corda.simulator.HoldingIdentity; import net.corda.simulator.HoldingIdentity;
import net.corda.simulator.RequestData; import net.corda.simulator.RequestData;
import net.corda.simulator.SimulatedVirtualNode; import net.corda.simulator.SimulatedVirtualNode;
@ -16,8 +15,8 @@ class MyFirstFlowTest {
private MemberX500Name bobX500 = MemberX500Name.parse("CN=Bob, OU=Test Dept, O=R3, L=London, C=GB"); private MemberX500Name bobX500 = MemberX500Name.parse("CN=Bob, OU=Test Dept, O=R3, L=London, C=GB");
@Test @Test
@SuppressWarnings("unchecked")
public void test_that_MyFirstFLow_returns_correct_message() { public void test_that_MyFirstFLow_returns_correct_message() {
// Instantiate an instance of the Simulator // Instantiate an instance of the Simulator
Simulator simulator = new Simulator(); Simulator simulator = new Simulator();
@ -26,7 +25,7 @@ class MyFirstFlowTest {
HoldingIdentity bobHoldingID = HoldingIdentity.Companion.create(bobX500); HoldingIdentity bobHoldingID = HoldingIdentity.Companion.create(bobX500);
// Create Alice and Bob's virtual nodes, including the Class's of the flows which will be registered on each node. // Create Alice and Bob's virtual nodes, including the Class's of the flows which will be registered on each node.
// We don't assign Bob's virtual node to a val because we don't need it for this particular test. // We don't assign Bob's virtual node to a variable because we don't need it for this particular test.
SimulatedVirtualNode aliceVN = simulator.createVirtualNode(aliceHoldingID, MyFirstFlow.class); SimulatedVirtualNode aliceVN = simulator.createVirtualNode(aliceHoldingID, MyFirstFlow.class);
simulator.createVirtualNode(bobHoldingID, MyFirstFlowResponder.class); simulator.createVirtualNode(bobHoldingID, MyFirstFlowResponder.class);
@ -36,7 +35,7 @@ class MyFirstFlowTest {
// Create a requestData object // Create a requestData object
RequestData requestData = RequestData.Companion.create( RequestData requestData = RequestData.Companion.create(
"request no 1", // A unique reference for the instance of the flow request "request no 1", // A unique reference for the instance of the flow request
MyFirstFlow.class, // The name of the flow class which is to be started MyFirstFlow.class, // The name of the flow class which is to be started
myFirstFlowStartArgs // The object which contains the start arguments of the flow myFirstFlowStartArgs // The object which contains the start arguments of the flow
); );