java.lang.NullPointerException: null 오류가 어느 순간 부터 발생되는데 원인이 무었일까요..ㅠㅠ

항상 포럼의 도움을 많이 받는 개발자입니다.
얼마 전 까지 사용 하던 지갑 기능으로 어느 순간 부터 java.lang.NullPointerException: null 오류가 발생 합니다.
어느 부분이 문제 일런지요?
답변 부탁드립니다.

=== 버전 정보 ===
klaytn.caver : 1.4.0
JDK : 1.8

코드 :

public Map<String , String> klayTokenTranjectstion(
String password ,
String fromAddress ,
String useGasPrice ,
String toAddress ,
String amount ,
String contractAddress) throws IOException, CipherException {

    HashMap<String, String> getTransferData = new HashMap<String, String>();
    DefaultBlockParameter blockParameter = DefaultBlockParameterName.PENDING;
    //BigInteger gasLimit = new DefaultGasProvider().getGasLimit();
    BigInteger gasLimit = BigInteger.valueOf(100_000L);

    KlayCredentials senderCredential = KlayWalletUtils.loadCredentials(password, WALLET_PATH + fromAddress + ".json"); // caver-java
    int chainId = ChainId.BAOBAB_TESTNET;
    if(NODE_TYPE.equals("idc")){
        chainId = ChainId.MAINNET;
    }



        HttpService httpService = new HttpService("https://node-api.klaytnapi.com/v1/klaytn");

        String auth = Credentials.basic(klaythAccessKeyId, klaythSecretAccessKey, StandardCharsets.UTF_8);
        httpService.addHeader("Authorization", auth);
        httpService.addHeader("x-chain-id", String.valueOf(chainId));

        Caver caver = Caver.build(httpService);

        BigDecimal  sendAmount = new BigDecimal(amount);
        BigInteger value = org.web3j.utils.Convert.toWei(sendAmount, org.web3j.utils.Convert.Unit.ETHER).toBigInteger();
        BigInteger value2 = Convert.fromPeb(sendAmount , KLAY ).toBigInteger();
        System.out.println("amount:"+ value);
        System.out.println("toAddr:"+toAddress);

        Function function = new Function(
                "transfer",
                Arrays.asList(
                        new Address(toAddress),
                        new Uint256(value)
                ),
                Arrays.asList(new TypeReference<Bool>() {
                }));

        // Using web3j FunctionEncoder is fine
        String functionCallData = FunctionEncoder.encode(function);
        TransactionManager manager = new TransactionManager.Builder(caver, senderCredential)
                .setTransactionReceiptProcessor(new PollingTransactionReceiptProcessor(caver, 1000, 10))
                .setChaindId(chainId)
                .build();


        KlayTransactionReceipt.TransactionReceipt receipt = manager.executeTransaction(
                SmartContractExecutionTransaction.create(
                        senderCredential.getAddress(),
                        contractAddress,
                        BigInteger.ZERO, // value should set to zero unless you are transferring KLAY to the contract
                        Numeric.hexStringToByteArray(functionCallData), // use Numeric.hexStringToByteArray for safe conversion
                        gasLimit)
            );

 //   System.out.println(receipt.getStatus()); // 0x1
    getTransferData.put("tx status", receipt.getStatus());
    getTransferData.put("status","200");
    getTransferData.put("msg","success");
    getTransferData.put("hash",receipt.getTransactionHash());


    getTransferData.put("addr",senderCredential.getAddress());
    getTransferData.put("toAddress" , toAddress);
    getTransferData.put("contractAddress",contractAddress);
    getTransferData.put("amount" , amount);


    return getTransferData;
}

안녕하세요.
어느부분에서 에러가 발생하는지 Exception log 전달 부탁드립니다.

안녕하세요.
manager.executeTransaction 를 처리한 receipt 에서 Exception 오류가 발생 하며,
에러 로그는 아래의 내용입니다.

오류 항목에서 TranjectstionService.java:521 라인은 receipt.getTransactionHash() 값을 map 으로 넣는 부분
getTransferData.put(“tx”, receipt.getTransactionHash()); 해당 라인입니다.

오류 내용 :

java.lang.NullPointerException: null
at com.klaywallet.service.TranjectstionService.newKlayTokenTranjectstion(TranjectstionService.java:521) ~[classes/:na]
at com.klaywallet.controller.KlayWalletRestController.klayTokenTranjectstion(KlayWalletRestController.java:122) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_221]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_221]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_221]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_221]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598) [tomcat-embed-core-9.0.30.jar:9.0.30]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.30.jar:9.0.30]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.30.jar:9.0.30]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]

안녕하세요.
Transaction receipt을 가져오는 부분에서 제대로 못가져온 것 같은데요.

Transaction Receipt을 못가져오는 이유는 여러가지가 있을 수 있습니다.

  • Transaction 전송 시 실패한 경우(balance 부족 등)
    • 이 부분은 Node와 클라이언트 사이에서 주고 받는 Http Request / Response를 확인해보시면 도움 될 것 같습니다.
  • 네트워크 부하가 발생하여 Node로 부터 Receipt을 받아오는 데 시간이 오래걸린 경우
    • 이 경우 PollingTransactionReceiptProcessor의 파라미터를 수정하셔서 좀 더 오래 polling하도록 수정해보시기 바랍니다.
1 Like

제가 현제 사용한 코드에 대해서 문제점은 없는지요? 예를 들어 사용하는 함수의 지원이 종료 되었다던지, 업데이트 되면서 같은 기능이지만 명칭이 변경 되었다던지 하는 부분으로요…
말씀 하신 부분으로 수량 및 파라미터 부분으로만 체크 하면 될런지요?

코드상에 문제는 없어보입니다.
개발에 도움 되실 수 있도록 caver-java 1.4.0의 튜토리얼 링크 전달드립니다.

SDK의 사용은 개발자분들의 몫이므로 배포된 어떤 버전이든 자유롭게 사용하셔도 됩니다만, SDK를 개발하고 유지보수하는 입장에서는 caver-java의 최신버전을 사용하라고 권장드리고 싶습니다.

그리고 1.4버전의 API들은 Deprecated되어 유지보수가 되고 있지 않습니다.
하지만 1.5버전부터 인터페이스가 많이 달라져서 익숙해지는데 시간이 걸리실 수 있습니다.

1 Like

@Kale 님 께서 말씀 해주셨던 사례들을 하나 하나 체크 하면서 원인을 찾았습니다.

        BigInteger GAS_LIMIT = GAS_PROVIDER.getGasLimit();
        Quantity klayGetGasPrice = caver.klay().getGasPrice().send();

해당 코드로 인하여 실제 발생되는 수수료 보다 높게 설정된 값을 확인 후
아래와 같이 수정 하였더니 정상으로 되었습니다.
혹시 저와 같은 상황이 있는 분들 계실거 같아서… 몇자 적어요.

아래의 코드로 리미트를 고정 하니 정상으로 되었습니다.
BigInteger GAS_LIMIT = BigInteger.valueOf(100_000L);

도움 주심 Kale 님 감사합니다.

추 후 1.4 이상 버전으로 시간적 여유를 두고 다시 공부 해봐야겠군요.

1 Like