public void handleTransaction ( ChaincodeMessage message ) { // The defer followed by triggering a go routine dance is needed to ensure that the previous state transition // is completed before the next one is triggered. The previous state transition is deemed complete only when // the beforeInit function is exited. Interesting bug fix!! Runnable task = ( ) -> { //better not be nil ChaincodeMessage nextStatemessage = null ; boolean send = true ; //Defer try { // Get the function and args from Payload ChaincodeInput input ; try { input = ChaincodeInput . parseFrom ( message . getPayload ( ) ) ; } catch ( Exception e ) { logger . debug ( String . format ( "[%s]Incorrect payload format. Sending %s" , shortID ( message ) , ERROR ) ) ; // Send ERROR message to chaincode support and change state nextStatemessage = ChaincodeMessage . newBuilder ( ) . setType ( ERROR ) . setPayload ( message . getPayload ( ) ) . setTxid ( message . getTxid ( ) ) . build ( ) ; return ; } // Mark as a transaction (allow put/del state) markIsTransaction ( message . getTxid ( ) , true ) ; // Create the ChaincodeStub which the chaincode can use to callback ChaincodeStub stub = new ChaincodeStub ( message . getTxid ( ) , this , message . getSecurityContext ( ) ) ; // Call chaincode's Run ByteString response ; try { response = chaincode . runHelper ( stub , getFunction ( input . getArgsList ( ) ) , getParameters ( input . getArgsList ( ) ) ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; System . err . flush ( ) ; // Send ERROR message to chaincode support and change state logger . error ( String . format ( "[%s]Error running chaincode. Transaction execution failed. Sending %s" , shortID ( message ) , ERROR ) ) ; nextStatemessage = ChaincodeMessage . newBuilder ( ) . setType ( ERROR ) . setPayload ( message . getPayload ( ) ) . setTxid ( message . getTxid ( ) ) . build ( ) ; return ; } finally { deleteIsTransaction ( message . getTxid ( ) ) ; } logger . debug ( String . format ( "[%s]Transaction completed. Sending %s" , shortID ( message ) , COMPLETED ) ) ; // Send COMPLETED message to chaincode support and change state Builder builder = ChaincodeMessage . newBuilder ( ) . setType ( COMPLETED ) . setTxid ( message . getTxid ( ) ) ; if ( response != null ) builder . setPayload ( response ) ; nextStatemessage = builder . build ( ) ; } finally { triggerNextState ( nextStatemessage , send ) ; } } ; new Thread ( task ) . start ( ) ; }
handleTransaction Handles request to execute a transaction .