diff --git a/buildSrc/src/main/groovy/csde.gradle b/buildSrc/src/main/groovy/csde.gradle index 9e6c525..bef129c 100644 --- a/buildSrc/src/main/groovy/csde.gradle +++ b/buildSrc/src/main/groovy/csde.gradle @@ -47,7 +47,7 @@ configurations { // Dependencies for supporting tools dependencies { combinedWorker "net.corda:corda-combined-worker:$combinedWorkerVersion" - myPostgresJDBC 'org.postgresql:postgresql:42.4.1' + myPostgresJDBC "org.postgresql:postgresql:$postgresqlVersion" notaryServerCPB("com.r3.corda.notary.plugin.nonvalidating:notary-plugin-non-validating-server:$cordaNotaryPluginsVersion") { artifact { classifier = 'package' diff --git a/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/contracts/ChatContract.java b/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/contracts/ChatContract.java index dfd5f6f..7e114ad 100644 --- a/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/contracts/ChatContract.java +++ b/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/contracts/ChatContract.java @@ -36,23 +36,6 @@ public class ChatContract implements Contract { else { throw new IllegalArgumentException("Unsupported command"); } - - /* - // This seems to be make Intellij unhappy. - switch(command.getClass()) { - case Create.class: - requireThat(transaction.getInputContractStates().isEmpty(), "When command is Create there should be no input state"); - requireThat(transaction.getOutputContractStates().size() == 1, "When command is Create there should be one and only one output state"); - break; - case Update.class: - requireThat(transaction.getInputContractStates().size() == 1, "When command is Update there should be one and only one input state"); - requireThat(transaction.getOutputContractStates().size() == 1, "When command is Update there should be one and only one output state"); - break; - default: - throw new IllegalArgumentException("Unsupported command"); - } - - */ } private void requireThat(boolean asserted, String errorMessage) throws IllegalArgumentException { diff --git a/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/states/ChatState.java b/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/states/ChatState.java index ddff982..7e632aa 100644 --- a/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/states/ChatState.java +++ b/contracts/src/main/java/com/r3/developers/csdetemplate/utxoexample/states/ChatState.java @@ -17,6 +17,7 @@ public class ChatState implements ContractState { public ChatState() { } + // Allows serialisation and to use a specified UUID. @ConstructorForDeserialization public ChatState(UUID id, String chatName, @@ -31,6 +32,7 @@ public class ChatState implements ContractState { this.participants = participants; } + // Convenience constructor for initial ChatState objects that need a new UUID generated. public ChatState(String chatName, MemberX500Name messageFrom, String message, @@ -101,6 +103,7 @@ public class ChatState implements ContractState { "(id=" + id + ", chatName=" + chatName + ", messageFrom=" + messageFrom + + ", message=" + message + ", participants=" + participants + ")"; } diff --git a/gradle.properties b/gradle.properties index 156d05f..44367a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,6 +31,8 @@ mockitoKotlinVersion=4.0.0 mockitoVersion=4.6.1 hamcrestVersion=2.2 +postgresqlVersion=42.4.3 + cordaClusterURL=https://localhost:8888 cordaRpcUser=admin cordaRpcPasswd=admin diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlow.java index fc51cb2..c13334a 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlow.java @@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory; public class MyFirstFlow implements RPCStartableFlow { // Log messages from the flows for debugging. - private final Logger log = LoggerFactory.getLogger(MyFirstFlow.class); + private final static Logger log = LoggerFactory.getLogger(MyFirstFlow.class); // Corda has a set of injectable services which are injected into the flow at runtime. // Flows declare them with @CordaInjectable, then the flows have access to their services. diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlowResponder.java b/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlowResponder.java index efdbdfe..70d35f9 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlowResponder.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/flowexample/workflows/MyFirstFlowResponder.java @@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory; public class MyFirstFlowResponder implements ResponderFlow { // Log messages from the flows for debugging. - private final Logger log = LoggerFactory.getLogger(MyFirstFlowResponder.class); + private final static Logger log = LoggerFactory.getLogger(MyFirstFlowResponder.class); // MemberLookup looks for information about members of the virtual network which // this CorDapp operates in. diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/utilities/CorDappHelpers.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utilities/CorDappHelpers.java similarity index 68% rename from workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/utilities/CorDappHelpers.java rename to workflows/src/main/java/com/r3/developers/csdetemplate/utilities/CorDappHelpers.java index ca09a17..e66299c 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/utilities/CorDappHelpers.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utilities/CorDappHelpers.java @@ -1,4 +1,4 @@ -package com.r3.developers.csdetemplate.utxoexample.workflows.utilities; +package com.r3.developers.csdetemplate.utilities; import java.util.Arrays; import java.util.Collection; @@ -8,16 +8,16 @@ import java.util.function.Predicate; import java.util.stream.Collectors; public final class CorDappHelpers { - public static T findAndExpectExactlyOne(Collection collection, Predicate filterFn, String exceptionMsg) throws IllegalArgumentException + public static T findAndExpectExactlyOne(Collection collection, Predicate filterFn, String exceptionMsg) { Collection results = collection.stream().filter(filterFn).collect(Collectors.toList()); if(results.size() != 1){ - throw new IllegalArgumentException(exceptionMsg); + throw new RuntimeException(exceptionMsg); } return results.iterator().next(); } - public static T findAndExpectExactlyOne(Collection collection, String exceptionMsg) throws IllegalArgumentException { + public static T findAndExpectExactlyOne(Collection collection, String exceptionMsg) { return findAndExpectExactlyOne(collection, e -> true, exceptionMsg); } } diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatResponderFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatResponderFlow.java index 928e996..27ee73e 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatResponderFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatResponderFlow.java @@ -5,11 +5,8 @@ import net.corda.v5.application.flows.CordaInject; import net.corda.v5.application.flows.InitiatedBy; import net.corda.v5.application.flows.ResponderFlow; import net.corda.v5.application.messaging.FlowSession; -import net.corda.v5.base.annotations.ConstructorForDeserialization; -import net.corda.v5.base.annotations.CordaSerializable; import net.corda.v5.base.annotations.Suspendable; import net.corda.v5.ledger.utxo.UtxoLedgerService; -import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction; import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction; import net.corda.v5.ledger.utxo.transaction.UtxoTransactionValidator; import org.jetbrains.annotations.NotNull; @@ -21,48 +18,18 @@ import static com.r3.developers.csdetemplate.utxoexample.workflows.ResponderVali @InitiatedBy(protocol = "append-chat-protocol") public class AppendChatResponderFlow implements ResponderFlow { + private final static Logger log = LoggerFactory.getLogger(AppendChatResponderFlow.class); -private final Logger log = LoggerFactory.getLogger(AppendChatResponderFlow.class); - -@CordaInject -public UtxoLedgerService utxoLedgerService; - - /* - static public class TxValidator implements UtxoTransactionValidator { - private final Logger log = LoggerFactory.getLogger(AppendChatResponderFlow.class); - - public TxValidator(FlowSession session) { - this.session = session; - } - - @Override - public void checkTransaction(@NotNull UtxoLedgerTransaction ledgerTransaction) { - ChatState state = (ChatState) ledgerTransaction.getOutputContractStates().get(0); - if (checkForBannedWords(state.getMessage()) || !checkMessageFromMatchesCounterparty(state, session.getCounterparty())) { - throw new IllegalStateException("Failed verification"); - } - log.info("Verified the transaction - " + ledgerTransaction.getId()); - - } - private FlowSession session; - } - - */ + @CordaInject + public UtxoLedgerService utxoLedgerService; @Suspendable @Override public void call(@NotNull FlowSession session) { log.info("AppendChatResponderFlow.call() called"); try { - //TxValidator txValidator = new TxValidator(session); UtxoTransactionValidator txValidator = ledgerTransaction -> { ChatState state = (ChatState) ledgerTransaction.getOutputContractStates().get(0); - log.info("ChatState.getMessage() = " + state.getMessage()); - log.info("ledgerTransaction.getOutputContractStates().size() = " + ledgerTransaction.getOutputContractStates().size()) ; - log.info("session.getCounterParty()=" + session.getCounterparty()); - log.info("state.getMessageFrom()=" + state.getMessageFrom()); - log.info("checkForBannedWords(state.getMessage) = " + checkForBannedWords(state.getMessage())); - log.info("checkMessageFromMatchesCounterparty(state, session.getCounterparty())=" + checkMessageFromMatchesCounterparty(state, session.getCounterparty())); if (checkForBannedWords(state.getMessage()) || !checkMessageFromMatchesCounterparty(state, session.getCounterparty())) { throw new IllegalStateException("Failed verification"); } diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatSubFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatSubFlow.java index 7350702..5c4d552 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatSubFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/AppendChatSubFlow.java @@ -1,14 +1,10 @@ package com.r3.developers.csdetemplate.utxoexample.workflows; -import com.r3.developers.csdetemplate.utxoexample.states.ChatState; import net.corda.v5.application.flows.*; import net.corda.v5.application.messaging.FlowMessaging; import net.corda.v5.application.messaging.FlowSession; -import net.corda.v5.base.annotations.ConstructorForDeserialization; -import net.corda.v5.base.annotations.CordaSerializable; import net.corda.v5.base.annotations.Suspendable; import net.corda.v5.base.types.MemberX500Name; -import net.corda.v5.crypto.SecureHash; import net.corda.v5.ledger.utxo.UtxoLedgerService; import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction; import org.slf4j.Logger; diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/CreateNewChatFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/CreateNewChatFlow.java index 81b3ec0..dd51fdd 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/CreateNewChatFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/CreateNewChatFlow.java @@ -23,9 +23,7 @@ import java.security.PublicKey; import java.time.Duration; import java.time.Instant; import java.util.Arrays; -import java.util.List; import java.util.Objects; -import java.util.function.Predicate; import static java.util.Objects.*; diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/GetChatFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/GetChatFlow.java index a0557f4..376a89d 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/GetChatFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/GetChatFlow.java @@ -16,12 +16,12 @@ import org.slf4j.LoggerFactory; import java.util.*; -import static com.r3.developers.csdetemplate.utxoexample.workflows.utilities.CorDappHelpers.findAndExpectExactlyOne; +import static com.r3.developers.csdetemplate.utilities.CorDappHelpers.findAndExpectExactlyOne; import static java.util.Objects.*; public class GetChatFlow implements RPCStartableFlow { - private final Logger log = LoggerFactory.getLogger(GetChatFlow.class); + private final static Logger log = LoggerFactory.getLogger(GetChatFlow.class); @CordaInject public JsonMarshallingService jsonMarshallingService; diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/ListChatsFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/ListChatsFlow.java index 3ec4854..c1bc6ef 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/ListChatsFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/ListChatsFlow.java @@ -21,7 +21,7 @@ import java.util.stream.Collectors; public class ListChatsFlow implements RPCStartableFlow{ - private final Logger log = LoggerFactory.getLogger(ListChatsFlow.class); + private final static Logger log = LoggerFactory.getLogger(ListChatsFlow.class); @CordaInject public JsonMarshallingService jsonMarshallingService; diff --git a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/UpdateChatFlow.java b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/UpdateChatFlow.java index d2b020c..e682871 100644 --- a/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/UpdateChatFlow.java +++ b/workflows/src/main/java/com/r3/developers/csdetemplate/utxoexample/workflows/UpdateChatFlow.java @@ -25,12 +25,12 @@ import java.time.Instant; import java.util.List; import java.util.stream.Collectors; -import static com.r3.developers.csdetemplate.utxoexample.workflows.utilities.CorDappHelpers.findAndExpectExactlyOne; +import static com.r3.developers.csdetemplate.utilities.CorDappHelpers.findAndExpectExactlyOne; import static java.util.Objects.*; public class UpdateChatFlow implements RPCStartableFlow { - private final Logger log = LoggerFactory.getLogger(UpdateChatFlow.class); + private final static Logger log = LoggerFactory.getLogger(UpdateChatFlow.class); @CordaInject public JsonMarshallingService jsonMarshallingService; @@ -53,7 +53,7 @@ public class UpdateChatFlow implements RPCStartableFlow { @NotNull @Suspendable @Override - public String call(RPCRequestData requestBody) throws IllegalArgumentException{ + public String call(RPCRequestData requestBody) { log.info("UpdateNewChatFlow.call() called"); @@ -61,7 +61,6 @@ public class UpdateChatFlow implements RPCStartableFlow { UpdateChatFlowArgs flowArgs = requestBody.getRequestBodyAs(jsonMarshallingService, UpdateChatFlowArgs.class); // Look up state (this is very inefficient) - // Can get the error when you forget to update the ID. StateAndRef stateAndRef = findAndExpectExactlyOne( ledgerService.findUnconsumedStatesByType(ChatState.class), sAndR -> sAndR.getState().getContractState().getId().equals(flowArgs.getId()), @@ -78,11 +77,10 @@ public class UpdateChatFlow implements RPCStartableFlow { // Now we want to check that there is only one member other than ourselves in the chat. members.remove(myInfo); if(members.size() != 1) { - throw new IllegalArgumentException("Should be only one participant other than the initiator"); + throw new RuntimeException("Should be only one participant other than the initiator"); } MemberInfo otherMember = members.get(0); - // This needs to be a deep copy? ChatState newChatState = state.updateMessage(myInfo.getName(), flowArgs.getMessage()); UtxoTransactionBuilder txBuilder = ledgerService.getTransactionBuilder() @@ -97,7 +95,6 @@ public class UpdateChatFlow implements RPCStartableFlow { UtxoSignedTransaction signedTransaction = txBuilder.toSignedTransaction(myInfo.getLedgerKeys().get(0)); return flowEngine.subFlow(new AppendChatSubFlow(signedTransaction, otherMember.getName())); - } catch (Exception e) { log.warn("Failed to process utxo flow for request body '$requestBody' because:'${e.message}'"); throw e;