From 62a27d545cebd4c81539163fb5b96211ba290921 Mon Sep 17 00:00:00 2001 From: McXD <74167137+McXD@users.noreply.github.com> Date: Fri, 18 Jun 2021 10:22:01 +0800 Subject: [PATCH 1/5] added REST client --- Accounts/supplychain/README.md | 89 ++++++- Accounts/supplychain/build.gradle | 2 + Accounts/supplychain/clients/build.gradle | 45 ++++ .../supplychain/clients/Controller.java | 234 ++++++++++++++++++ .../clients/NodeRPCConnection.java | 44 ++++ .../samples/supplychain/clients/Starter.java | 9 + .../supplychain/clients/models/Account.java | 34 +++ .../clients/models/AccountShare.java | 48 ++++ .../supplychain/clients/models/Cargo.java | 39 +++ .../supplychain/clients/models/Inbox.java | 41 +++ .../clients/models/InternalMessage.java | 49 ++++ .../supplychain/clients/models/Invoice.java | 39 +++ .../supplychain/clients/models/Payment.java | 39 +++ .../clients/models/ShippingRequest.java | 39 +++ .../supplychain/clients/models/Status.java | 19 ++ .../src/main/resources/application.properties | 6 + Accounts/supplychain/settings.gradle | 3 +- 17 files changed, 775 insertions(+), 4 deletions(-) create mode 100644 Accounts/supplychain/clients/build.gradle create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Account.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/AccountShare.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Cargo.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Inbox.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/InternalMessage.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Invoice.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Payment.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/ShippingRequest.java create mode 100644 Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Status.java create mode 100644 Accounts/supplychain/clients/src/main/resources/application.properties diff --git a/Accounts/supplychain/README.md b/Accounts/supplychain/README.md index cc8730a4..32009f2f 100644 --- a/Accounts/supplychain/README.md +++ b/Accounts/supplychain/README.md @@ -100,6 +100,89 @@ flow start SendCargo pickupFrom: SellerInventory, shipTo: BuyerWarehouse, cargo: ## Now, the entire business chain is completed. - - - +# REST API Overview + +A single web endpoint exposes REST APIs for operations on 3 Nodes: `Buyer`, `Seller` and `ShippingCo`. + +## Operations + +* Create an account on any of the three nodes + * **Method**: `POST` + * **URL**: `/api/createAcct` + * **Body**: `Account` + * **Response**: `Status` +* Share account on any of the three nodes + * **Method**: `POST` + * **URL**: `/api/shareAcct` + * **Body**: `AccountShare` + * **Response**: `Status` +* Send Invoice on `Seller` + * **Method**: `POST` + * **URL**: `/api/sendInvoice` + * **Body**: `Invoice` + * **Response**: `Status` + * **Note**: the flow operation is delegated to `Seller` +* Send internal messages on any of the three nodes + * **Method**: `POST` + * **URL**: `/api/sendInternalMessage` + * **Body**: `InternalMessage` + * **Response**: `Status` +* Send payment on `Buyer` + * **Method**: `POST` + * **URL**: `/api/sendPayment` + * **Body**: `Payment` + * **Response**: `Status` + * **Note**: the flow operation is delegated to `Buyer` +* Send shipping request on `Seller` + * **Method**: `POST` + * **URL**: `/api/sendShippingRequest` + * **Body**: `ShippingRequest` + * **Response**: `Status` + * **Note**: the flow operation is delegated to `Buyer` +* Send cargo on `ShippingCo` + * **Method**: `POST` + * **URL**: `/api/sendCargo` + * **Body**: `Cargo` + * **Response**: `Status` + * **Note**: the flow operation is delegated to `ShippingCo` +* Additionally, for monitoring, view inbox on any of the three nodes for their accounts + * **Method**: `GET` + * **URL**: `/api/inbox?node=$node&acctName=$acctName` + * **Response**: `Inbox` + +## Required Abstract Data Model + +* Account + * onNode: String + * acctName: String +* AccountShare + * senderNode: String + * receiverNode: String + * acctName: String +* Invoice + * whoAmI : String + * whereTo : String + * amount : int32 +* InternalMessage + * onNode: String + * whoAmI : String + * whereTo : String + * message : String +* Payment + * whoAmI: String + * whereTo: String + * amount: int32 +* ShippingRequest + * whoAmI: String + * whereTo: String + * cargo: String +* Cargo + * pickUpFrom: String + * whereTo: String + * cargo: String +* Inbox + * fromNode: String + * ofAcct: String + * messages: List +* Status + * success: boolean diff --git a/Accounts/supplychain/build.gradle b/Accounts/supplychain/build.gradle index 67dde5d5..76528329 100644 --- a/Accounts/supplychain/build.gradle +++ b/Accounts/supplychain/build.gradle @@ -34,6 +34,8 @@ buildscript { classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version" classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version" classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version" + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.2.RELEASE") + } } diff --git a/Accounts/supplychain/clients/build.gradle b/Accounts/supplychain/clients/build.gradle new file mode 100644 index 00000000..6ab90e91 --- /dev/null +++ b/Accounts/supplychain/clients/build.gradle @@ -0,0 +1,45 @@ +plugins { + id 'org.springframework.boot' + id 'io.spring.dependency-management' + id 'application' + id 'net.corda.plugins.cordapp' +} + +group 'net.corda' +version '1.0' + +mainClassName="net.corda.samples.supplychain.clients.Starter" + +repositories { + mavenCentral() +} + +dependencies { + // Corda dependencies. + compile "$corda_core_release_group:corda-core:$corda_core_release_version" + compile "$corda_core_release_group:corda-rpc:$corda_core_release_version" + cordaRuntime "$corda_release_group:corda:$corda_release_version" + testCompile "$corda_release_group:corda-node-driver:$corda_release_version" + + //Account dependencies + cordaCompile "$confidential_id_release_group:ci-workflows:$confidential_id_release_version" + cordaCompile "$accounts_release_group:accounts-workflows:$accounts_release_version" + + // CorDapp dependencies. + compile project(":contracts") + compile project(":workflows") + + compileOnly("org.springframework.boot:spring-boot-devtools") + implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +test { + useJUnitPlatform() +} + +task runServer(type: JavaExec){ + description = "Deploying Server" + classpath = sourceSets.main.runtimeClasspath + main = "net.corda.samples.supplychain.clients.Starter" +} \ No newline at end of file diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java new file mode 100644 index 00000000..a45f3d8c --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java @@ -0,0 +1,234 @@ +package net.corda.samples.supplychain.clients; + +import net.corda.core.messaging.CordaRPCOps; +import net.corda.samples.supplychain.accountUtilities.CreateNewAccount; +import net.corda.samples.supplychain.accountUtilities.ShareAccountTo; +import net.corda.samples.supplychain.accountUtilities.ViewInboxByAccount; +import net.corda.samples.supplychain.clients.models.*; +import net.corda.samples.supplychain.flows.SendCargo; +import net.corda.samples.supplychain.flows.SendInvoice; +import net.corda.samples.supplychain.flows.SendPayment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.concurrent.ExecutionException; + +@RestController +@RequestMapping("/api") +public class Controller implements ApplicationContextAware { + private CordaRPCOps buyerProxy; + private CordaRPCOps sellerProxy; + private CordaRPCOps shipperProxy; + Logger logger = LoggerFactory.getLogger(Controller.class); + + @PostMapping("createAcct") + public Status createAcct(@RequestBody Account account){ + String onNode = account.getOnNode(); + Status status = new Status(true); + + logger.info("createAcct(Account) " + account.toString()); + + switch (onNode) { + case "buyer": + buyerProxy.startFlowDynamic(CreateNewAccount.class, account.getAcctName()); + break; + case "seller": + sellerProxy.startFlowDynamic(CreateNewAccount.class, account.getAcctName()); + break; + case "shipper": + shipperProxy.startFlowDynamic(CreateNewAccount.class, account.getAcctName()); + break; + default: + status.setSuccess(false); + logger.info("createAcct(Account) received unrecognizable node: " + onNode); + break; + } + + return status; + } + + @PostMapping("shareAcct") + public Status shareAcct(@RequestBody AccountShare accountShare){ + Status status = new Status(true); + String receiver = accountShare.getReceiverNode(); + String sender = accountShare.getSenderNode(); + String acct = accountShare.getAcctName(); + + CordaRPCOps senderNode = null, receiverNode = null; + + logger.info("shareAcct(AccountShare) " + accountShare.toString()); + + switch (sender) { + case "buyer": + senderNode = this.buyerProxy; + break; + case "seller": + senderNode = this.sellerProxy; + break; + case "shipper": + senderNode = this.shipperProxy; + break; + default: + status.setSuccess(false); + logger.info("createAcct(Account) received unrecognizable node: " + sender); + break; + } + + switch (receiver) { + case "buyer": + receiverNode = this.buyerProxy; + break; + case "seller": + receiverNode = this.sellerProxy; + break; + case "shipper": + receiverNode = this.shipperProxy; + break; + default: + status.setSuccess(false); + logger.info("createAcct(Account) received unrecognizable node: " + receiver); + break; + } + + if (senderNode != null && receiverNode != null){ + String ret = null; + try { + ret = senderNode.startFlowDynamic(ShareAccountTo.class, acct, receiverNode.nodeInfo().getLegalIdentities().get(0)).getReturnValue().get(); + } catch (InterruptedException | ExecutionException e) { + logger.info(e.getMessage()); + } + logger.info(ret); + } + + return status; + } + + @PostMapping("/sendInvoice") + public Status sendInvoice(@RequestBody Invoice invoice){ + Status status = new Status(true); + + try{ + sellerProxy.startFlowDynamic(SendInvoice.class, invoice.getWhoAmI(), invoice.getWhereTo(), invoice.getAmount()); + }catch(Exception e){ + logger.info(e.getMessage()); + status.setSuccess(false); + } + + return status; + } + + @PostMapping("/sendInternalMessage") + public Status sendInternalMessage(@RequestBody InternalMessage message){ + Status status = new Status(true); + + CordaRPCOps node = findRPCOps(message.getOnNode()); + if (node == null) { + status.setSuccess(false); + return status; + } + + try{ + String ret = node.startFlowDynamic(net.corda.samples.supplychain.flows.InternalMessage.class, message.getWhoAmI(), message.getWhereTo(), message.getMessage()).getReturnValue().get(); + }catch (Exception e){ + logger.info(e.getMessage()); + status.setSuccess(false); + } + + return status; + } + + @PostMapping("/sendPayment") + public Status sendPayment(@RequestBody Payment payment){ + Status status = new Status(true); + + try{ + buyerProxy.startFlowDynamic(SendPayment.class, payment.getWhoAmI(), payment.getWhereTo(), payment.getAmount()); + }catch(Exception e){ + logger.info(e.getMessage()); + status.setSuccess(false); + } + + return status; + } + + @PostMapping("/sendShippingRequest") + public Status sendShippingRequest(@RequestBody ShippingRequest shippingRequest){ + Status status = new Status(true); + + try{ + sellerProxy.startFlowDynamic(SendPayment.class, shippingRequest.getWhoAmI(), shippingRequest.getWhereTo(), shipperProxy.nodeInfo().getLegalIdentities().get(0), shippingRequest.getCargo()); + }catch(Exception e){ + logger.info(e.getMessage()); + status.setSuccess(false); + } + + return status; + } + + @PostMapping("/sendCargo") + public Status sendCargo(@RequestBody Cargo cargo){ + Status status = new Status(true); + + try{ + String ret = shipperProxy.startFlowDynamic(SendCargo.class, cargo.getPickUpFrom(), cargo.getWhereTo(), cargo.getCargo()).getReturnValue().get(); + logger.info(ret); + }catch(Exception e){ + logger.info(e.getMessage()); + status.setSuccess(false); + } + + return status; + } + + @GetMapping("/inbox") + public Inbox getInbox(@RequestParam("node") String onNode, @RequestParam("acctName") String acctName){ + CordaRPCOps proxy = findRPCOps(onNode); + if (proxy == null) return null; + + Inbox inbox = new Inbox(); + try{ + List ret = proxy.startFlowDynamic(ViewInboxByAccount.class, acctName).getReturnValue().get(); + inbox.setMessage(ret); + inbox.setFromNode(onNode); + inbox.setOfAcct(acctName); + }catch(Exception e){ + logger.info(e.getMessage()); + return null; + } + + return inbox; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.buyerProxy = applicationContext.getBean("buyerProxy", CordaRPCOps.class); + this.sellerProxy = applicationContext.getBean("sellerProxy", CordaRPCOps.class); + this.shipperProxy = applicationContext.getBean("shipperProxy", CordaRPCOps.class); + } + + private CordaRPCOps findRPCOps(String nodeName){ + CordaRPCOps ret = null; + + switch (nodeName) { + case "buyer": + ret = this.buyerProxy; + break; + case "seller": + ret = this.sellerProxy; + break; + case "shipper": + ret = this.shipperProxy; + break; + default: + logger.info("Unrecognizable node: " + nodeName); + break; + } + + return ret; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java new file mode 100644 index 00000000..1314b5d0 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java @@ -0,0 +1,44 @@ +package net.corda.samples.supplychain.clients; + +import net.corda.client.rpc.CordaRPCClient; +import net.corda.client.rpc.CordaRPCConnection; +import net.corda.core.messaging.CordaRPCOps; +import net.corda.core.utilities.NetworkHostAndPort; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class NodeRPCConnection { + @Value("${config.rpc.host}") + private static String host; + @Value("${config.rpc.username}") + private static String username; + @Value("${config.rpc.password}") + private static String password; + + @Bean(name = "buyerProxy") + public static CordaRPCOps buyerProxy(@Value("$config.rpc.buyer.port") int port){ + NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); + CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); + CordaRPCConnection connection = rpcClient.start(username, password); + return connection.getProxy(); + } + + @Bean(name = "sellerProxy") + public static CordaRPCOps sellerProxy(@Value("$config.rpc.seller.port") int port){ + NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); + CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); + CordaRPCConnection connection = rpcClient.start(username, password); + return connection.getProxy(); + } + + @Bean(name = "shipperProxy") + public static CordaRPCOps shipperProxy(@Value("$config.rpc.shipper.port") int port){ + NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); + CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); + CordaRPCConnection connection = rpcClient.start(username, password); + return connection.getProxy(); + } + +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java new file mode 100644 index 00000000..210a1ef4 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java @@ -0,0 +1,9 @@ +package net.corda.samples.supplychain.clients; + +import org.springframework.boot.SpringApplication; + +public class Starter { + public static void main(String[] args){ + SpringApplication.run(Starter.class, args); + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Account.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Account.java new file mode 100644 index 00000000..821ed895 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Account.java @@ -0,0 +1,34 @@ +package net.corda.samples.supplychain.clients.models; + +public class Account { + private String onNode; + private String acctName; + + public Account(){} + + public Account(String onNode, String acctName) { + this.onNode = onNode; + this.acctName = acctName; + } + + public String getOnNode() { + return onNode; + } + + public void setOnNode(String onNode) { + this.onNode = onNode; + } + + public String getAcctName() { + return acctName; + } + + public void setAcctName(String acctName) { + this.acctName = acctName; + } + + @Override + public String toString(){ + return String.format("{onNode: %s, acctName: %s}", onNode, acctName); + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/AccountShare.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/AccountShare.java new file mode 100644 index 00000000..ea1eb4fd --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/AccountShare.java @@ -0,0 +1,48 @@ +package net.corda.samples.supplychain.clients.models; + +public class AccountShare { + private String senderNode; + private String receiverNode; + private String acctName; + + public AccountShare(){} + + public AccountShare(String senderNode, String receiverNode, String acctName) { + this.senderNode = senderNode; + this.receiverNode = receiverNode; + this.acctName = acctName; + } + + public String getSenderNode() { + return senderNode; + } + + public void setSenderNode(String senderNode) { + this.senderNode = senderNode; + } + + public String getReceiverNode() { + return receiverNode; + } + + public void setReceiverNode(String receiverNode) { + this.receiverNode = receiverNode; + } + + public String getAcctName() { + return acctName; + } + + public void setAcctName(String acctName) { + this.acctName = acctName; + } + + @Override + public String toString() { + return "AccountShare{" + + "senderNode='" + senderNode + '\'' + + ", receiverNode='" + receiverNode + '\'' + + ", acctName='" + acctName + '\'' + + '}'; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Cargo.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Cargo.java new file mode 100644 index 00000000..b4bbad39 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Cargo.java @@ -0,0 +1,39 @@ +package net.corda.samples.supplychain.clients.models; + +public class Cargo { + private String pickUpFrom; + private String whereTo; + private String Cargo; + + public Cargo() {} + + public Cargo(String pickUpFrom, String whereTo, String cargo) { + this.pickUpFrom = pickUpFrom; + this.whereTo = whereTo; + Cargo = cargo; + } + + public String getPickUpFrom() { + return pickUpFrom; + } + + public void setPickUpFrom(String pickUpFrom) { + this.pickUpFrom = pickUpFrom; + } + + public String getWhereTo() { + return whereTo; + } + + public void setWhereTo(String whereTo) { + this.whereTo = whereTo; + } + + public String getCargo() { + return Cargo; + } + + public void setCargo(String cargo) { + Cargo = cargo; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Inbox.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Inbox.java new file mode 100644 index 00000000..5a6d75c2 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Inbox.java @@ -0,0 +1,41 @@ +package net.corda.samples.supplychain.clients.models; + +import java.util.List; + +public class Inbox { + private String fromNode; + private String ofAcct; + private List messages; + + public Inbox() {} + + public Inbox(String fromNode, String ofAcct, List messages) { + this.fromNode = fromNode; + this.ofAcct = ofAcct; + this.messages = messages; + } + + public String getFromNode() { + return fromNode; + } + + public void setFromNode(String fromNode) { + this.fromNode = fromNode; + } + + public String getOfAcct() { + return ofAcct; + } + + public void setOfAcct(String ofAcct) { + this.ofAcct = ofAcct; + } + + public List getMessage() { + return messages; + } + + public void setMessage(List messages) { + this.messages = messages; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/InternalMessage.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/InternalMessage.java new file mode 100644 index 00000000..d4bba70b --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/InternalMessage.java @@ -0,0 +1,49 @@ +package net.corda.samples.supplychain.clients.models; + +public class InternalMessage { + private String onNode; + private String whoAmI; + private String whereTo; + private String message; + + public InternalMessage(){} + + public InternalMessage(String onNode, String whoAmI, String whereTo, String message) { + this.onNode = onNode; + this.whoAmI = whoAmI; + this.whereTo = whereTo; + this.message = message; + } + + public String getOnNode() { + return onNode; + } + + public void setOnNode(String onNode) { + this.onNode = onNode; + } + + public String getWhoAmI() { + return whoAmI; + } + + public void setWhoAmI(String whoAmI) { + this.whoAmI = whoAmI; + } + + public String getWhereTo() { + return whereTo; + } + + public void setWhereTo(String whereTo) { + this.whereTo = whereTo; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Invoice.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Invoice.java new file mode 100644 index 00000000..ec6eb96e --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Invoice.java @@ -0,0 +1,39 @@ +package net.corda.samples.supplychain.clients.models; + +public class Invoice { + private String whoAmI; + private String whereTo; + private int amount; + + public Invoice(){} + + public Invoice(String whoAmI, String whereTo, int amount) { + this.whoAmI = whoAmI; + this.whereTo = whereTo; + this.amount = amount; + } + + public String getWhoAmI() { + return whoAmI; + } + + public void setWhoAmI(String whoAmI) { + this.whoAmI = whoAmI; + } + + public String getWhereTo() { + return whereTo; + } + + public void setWhereTo(String whereTo) { + this.whereTo = whereTo; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Payment.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Payment.java new file mode 100644 index 00000000..ea02719b --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Payment.java @@ -0,0 +1,39 @@ +package net.corda.samples.supplychain.clients.models; + +public class Payment { + private String whoAmI; + private String whereTo; + private int amount; + + public Payment(){} + + public Payment(String whoAmI, String whereTo, int amount) { + this.whoAmI = whoAmI; + this.whereTo = whereTo; + this.amount = amount; + } + + public String getWhoAmI() { + return whoAmI; + } + + public void setWhoAmI(String whoAmI) { + this.whoAmI = whoAmI; + } + + public String getWhereTo() { + return whereTo; + } + + public void setWhereTo(String whereTo) { + this.whereTo = whereTo; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/ShippingRequest.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/ShippingRequest.java new file mode 100644 index 00000000..03971860 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/ShippingRequest.java @@ -0,0 +1,39 @@ +package net.corda.samples.supplychain.clients.models; + +public class ShippingRequest { + private String whoAmI; + private String whereTo; + private String Cargo; + + public ShippingRequest(){} + + public ShippingRequest(String whoAmI, String whereTo, String cargo) { + this.whoAmI = whoAmI; + this.whereTo = whereTo; + Cargo = cargo; + } + + public String getWhoAmI() { + return whoAmI; + } + + public void setWhoAmI(String whoAmI) { + this.whoAmI = whoAmI; + } + + public String getWhereTo() { + return whereTo; + } + + public void setWhereTo(String whereTo) { + this.whereTo = whereTo; + } + + public String getCargo() { + return Cargo; + } + + public void setCargo(String cargo) { + Cargo = cargo; + } +} diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Status.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Status.java new file mode 100644 index 00000000..7992666e --- /dev/null +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/models/Status.java @@ -0,0 +1,19 @@ +package net.corda.samples.supplychain.clients.models; + +public class Status { + private boolean success; + + public Status() {} + + public Status(boolean success) { + this.success = success; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } +} diff --git a/Accounts/supplychain/clients/src/main/resources/application.properties b/Accounts/supplychain/clients/src/main/resources/application.properties new file mode 100644 index 00000000..81bdcb82 --- /dev/null +++ b/Accounts/supplychain/clients/src/main/resources/application.properties @@ -0,0 +1,6 @@ +config.rpc.host=localhost +config.rpc.username=user1 +config.rpc.password=test +config.rpc.buyer.port=10006 +config.rpc.seller.port=10009 +config.rpc.shipper.port=10011 \ No newline at end of file diff --git a/Accounts/supplychain/settings.gradle b/Accounts/supplychain/settings.gradle index 2514aca2..d58d1730 100644 --- a/Accounts/supplychain/settings.gradle +++ b/Accounts/supplychain/settings.gradle @@ -1,3 +1,4 @@ include 'workflows' include 'contracts' -include 'clients' \ No newline at end of file +include 'clients' + From 79ed175bf6c03c0499513b20ab6af529a35456a5 Mon Sep 17 00:00:00 2001 From: McXD <74167137+McXD@users.noreply.github.com> Date: Fri, 18 Jun 2021 12:20:08 +0800 Subject: [PATCH 2/5] added open api definition --- Accounts/supplychain/openapi.yml | 185 +++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 Accounts/supplychain/openapi.yml diff --git a/Accounts/supplychain/openapi.yml b/Accounts/supplychain/openapi.yml new file mode 100644 index 00000000..631aec61 --- /dev/null +++ b/Accounts/supplychain/openapi.yml @@ -0,0 +1,185 @@ +openapi: '3.0.2' +info: + title: Supplychain API + version: '1.0' +servers: + - url: https://localhost:8080 +paths: + /api/createAcct: + post: + requestBody: + $ref: '#/components/schemas/Account' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/shareAcct: + post: + requestBody: + $ref: '#/components/schemas/AccountShare' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/sendInternalMessage: + post: + requestBody: + $ref: '#/components/schemas/InternalMessage' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/snedPayment: + post: + requestBody: + $ref: '#/components/schemas/Payment' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/sendShippingRequest: + post: + requestBody: + $ref: '#/components/schemas/ShippingRequest' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/sendCargo: + post: + requestBody: + $ref: '#/components/schemas/Cargo' + responses: + '200': + $ref: '#/components/schemas/Status' + /api/inbox: + get: + parameters: + - in: query + name: node + schema: + type: string + description: node the account resides on + - in: query + name: acctName + schema: + type: string + description: the account name + responses: + '200': + $ref: '#/components/schemas/Inbox' +components: + schemas: + Account: + type: object + required: + - acctName + - onNode + properties: + acctName: + type: string + onNode: + type: string + AccountShare: + type: object + required: + - senderNode + - receiverNode + - acctName + properties: + senderNode: + type: string + receiverNode: + type: string + acctName: + type: string + Invoice: + type: object + required: + - whoAmI + - whereTo + - amount + properties: + whoAmI: + type: string + whereTo: + type: string + amuont: + type: integer + format: int32 + InternalMessage: + type: object + required: + - onNode + - whoAmI + - whereTo + - message + properties: + onNode: + type: string + whoAmI: + type: string + whereTo: + type: string + message: + type: string + Payment: + type: object + required: + - whoAmI + - whereTo + - amount + properties: + whoAmI: + type: string + whereTo: + type: string + amuont: + type: integer + format: int32 + ShippingRequest: + type: object + required: + - whoAmI + - whereTo + - cargo + properties: + whoAmI: + type: string + whereTo: + type: string + cargo: + type: string + Cargo: + type: object + required: + - pickUpFrom + - whereTo + - cargo + properties: + pickUpFrom: + type: string + whereTo: + type: string + cargo: + type: string + Inbox: + type: object + required: + - fromNode + - ofAcct + - messages + properties: + fromNode: + type: string + ofAcct: + type: string + messages: + type: array + items: + type: string + Status: + type: object + required: + - success + properties: + success: + type: boolean + + + \ No newline at end of file From f3a4722b744202186fb311002f474dacb8cdf3b1 Mon Sep 17 00:00:00 2001 From: McXD <74167137+McXD@users.noreply.github.com> Date: Fri, 18 Jun 2021 12:25:56 +0800 Subject: [PATCH 3/5] added missing paths --- Accounts/supplychain/clients/build.gradle | 3 +++ .../supplychain/clients/NodeRPCConnection.java | 15 ++++++++------- .../samples/supplychain/clients/Starter.java | 2 ++ .../src/main/resources/application.properties | 12 ++++++------ Accounts/supplychain/openapi.yml | 7 +++++++ 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Accounts/supplychain/clients/build.gradle b/Accounts/supplychain/clients/build.gradle index 6ab90e91..ad08d01f 100644 --- a/Accounts/supplychain/clients/build.gradle +++ b/Accounts/supplychain/clients/build.gradle @@ -29,6 +29,9 @@ dependencies { compile project(":contracts") compile project(":workflows") + implementation ("org.apache.activemq:artemis-jms-server:2.6.2") + implementation ('javax.json:javax.json-api:1.1.4') + compileOnly("org.springframework.boot:spring-boot-devtools") implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java index 1314b5d0..7887f6a8 100644 --- a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/NodeRPCConnection.java @@ -7,18 +7,19 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; -@Configuration +@Component public class NodeRPCConnection { @Value("${config.rpc.host}") - private static String host; + private String host; @Value("${config.rpc.username}") - private static String username; + private String username; @Value("${config.rpc.password}") - private static String password; + private String password; @Bean(name = "buyerProxy") - public static CordaRPCOps buyerProxy(@Value("$config.rpc.buyer.port") int port){ + public CordaRPCOps buyerProxy(@Value("${config.rpc.buyer.port}") int port){ NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); CordaRPCConnection connection = rpcClient.start(username, password); @@ -26,7 +27,7 @@ public static CordaRPCOps buyerProxy(@Value("$config.rpc.buyer.port") int port){ } @Bean(name = "sellerProxy") - public static CordaRPCOps sellerProxy(@Value("$config.rpc.seller.port") int port){ + public CordaRPCOps sellerProxy(@Value("${config.rpc.seller.port}") int port){ NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); CordaRPCConnection connection = rpcClient.start(username, password); @@ -34,7 +35,7 @@ public static CordaRPCOps sellerProxy(@Value("$config.rpc.seller.port") int port } @Bean(name = "shipperProxy") - public static CordaRPCOps shipperProxy(@Value("$config.rpc.shipper.port") int port){ + public CordaRPCOps shipperProxy(@Value("${config.rpc.shipper.port}") int port){ NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, port); CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); CordaRPCConnection connection = rpcClient.start(username, password); diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java index 210a1ef4..afe7026b 100644 --- a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Starter.java @@ -1,7 +1,9 @@ package net.corda.samples.supplychain.clients; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +@SpringBootApplication public class Starter { public static void main(String[] args){ SpringApplication.run(Starter.class, args); diff --git a/Accounts/supplychain/clients/src/main/resources/application.properties b/Accounts/supplychain/clients/src/main/resources/application.properties index 81bdcb82..745a0157 100644 --- a/Accounts/supplychain/clients/src/main/resources/application.properties +++ b/Accounts/supplychain/clients/src/main/resources/application.properties @@ -1,6 +1,6 @@ -config.rpc.host=localhost -config.rpc.username=user1 -config.rpc.password=test -config.rpc.buyer.port=10006 -config.rpc.seller.port=10009 -config.rpc.shipper.port=10011 \ No newline at end of file +config.rpc.host = localhost +config.rpc.username = user1 +config.rpc.password = test +config.rpc.buyer.port = 10006 +config.rpc.seller.port = 10009 +config.rpc.shipper.port = 10011 \ No newline at end of file diff --git a/Accounts/supplychain/openapi.yml b/Accounts/supplychain/openapi.yml index 631aec61..e0fff232 100644 --- a/Accounts/supplychain/openapi.yml +++ b/Accounts/supplychain/openapi.yml @@ -26,6 +26,13 @@ paths: responses: '200': $ref: '#/components/schemas/Status' + /api/snedInvoice: + post: + requestBody: + $ref: '#/components/schemas/Invoice' + responses: + '200': + $ref: '#/components/schemas/Status' /api/snedPayment: post: requestBody: From a4bda690b68d79c3dbb8f0ab652453c444624bbc Mon Sep 17 00:00:00 2001 From: McXD <74167137+McXD@users.noreply.github.com> Date: Fri, 18 Jun 2021 12:41:38 +0800 Subject: [PATCH 4/5] fixed api definition bugs --- Accounts/supplychain/openapi.yml | 98 +++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/Accounts/supplychain/openapi.yml b/Accounts/supplychain/openapi.yml index e0fff232..0aae4568 100644 --- a/Accounts/supplychain/openapi.yml +++ b/Accounts/supplychain/openapi.yml @@ -8,52 +8,108 @@ paths: /api/createAcct: post: requestBody: - $ref: '#/components/schemas/Account' + description: Create an account on a node + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Account' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/shareAcct: post: requestBody: - $ref: '#/components/schemas/AccountShare' + description: Share an account + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/AccountShare' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/sendInternalMessage: post: requestBody: - $ref: '#/components/schemas/InternalMessage' + description: Send an internal message on a node + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/InternalMessage' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/snedInvoice: - post: - requestBody: - $ref: '#/components/schemas/Invoice' - responses: - '200': - $ref: '#/components/schemas/Status' + post: + requestBody: + description: Send invoice from seller to buyer + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Invoice' + responses: + '200': + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/snedPayment: post: requestBody: - $ref: '#/components/schemas/Payment' + description: Send payment from buyer to seller + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Payment' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/sendShippingRequest: post: requestBody: - $ref: '#/components/schemas/ShippingRequest' + description: Send a shipping request from seller to shippingCo + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/ShippingRequest' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/sendCargo: post: requestBody: - $ref: '#/components/schemas/Cargo' + description: Send cargo on shippingCo from seller to buyer + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Cargo' responses: '200': - $ref: '#/components/schemas/Status' + description: OK or not + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Status' /api/inbox: get: parameters: @@ -69,7 +125,11 @@ paths: description: the account name responses: '200': - $ref: '#/components/schemas/Inbox' + description: OK + content: + applicatoin/json: + schema: + $ref: '#/components/schemas/Inbox' components: schemas: Account: From d5479fa7c28204c01e9b08395fb79a15067c8e91 Mon Sep 17 00:00:00 2001 From: McXD <74167137+McXD@users.noreply.github.com> Date: Fri, 18 Jun 2021 13:18:43 +0800 Subject: [PATCH 5/5] bug fixes --- .../supplychain/clients/Controller.java | 2 +- Accounts/supplychain/openapi.yml | 42 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java index a45f3d8c..c377192a 100644 --- a/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java +++ b/Accounts/supplychain/clients/src/main/java/net/corda/samples/supplychain/clients/Controller.java @@ -161,7 +161,7 @@ public Status sendShippingRequest(@RequestBody ShippingRequest shippingRequest){ Status status = new Status(true); try{ - sellerProxy.startFlowDynamic(SendPayment.class, shippingRequest.getWhoAmI(), shippingRequest.getWhereTo(), shipperProxy.nodeInfo().getLegalIdentities().get(0), shippingRequest.getCargo()); + sellerProxy.startFlowDynamic(SendShippingRequest.class, shippingRequest.getWhoAmI(), shippingRequest.getWhereTo(), shipperProxy.nodeInfo().getLegalIdentities().get(0), shippingRequest.getCargo()); }catch(Exception e){ logger.info(e.getMessage()); status.setSuccess(false); diff --git a/Accounts/supplychain/openapi.yml b/Accounts/supplychain/openapi.yml index 0aae4568..aaff4860 100644 --- a/Accounts/supplychain/openapi.yml +++ b/Accounts/supplychain/openapi.yml @@ -10,14 +10,14 @@ paths: requestBody: description: Create an account on a node content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Account' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' /api/shareAcct: @@ -25,14 +25,14 @@ paths: requestBody: description: Share an account content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/AccountShare' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' /api/sendInternalMessage: @@ -40,44 +40,44 @@ paths: requestBody: description: Send an internal message on a node content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/InternalMessage' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' - /api/snedInvoice: + /api/sendInvoice: post: requestBody: description: Send invoice from seller to buyer content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Invoice' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' - /api/snedPayment: + /api/sendPayment: post: requestBody: description: Send payment from buyer to seller content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Payment' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' /api/sendShippingRequest: @@ -85,14 +85,14 @@ paths: requestBody: description: Send a shipping request from seller to shippingCo content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/ShippingRequest' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' /api/sendCargo: @@ -100,14 +100,14 @@ paths: requestBody: description: Send cargo on shippingCo from seller to buyer content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Cargo' responses: '200': description: OK or not content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Status' /api/inbox: @@ -127,7 +127,7 @@ paths: '200': description: OK content: - applicatoin/json: + application/json: schema: $ref: '#/components/schemas/Inbox' components: @@ -166,7 +166,7 @@ components: type: string whereTo: type: string - amuont: + amount: type: integer format: int32 InternalMessage: @@ -184,7 +184,7 @@ components: whereTo: type: string message: - type: string + type: string Payment: type: object required: @@ -196,7 +196,7 @@ components: type: string whereTo: type: string - amuont: + amount: type: integer format: int32 ShippingRequest: @@ -236,7 +236,7 @@ components: type: string ofAcct: type: string - messages: + message: type: array items: type: string