Reputation: 39
uploading and downloading zip attachment containing a text file in corda not working
Tried to attach and download a zip file manually and also tried to send the attachment using client RPC using proxy.
flow code:
public class IOUFlow extends FlowLogic<Void> {
private final Integer iouValue;
private final Party otherParty;
private final SecureHash attachmentHash;
public IOUFlow(Integer iouValue, Party otherParty,SecureHash attachmentHash) {
this.iouValue = iouValue;
this.otherParty = otherParty;
this.attachmentHash=attachmentHash;
}
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
private static final Step ID_OTHER_NODES = new Step("Identifying other nodes on the network.");
private static final Step SENDING_AND_RECEIVING_DATA = new Step("Sending data between parties.");
private static final Step EXTRACTING_VAULT_STATES = new Step("Extracting states from the vault.");
private static final Step OTHER_TX_COMPONENTS = new Step("Gathering a transaction's other components.");
private static final Step TX_BUILDING = new Step("Building a transaction.");
private static final Step TX_SIGNING = new Step("Signing a transaction.");
private static final Step TX_VERIFICATION = new Step("Verifying a transaction.");
private static final Step SIGS_GATHERING = new Step("Gathering a transaction's signatures.") {
// Wiring up a child progress tracker allows us to see the
// subflow's progress steps in our flow's progress tracker.
@Override
public ProgressTracker childProgressTracker() {
return CollectSignaturesFlow.tracker();
}
};
private static final Step VERIFYING_SIGS = new Step("Verifying a transaction's signatures.");
private static final Step FINALISATION = new Step("Finalising a transaction.") {
@Override
public ProgressTracker childProgressTracker() {
return FinalityFlow.tracker();
}
};
private final ProgressTracker progressTracker = new ProgressTracker(
ID_OTHER_NODES,
SENDING_AND_RECEIVING_DATA,
EXTRACTING_VAULT_STATES,
OTHER_TX_COMPONENTS,
TX_BUILDING,
TX_SIGNING,
TX_VERIFICATION,
SIGS_GATHERING,
FINALISATION
);
@Suspendable
@Override
public Void call() throws FlowException {
progressTracker.setCurrentStep(ID_OTHER_NODES);
// We retrieve the notary identity from the network map.
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
progressTracker.setCurrentStep(SENDING_AND_RECEIVING_DATA);
// We create the transaction components.
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
List<PublicKey> requiredSigners = Arrays.asList(getOurIdentity().getOwningKey(), otherParty.getOwningKey());
Command command = new Command<>(new IOUContract.Create(), requiredSigners);
TimeWindow ourAfter = TimeWindow.fromOnly(Instant.MIN);
progressTracker.setCurrentStep(TX_BUILDING);
// We create a transaction builder and add the components.
TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addOutputState(outputState, IOUContract.ID)
.addCommand(command)
.addAttachment(attachmentHash);
// Verifying the transaction.
txBuilder.verify(getServiceHub());
progressTracker.setCurrentStep(TX_SIGNING);
// Signing the transaction.
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
// Creating a session with the other party.
FlowSession otherPartySession = initiateFlow(otherParty);
// Obtaining the counterparty's signature.
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.tracker()));
progressTracker.setCurrentStep(TX_VERIFICATION);
// Finalising the transaction.
subFlow(new FinalityFlow(fullySignedTx, otherPartySession));
return null;
}
}
client code:
public class Client {
private static final Logger logger = LoggerFactory.getLogger(Client.class);
public static void main(String[] args) throws Exception {
// Create an RPC connection to the node.
if (args.length != 3) throw new IllegalArgumentException("Usage: Client <node address> <rpc username> <rpc password>");
final NetworkHostAndPort nodeAddress = parse(args[0]);
final String rpcUsername = args[1];
final String rpcPassword = args[2];
final CordaRPCClient client = new CordaRPCClient(nodeAddress);
final CordaRPCOps proxy = client.start(rpcUsername, rpcPassword).getProxy();
// Interact with the node.
// For example, here we print the nodes on the network.
final List<NodeInfo> nodes = proxy.networkMapSnapshot();
logger.info("{}", nodes);
InputStream inputstream = new FileInputStream("corda.zip");
SecureHash hashId= proxy.uploadAttachment(inputstream);
System.out.println(hashId);
CordaX500Name x500Name = CordaX500Name.parse("O=ICICI,L=New York,C=US");
final Party otherParty = proxy.wellKnownPartyFromX500Name(x500Name);
/* proxy
.startFlowDynamic(IOUFlow.class, "10", otherParty,hashId)
.getReturnValue()
.get();*/
InputStream stream = proxy.openAttachment(hashId);
JarInputStream in = new JarInputStream(stream);
BufferedReader br =new BufferedReader(new InputStreamReader(in));
System.out.println("Output from attachment : "+br.readLine());
}
}
Output:
Task :clients:runTemplateClient I 16:36:28 1 RPCClient.logElapsedTime - Startup took 2066 msec I 16:36:28 1 Client.main - [NodeInfo(addresses=[localhost:10005], legalIdentitiesAndCerts=[O=PNB, L=London, C=GB], platformVersion=4, serial=1559037129874), NodeInfo(addresses=[localhost:10002], legalIdentitiesAndCerts=[O=Notary, L=London, C=GB], platformVersion=4, serial=1559037126875), NodeInfo(addresses=[localhost:10008], legalIdentitiesAndCerts=[O=ICICI, L=New York, C=US], platformVersion=4, serial=1559037128218)]
DF3C198E05092E52F47AE8EAA0D5D26721F344B3F5E0DF80B5A53CA2B7104C9C Output from attachment : null
Another output:when tried to send the attachment from client using RPC
Task :clients:runTemplateClient I 16:41:46 1 RPCClient.logElapsedTime - Startup took 2045 msec I 16:41:47 1 Client.main - [NodeInfo(addresses=[localhost:10005], legalIdentitiesAndCerts=[O=PNB, L=London, C=GB], platformVersion=4, serial=1559037129874), NodeInfo(addresses=[localhost:10002], legalIdentitiesAndCerts=[O=Notary, L=London, C=GB], platformVersion=4, serial=1559037126875), NodeInfo(addresses=[localhost:10008], legalIdentitiesAndCerts=[O=ICICI, L=New York, C=US], platformVersion=4, serial=1559037128218)] B7F5F70FC9086ED594883E6EB8B0B53B666B92CC4412E27FF3D6531446E9E40C Exception in thread "main" net.corda.core.CordaRuntimeException: net.corda.core.flows.IllegalFlowLogicException: A FlowLogicRef cannot be constructed for FlowLogic of type com.template.flows.IOUFlow: due to missing constructor for arguments: [class java.lang.String, class net.corda.core.identity.Party, class net.corda.core.crypto.SecureHash$SHA256]
Upvotes: 1
Views: 245
Reputation: 360
thanks for raising this question. This is definitely something we could improve in the developer experience.
Essentially there are two-steps to adding an attachment to a TX.
SecureHash attachmentHash = getServiceHub().getAttachments().importAttachment(INPUT-FILE, getOurIdentity().getName().toString(), INPUT-FILE.getName());
Replace INPUT-FILE with a java File instance.
.addAttachment(attachmentHash);
You can facilitate the first step either explicitly via flow logic OR using the RPC proxy as you've done here.
For the second error you've listed:
The exception you've posted however is related to the way you're invoking your IOUFlow. The IOUFlow is expecting an Integer as the first argument but we are providing a String - this is causing the IllegalFlowLogicException. Try providing an Int OR changing the IOUFlow to expect a string input to be converted to an Int.
Upvotes: 0
Reputation: 444
A FlowLogicRef cannot be constructed for FlowLogic of type com.template.flows.IOUFlow: due to missing constructor for arguments: [class java.lang.String, class net.corda.core.identity.Party, class net.corda.core.crypto.SecureHash$SHA256]
startFlowDynamic(IOUFlow.class, "10", otherParty,hashId)
It looks like your IOUFlow expects an Integer, and you are sending a String instead?
Upvotes: 0