0

This is my simple contract in my private network

contract AB {
    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;

    /* Initializes contract with initial supply tokens to the creator of the contract */
    function AB () {
        balanceOf[msg.sender] = 1200;              // Give the creator all initial tokens
    }

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
    }

    function gettokenBalance(address to)constant returns (uint256){
          return balanceOf[to];
       }
}

I have generated smart contract wrappers using web3J and there is function like

public Future<Uint256> gettokenBalance(Address to) {
        Function function = new Function("gettokenBalance", 
                Arrays.<Type>asList(to), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallSingleValueReturnAsync(function);
    }

when i am trying to access my contract function like

AB newAB = AB.load(contractaddress, web3j, credentials, gasprice, gaslimit);
        Future<Uint256> result = newAB.gettokenBalance(new Address(address));
        LOGGER.info("result:::"+result.get());

it is giving me a exception like

 java.util.concurrent.ExecutionException: java.lang.IndexOutOfBoundsException: Index: 0
    at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) ~[na:1.8.0_91]
    at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895) ~[na:1.8.0_91]
    at com.belrium.service.UserWalletService.check(UserWalletService.java:197) ~[classes/:na]
    at com.belrium.controller.UserController.check(UserController.java:119) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]

Please help.

Adam Kipnis
  • 10,175
  • 10
  • 35
  • 48
Abhishek saini
  • 507
  • 1
  • 8
  • 29

1 Answers1

0

Futures are asynchronous, so get() will try to fetch the result value, which is currently still being computed. It only works after the computation is done.

I think the Java Future API does not support what you want. Instead, I can recommend using CompletableFuture, which has a join() method that does exactly what you want: wait and get.

When I generated code from contracts, I had the same problem. So I ditched the generator and replaced all the Futures in my generated code with CompletableFutures. I think it's an oversight from web3j, although maybe there is a different way to deal with this problem that I don't know about!

Jodiug
  • 5,425
  • 6
  • 32
  • 48
  • web3j uses regular Futures as the generated smart contract wrappers need to be Java 1.6 compatible for Android. I hope in a future release to provide a choice of sync/async much like the JSON-RPC calls. – Conor Svensson Jul 23 '17 at 13:22
  • @ConorSvensson Might be interesting to look at Kotlin - it's supported on Android and it can target old Java versions. It also has very nice looking async support, though I haven't tried that yet. – Jodiug Jul 23 '17 at 15:31