0

I am new to Hyperlegder-Fabric and already manage to connect to a network through the org.hyperledger.fabric.gateway package.

This is my App.java class:


//Fabric Imports
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.sdk.BlockEvent;
import org.hyperledger.fabric.sdk.ChaincodeEventListener;

//Other Imports
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;


public class App{

public static void main(String[] args) throws IOException {
        // Load an existing wallet holding identities used to access the network.
        Path walletDirectory = Paths.get("wallet");
        Wallet wallet = Wallets.newFileSystemWallet(walletDirectory);

        // Path to a common connection profile describing the network.
        Path networkConfigFile = Paths.get("connection.json");

        // Configure the gateway connection used to access the network.
        Gateway.Builder builder = Gateway.createBuilder()
                .identity(wallet, "user1")
                .networkConfig(networkConfigFile);

        // Create a gateway connection
        try (Gateway gateway = builder.connect()) {

            // Obtain a smart contract deployed on the network.
            Network network = gateway.getNetwork("mychannel");
            Contract contract = network.getContract("fabcar");

            // Submit transactions that store state to the ledger.
            byte[] createCarResult = contract.createTransaction("createCar")
                    .submit("CAR10", "VW", "Polo", "Grey", "Mary");
            System.out.println(new String(createCarResult, StandardCharsets.UTF_8));

            // Evaluate transactions that query state from the ledger.
            byte[] queryAllCarsResult = contract.evaluateTransaction("queryAllCars");
            System.out.println(new String(queryAllCarsResult, StandardCharsets.UTF_8));

        } catch (ContractException | TimeoutException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Now I need to listen for block events, so I see in the documentation that the Network package contains the addBlockListener method (https://hyperledger.github.io/fabric-gateway-java/release-2.2/org/hyperledger/fabric/gateway/Network.html)

My doubt is how i can implement this method in the above App.java file so i can get the block number, etc. I am not a java developer i am struggling a lot on this since.

Appreciate any help.

1 Answers1

1

The listener you attach is an implementation of the Consumer<BlockEvent> type, where Consumer is a standard Java functional interface:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/Consumer.html

To define your listener you could:

  1. write your own listener class that implements that interface; or
  2. define an anonymous class in-line that implements that interface; or
  3. use a lambda expression as a short-hand for the anonymous class implementation to minimise boiler-plate code.

Using a lambda expression, your code might look like this:

network.addBlockListener(blockEvent -> {
    long blockNumber = blockEvent.getBlockNumber();
    System.out.println("Received block number " + blockNumber);
});

If you add the listener to the network before submitting your transaction, you should see the block event created when your submitted transaction is recorded on the ledger.

Dharman
  • 30,962
  • 25
  • 85
  • 135
bestbeforetoday
  • 1,302
  • 1
  • 8
  • 12
  • Thanks, that helped! I was reviewing functional interfaces and now i have a better idea of how they work. Althought i still have doubts about how to implement option 1 (write your own class that implements the interface). I edited my question to show you the problem – Víctor Rosillo Oct 02 '22 at 11:28
  • If you want to have one of your own classes act directly as a block event listener, you would need to declare that it implements the required interface, for example: `class MyListener implements Consumer { ... }`. In order to successfully implement this interface, it would have to include a method with the signature `public void accept​(BlockEvent event)`. You could then pass an instance of MyListener as the argument to `addBlockListener()`. – bestbeforetoday Oct 05 '22 at 09:40