How to create a Discord bot that waits for user response using JDA library?

I’m working on a Discord bot project using JDA and need help with making it wait for user responses. My bot should work like this: when someone types “Hello Bot!” the bot asks for their name and waits for that same person to reply. If someone else tries to answer, it should tell them to wait. Right now everything happens at once instead of waiting for new messages.

Here’s my current code:

import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;

public class BotMain {
  public static void main(String[] args) throws Exception {
    try {
      JDA bot = new JDABuilder(AccountType.BOT).setToken("YOUR_TOKEN_HERE").build();
      bot.addEventListener(new BotListener());
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

import net.dv8tion.jda.core.entities.*;
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;

public class BotListener extends ListenerAdapter {
  public void onMessageReceived(MessageReceivedEvent evt) {
    if (evt.getAuthor().isBot()) return;

    Message msg = evt.getMessage();
    String text = msg.getContentRaw();
    MessageChannel chat = evt.getChannel();

    if (text.startsWith("Hello Bot!")) {
      Member user = msg.getMember();
      chat.sendMessage("What's your name? Say 'quit' to cancel.").queue();
      int flag = 0;    
      while (flag == 0) {
        Message nextMsg = evt.getMessage(); 
        String nextText = msg.getContentRaw();
        Member nextUser = nextMsg.getMember();
        String nickname = nextUser.getNickname();
        if (user == nextUser) {
          chat.sendMessage("Hello " + nextText + "!").queue();
          flag = 1;
        }
        else {
          chat.sendMessage("Please wait " + nickname + "!").queue();
        }
        if (nextText == "quit") {
          chat.sendMessage("Cancelled!").queue();
          flag = 1;
        }
      }   
    }        
  }
}

The problem is it doesn’t actually wait for new messages. How can I make it pause and listen for the next message from the same user? Also is there a way to add a timeout so it doesn’t wait forever?

The main issue with your approach is trying to use a while loop inside the event handler, which doesn’t actually wait for new messages - it just gets stuck processing the same event repeatedly. You need to track conversation states between different message events instead.

I ran into this exact problem when I started with JDA. What worked for me was creating a HashMap to store pending conversations. Here’s the basic concept: when someone says “Hello Bot!”, store their user ID in a map indicating they’re in a “waiting_for_name” state. Then in your onMessageReceived method, check if the sender has a pending state before processing their message.

Something like Map<String, String> userStates = new HashMap<>(); at the class level, then set userStates.put(user.getId(), "waiting_for_name"); when they trigger the hello command. For subsequent messages, check if userStates.containsKey(author.getId()) and handle accordingly.

For timeouts, you can use ScheduledExecutorService to remove entries from your state map after a certain period. I typically set mine to 60 seconds which seems reasonable for most interactions.

Your code has a fundamental flaw - you’re trying to block the event thread with a while loop, which won’t work in JDA’s event-driven architecture. Each message triggers a separate event, so you can’t simply wait within one event handler. I solved this by implementing a state machine approach using a ConcurrentHashMap to track user conversations. When someone triggers the bot, store their user ID as the key and create a state object containing their current step and timestamp. Then modify your onMessageReceived to first check if the user has an active conversation state before processing any commands. For the timeout functionality, I use a separate thread that runs every few minutes to clean up expired conversations. You can check the timestamp in each state object and remove entries older than your desired timeout period. This prevents memory leaks and automatically cancels stale conversations. Also heads up - you’re using the old JDA version in your imports. The newer versions use net.dv8tion.jda.api instead of net.dv8tion.jda.core and have better async handling methods that make this kind of stateful interaction easier to implement.

ah yeah i see the issue, ur stuck in that infinite loop gettin the same msg object over n over. cant block the event thread like that in jda. what i did was make a simple Map to store whos currently chatting with bot, then just check that map each time onMessageRecieved fires. so like HashMap<Long, Boolean> waitingUsers, and when they say hello bot just add their id to map. next msg from that user gets processed as the name response. worked gr8 for my music bot cmds.