-
Notifications
You must be signed in to change notification settings - Fork 77
Description
I tried to create a function to transfer splToken by writing the code below, but I get an error.
I've written the code and the error separately, so please advise me so that the related function is normalized.
code :
import org.p2p.solanaj.core.*;
import org.p2p.solanaj.rpc.RpcClient;
import org.p2p.solanaj.rpc.RpcException;
import org.p2p.solanaj.rpc.types.AccountInfo;
import org.p2p.solanaj.rpc.types.LatestBlockhash;
import java.util.Arrays;
import java.util.List;
public class SolTransaction {
private static final PublicKey TOKEN_PROGRAM_ID = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
private static final PublicKey ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
private static final PublicKey RENT_SYSVAR = new PublicKey("SysvarRent111111111111111111111111111111111");
private static final long LAMPORTS_PER_SOL = 1_000_000_000L;
public String splTokenTransfer(TransferDto transferDto) {
String result = "";
RpcClient rpcClient = new RpcClient("DEV-RPC");
try {
// Derive sender account from mnemonic
List<String> mnemonicWords = List.of(transferDto.getMnemonic().split(" "));
Account senderAccount = Account.fromBip44MnemonicWithChange(mnemonicWords, "");
PublicKey senderPublicKey = senderAccount.getPublicKey();
System.out.println("Sender Public Key: " + senderPublicKey.toBase58());
// Check sender SOL balance
AccountInfo senderAccountInfo = rpcClient.getApi().getAccountInfo(senderPublicKey);
if (senderAccountInfo == null || senderAccountInfo.getValue() == null || senderAccountInfo.getValue().getLamports() < 0.005 * LAMPORTS_PER_SOL) {
throw new RuntimeException("Insufficient SOL balance in signer account. Required: ~0.005 SOL");
}
System.out.println("Sender SOL Balance: " + (senderAccountInfo.getValue().getLamports() / (double) LAMPORTS_PER_SOL) + " SOL");
// Token mint and receiver details
PublicKey mintPublicKey = new PublicKey(transferDto.getContractAddress());
PublicKey receiverPublicKey = new PublicKey(transferDto.getToAddress());
long transferAmount = (long) (Double.parseDouble(transferDto.getAmount()) * Math.pow(10, 8)); // Assuming 8 decimals
// Calculate ATAs
PublicKey senderTokenAccount = findAssociatedTokenAddress(senderPublicKey, mintPublicKey);
PublicKey receiverTokenAccount = findAssociatedTokenAddress(receiverPublicKey, mintPublicKey);
System.out.println("Sender ATA: " + senderTokenAccount.toBase58());
System.out.println("Receiver ATA: " + receiverTokenAccount.toBase58());
// Ensure sender ATA exists
AccountInfo senderAtaInfo = rpcClient.getApi().getAccountInfo(senderTokenAccount);
if (senderAtaInfo == null || senderAtaInfo.getValue() == null) {
System.out.println("Creating Sender ATA...");
String senderAtaTxHash = createAssociatedTokenAccount(rpcClient, senderAccount, senderTokenAccount, senderPublicKey, mintPublicKey);
System.out.println("Sender ATA Creation Tx Hash: " + senderAtaTxHash);
Thread.sleep(2000); // Wait for confirmation
} else {
System.out.println("Sender ATA already exists.");
}
// Ensure receiver ATA exists
AccountInfo receiverAtaInfo = rpcClient.getApi().getAccountInfo(receiverTokenAccount);
if (receiverAtaInfo == null || receiverAtaInfo.getValue() == null) {
System.out.println("Creating Receiver ATA...");
String receiverAtaTxHash = createAssociatedTokenAccount(rpcClient, senderAccount, receiverTokenAccount, receiverPublicKey, mintPublicKey);
System.out.println("Receiver ATA Creation Tx Hash: " + receiverAtaTxHash);
Thread.sleep(2000); // Wait for confirmation
} else {
System.out.println("Receiver ATA already exists.");
}
// Build transfer transaction
Transaction transferTx = new Transaction();
LatestBlockhash latestBlockhash = rpcClient.getApi().getLatestBlockhash();
transferTx.setRecentBlockHash(latestBlockhash.getValue().getBlockhash());
// Add transfer instruction
System.out.println("Adding transfer instruction...");
TransactionInstruction transferInstruction = TokenProgram.transfer(
senderTokenAccount,
receiverTokenAccount,
transferAmount,
senderPublicKey
);
transferTx.addInstruction(transferInstruction);
// Detailed logging for transfer instruction
System.out.println("Transfer Instruction Program ID: " + transferInstruction.getProgramId().toBase58());
List<AccountMeta> transferKeys = transferInstruction.getKeys();
for (int i = 0; i < transferKeys.size(); i++) {
AccountMeta key = transferKeys.get(i);
System.out.println("Transfer Key " + i + ": PublicKey=" + key.getPublicKey().toBase58() +
", isSigner=" + key.isSigner() + ", isWritable=" + key.isWritable());
}
// Sign and send
System.out.println("Signing with sender: " + senderPublicKey.toBase58());
transferTx.sign(senderAccount);
System.out.println("Sending transaction...");
String transactionHash = rpcClient.getApi().sendTransaction(transferTx, senderAccount);
System.out.println("Transaction Hash: " + transactionHash);
result = transactionHash;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Token transfer failed: " + e.getMessage());
}
return result;
}
private String createAssociatedTokenAccount(RpcClient rpcClient, Account signer, PublicKey ata, PublicKey owner, PublicKey mint) throws RpcException {
Transaction transaction = new Transaction();
LatestBlockhash latestBlockhash = rpcClient.getApi().getLatestBlockhash();
String blockhash = latestBlockhash.getValue().getBlockhash();
transaction.setRecentBlockHash(blockhash);
// Associated Token Program의 계정 목록
List<AccountMeta> keys = Arrays.asList(
new AccountMeta(signer.getPublicKey(), true, true), // Payer (signer, writable)
new AccountMeta(ata, false, true), // ATA (writable)
new AccountMeta(owner, false, false), // ATA owner (read-only)
new AccountMeta(mint, false, false), // Token mint (read-only)
new AccountMeta(SystemProgram.PROGRAM_ID, false, false), // System Program (read-only)
new AccountMeta(TOKEN_PROGRAM_ID, false, false), // Token Program (read-only)
new AccountMeta(RENT_SYSVAR, false, false) // Rent Sysvar (read-only)
);
byte[] data = new byte[0]; // No data needed for ATA creation
TransactionInstruction instruction = new TransactionInstruction(ASSOCIATED_TOKEN_PROGRAM_ID, keys, data);
transaction.addInstruction(instruction);
// Detailed logging before signing
System.out.println("ATA Instruction Program ID: " + instruction.getProgramId().toBase58());
List<AccountMeta> ataKeys = instruction.getKeys();
for (int i = 0; i < ataKeys.size(); i++) {
AccountMeta key = ataKeys.get(i);
System.out.println("ATA Key " + i + ": PublicKey=" + key.getPublicKey().toBase58() +
", isSigner=" + key.isSigner() + ", isWritable=" + key.isWritable());
}
System.out.println("Signing ATA Tx with: " + signer.getPublicKey().toBase58());
transaction.sign(signer);
String txHash = rpcClient.getApi().sendTransaction(transaction, signer);
return txHash;
}
private PublicKey findAssociatedTokenAddress(PublicKey owner, PublicKey mint) {
try {
return PublicKey.findProgramAddress(
Arrays.asList(
owner.toByteArray(),
TOKEN_PROGRAM_ID.toByteArray(),
mint.toByteArray()
),
ASSOCIATED_TOKEN_PROGRAM_ID
).getAddress();
} catch (Exception e) {
throw new RuntimeException("Failed to find associated token address", e);
}
}
// Removed redundant createAtaTransaction since createAssociatedTokenAccount works
}
class TransferDto {
private String mnemonic;
private String toAddress;
private String contractAddress;
private String amount;
public TransferDto(String mnemonic, String toAddress, String contractAddress, String amount) {
this.mnemonic = mnemonic;
this.toAddress = toAddress;
this.contractAddress = contractAddress;
this.amount = amount;
}
public String getMnemonic() { return mnemonic; }
public String getToAddress() { return toAddress; }
public String getContractAddress() { return contractAddress; }
public String getAmount() { return amount; }
}
ERROR CODE :
Sender Public Key: 91BN52BUrPwKyddX7RwrLfBk27G2aYscVbgXiVobFhvw
Sender SOL Balance: 4.99798 SOL
Sender ATA: 3qH2UZa35n8DNjiS9KeJzKeQrgR8V99U3Fu4CkAKTwpN
Receiver ATA: DzE88DrpEHjbyB5V3om4e6DjCR5jgWLm2QeAtnbWew1
Sender ATA already exists.
Creating Receiver ATA...
ATA Instruction Program ID: ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
ATA Instruction Keys Count: 7
ATA Key 0: PublicKey=91BN52BUrPwKyddX7RwrLfBk27G2aYscVbgXiVobFhvw, isSigner=true, isWritable=true
ATA Key 1: PublicKey=DzE88DrpEHjbyB5V3om4e6DjCR5jgWLm2QeAtnbWew1, isSigner=false, isWritable=true
ATA Key 2: PublicKey=4YJcbEJRkRdWyJqG6kP7Bcuo9oPk9YfKYa9LQhb7ec5u, isSigner=false, isWritable=false
ATA Key 3: PublicKey=23Ztr5kAgxbPkg8RpVzZKo4waU78WhhkEteg9m1a1hiu, isSigner=false, isWritable=false
ATA Key 4: PublicKey=11111111111111111111111111111111, isSigner=false, isWritable=false
ATA Key 5: PublicKey=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA, isSigner=false, isWritable=false
ATA Key 6: PublicKey=SysvarRent111111111111111111111111111111111, isSigner=false, isWritable=false
Signing ATA Tx with: 91BN52BUrPwKyddX7RwrLfBk27G2aYscVbgXiVobFhvw
Failed to send ATA transaction: invalid transaction: Transaction failed to sanitize accounts offsets correctly
org.p2p.solanaj.rpc.RpcException: invalid transaction: Transaction failed to sanitize accounts offsets correctly
at org.p2p.solanaj.rpc.RpcClient.call(RpcClient.java:174)
at org.p2p.solanaj.rpc.RpcApi.sendTransaction(RpcApi.java:91)
at org.p2p.solanaj.rpc.RpcApi.sendTransaction(RpcApi.java:106)
at org.p2p.solanaj.rpc.RpcApi.sendTransaction(RpcApi.java:61)
at com.qverselab.multiwallet.api.sol.service.SolTransaction.createAtaTransaction(SolTransaction.java:304)
at com.qverselab.multiwallet.api.sol.service.SolTransaction.splTokenTransfer(SolTransaction.java:151)
at com.qverselab.multiwallet.api.sol.controller.SolWalletApiController.splTokenTransfer(SolWalletApiController.java:61)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:257)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:1575)
2025-03-04T16:28:49.669+09:00 ERROR 17780 --- [multi-wallet] [nio-8090-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: Token transfer failed: invalid transaction: Transaction failed to sanitize accounts offsets correctly] with root cause
java.lang.RuntimeException: Token transfer failed: invalid transaction: Transaction failed to sanitize accounts offsets correctly
at com.qverselab.multiwallet.api.sol.service.SolTransaction.splTokenTransfer(SolTransaction.java:187) ~[main/:na]
at com.qverselab.multiwallet.api.sol.controller.SolWalletApiController.splTokenTransfer(SolWalletApiController.java:61) ~[main/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:257) ~[spring-web-6.2.2.jar:6.2.2]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190) ~[spring-web-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.2.jar:6.2.2]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.2.2.jar:6.2.2]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.34.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.2.jar:6.2.2]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.34.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.2.2.jar:6.2.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.2.jar:6.2.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.2.2.jar:6.2.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.2.jar:6.2.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.2.2.jar:6.2.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.2.jar:6.2.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.34.jar:10.1.34]
at java.base/java.lang.Thread.run(Thread.java:1575) ~[na:na]