sakeer
sakeer

Reputation: 39

Unable to upload and download attachment in corda 4.0 ( java) showing null

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

Answers (2)

Nicholas Rogers
Nicholas Rogers

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.

  • The first step is importing the attachment itself into the node (which it seems you've already done):

SecureHash attachmentHash = getServiceHub().getAttachments().importAttachment(INPUT-FILE, getOurIdentity().getName().toString(), INPUT-FILE.getName());

Replace INPUT-FILE with a java File instance.

  • The second is to add the attachment hash to the TX (which you have already done as well)

.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

florian
florian

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

Related Questions