How to register a custom serializer for chaincode in Hyperledger Fabric

Thusitha Dayaratne
1 min readNov 16, 2021

--

Recently, I come across an issue where Fabric chaincode throws a NullPointerException as follows when try to return an ArrayList<String>

org.hyperledger.fabric.Logger error nulljava.lang.NullPointerException
at org.hyperledger.fabric.contract.execution.JSONTransactionSerializer.toBuffer(JSONTransactionSerializer.java:84)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.convertReturn(ContractExecutionService.java:89)
at org.hyperledger.fabric.contract.execution.impl.ContractExecutionService.executeRequest(ContractExecutionService.java:67)
at org.hyperledger.fabric.contract.ContractRouter.processRequest(ContractRouter.java:119)
at org.hyperledger.fabric.contract.ContractRouter.invoke(ContractRouter.java:130)
at org.hyperledger.fabric.shim.impl.ChaincodeInvocationTask.call(ChaincodeInvocationTask.java:100)
at org.hyperledger.fabric.shim.impl.InvocationTaskManager.lambda$newTask$17(InvocationTaskManager.java:265)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

As I understand this happens due to the default JSONTransactionSerializer cannot handle my return type. Thus, I had to find a way to implement my own Serializer to cater my requirement.

After some googling, it seems there is a SerializerInterface (org.hyperledger.fabric.contract.execution.SerializerInterface) that need to be implemented according to the according to [FAB-15634] Implement Interface/annotation for the serializer — Hyperledger JIRA. However, I couldn’t find any documentation on how to register the custom serializer so that chaincode can use the custom serializer instead of the default one. Checking on the Serializer PR [FAB-15634] Annotations for Serializer by mbwhite · Pull Request #41 · hyperledger/fabric-chaincode-java · GitHub I realised how to register the custom implementation.

What you have to do is use the transactionSerializer attribute with the Contract annotation

Sample code

Implement the SerializerInterface and create the Serializer

import org.hyperledger.fabric.contract.annotation.Serializer;
import org.hyperledger.fabric.contract.execution.SerializerInterface;
import org.hyperledger.fabric.contract.metadata.TypeSchema;

@Serializer()
public class CustomSerializer implements SerializerInterface {
@Override
public byte[] toBuffer(Object value, TypeSchema ts) {
...
}

@Override
public Object fromBuffer(byte[] buffer, TypeSchema ts) {
...
}
}

Register the Serializer with the contract

@Contract(
name = "HelloHyper",
transactionSerializer = "org.contract.CustomSerializer"
)
@Default
public class InverterContract implements ContractInterface {

--

--