Event Listener using the Java SDK

In this post, we’ll walk through an event listener within the Java SDK paradigm.

This post is an extension to the previous one, whereby I had walked through what APIs could be used to connect the Java SDK to an existing Fabric network. For this post, I’ll be creating an event listener and tying it up with an existing network. (which can be brought up, using intsructions from the previous post)

Types of events:

For the purpose of this post, we’re only concerned with channel-based events. There exist three types of such events:

  • Block events: Events generated whenever a block is cut
  • Transaction Events: Events generated whenever a transaction is committed
  • Chaincode Events: Events generated by the chaincode. These events come from within the chaincode and need to be added when chaincodes are being written.

The example below will be using BlockEvents.

Tying it up together:

For the Java SDK client to be able to get events, it needs to register with the channel, using the APIs corresponding to one of the above listeners.

  • Firstly, have a class implementing the BlockListener interface.
public class aBlockListener implements BlockListener{
	...
	@Override
	public void received (BlockEvent blockEvent){
		//do something with the blockEvent
	}
}

Everything added to the body of the received method gets executed for every blockEvent that this listener receives.

  • Secondly, register the appropriate listener with the channel, passing the aBlockListener class:
aBlockListener bl = new aBlockListener();

// registering a listener for Block Events		
channel.registerBlockListener(bl);
		

Note that this is simply a snippet to give an idea of what the APIs look like.

The actual code might need to address a few exceptions and perhaps wrap it within a Runnable to keep the process endlessly ongoing.

Also, the eventhub doesn’t buffer events for the listener, i.e., there is no way for the listener to get events that took place before it joined the network, or when it was down.

Parsing the block event:

The structure of the Block event is described in this post.

Following the same, here’s a snippet that covers some APIs to parse out details from a block:

(This goes within the received method described earlier)

try {
		long blockNum = blockEvent.getBlockNumber();

		log.info("<<<<<<<<<<<<<<<<<<< RECEIVED BLOCK {} >>>>>>>>>>>>>>>>>>>>>>>>>>>", blockNum);

		String rawBlock = blockEvent.getBlock().getData().toString();

		Iterable<TransactionEvent> transactionEvents = blockEvent.getTransactionEvents();
		Iterator<TransactionEvent> transactionsIter = transactionEvents.iterator();

		//Ensure you have some object to capture the transaction attributes
		TxObject txObject = new TransactionObject(); 
		String txID;
		
		// Iterate over the many transactions in the block
		while (transactionsIter.hasNext()) {
			TransactionEvent transactionEvent = (TransactionEvent) transactionsIter.next();
			
			txObject.setBlockReceiveTime(currTimestamp);

			log.info("Tx ID: {}", transactionEvent.getTransactionID());
			txObject.setTxValidationCode(transactionEvent.getValidationCode()); 
			// Validation Code is 0 for valid transactions
			log.info("Tx Validation Code: {}", transactionEvent.getValidationCode());
							
			log.info("Tx isValid: {}", transactionEvent.isValid());

			Timestamp txTimestamp = new Timestamp(transactionEvent.getTimestamp().getTime());
			txObject.setProposalCreatedTime(txTimestamp);
			
			log.info("Tx Timestamp: " + txTimestamp);
			
			txObject.setBlockNumber(blockEvent.getBlockNumber());

		}

		log.info("<<<<<<<<<<<<<<<<<<<< END of BLOCK {} >>>>>>>>>>>>>>>>>>>>>>>>>", blockNum);
	} catch (Exception e) {
		log.error("Exception :",e);
	}

One can now patch these pieces up and build something like the blockchain explorer perhaps!

Written on May 10, 2018