Meu programa roda apenas até a segunda iteração, depois recebo o NoSuchElementException da classe Scanner

Bom dia, estou praticando com JDBC e fiz uma classe Contato, uma classe Menu e a classe Principal para testar, mas estou com o problema descrito no título:

Classe Menu

package controller;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Scanner;

import org.postgresql.util.PSQLException;

import model.Contato;

public abstract class Menu {
	
	private final static String MENU = """
			--- Projeto Agenda ---
			
			1) Iniciar
			2) Encerrar
			
			""";
	private final static String AGENDA_MENU = """
			
			1) Criar Novo Contato
			2) Localizar Contato por ID
			3) Atualizar Contato por ID
			4) Apagar Contato por ID
			5) Encerrar aplicação
			
			""";
	
	public static void exibirMenu() {
		
		try (Scanner scan = new Scanner(System.in)) {
			System.out.println(MENU);
			int opcao = Integer.parseInt(scan.nextLine());
			while(opcao != 2) {
				String url = "jdbc:postgresql://localhost:5432/Agenda";
				
				System.out.println("Entre com o nome de usuário:");
				String usuario = scan.nextLine();
				System.out.println("Entre com a senha:");
				String senha = scan.nextLine();
				
				try (Connection conexao = DriverManager.getConnection(url, usuario, senha)){
					System.out.println("Conexão bem-sucedida ao banco de dados!");
					Contato contato = new Contato();
					opcao = 0;
					
						while (opcao != 5) {
							
							System.out.println(AGENDA_MENU);
							opcao = scan.nextInt();
						    
							switch(opcao) {
						    case 1:
						    	contato.criarContato(conexao);
						    	break;
						    	
						    case 2:
						    	contato.lerContato(conexao);
						    	break;
						    	
						    case 3:
						    	contato.atualizarContato(conexao);
						    	break;
						    	
						    case 4:
						    	contato.apagarContato(conexao);
						    	break;
						    	
						    default:
						    	System.out.println("Agenda fechada.");
						    	opcao = 2;
						    	break;
						    	
						    }
						}
					
				} catch(PSQLException e) { 
					if(e.getMessage().contains("password authentication failed")) {
						
						System.out.println("Credenciais inválidas. \nVerifique nome de usuário e senha \ne tente novamente.");
					
					} else {
						
						System.out.println("Erro ao conectar ao banco de dados." + e.getMessage());
						e.printStackTrace();
					}
				}catch (SQLException e) {
					
					System.out.println("Erro ao conectar ao banco de dados:" + e.getMessage());
					e.printStackTrace();
				}
				
			}
		}
	}

}

Classe Contato

package model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class Contato {

	//private int id;
	private String nome;
	private String telefone;

	public void criarContato(Connection conexao) throws SQLException {
		String sql = "INSERT INTO contatos (nome, telefone) VALUES (?, ?)";

		try (Scanner scan = new Scanner(System.in)){
			try (PreparedStatement ps = conexao.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
				System.out.println("Entre com o nome do contato:");
				nome = scan.nextLine();
				System.out.println("Entre com o telefone do contato:");
				telefone = scan.nextLine();
				ps.setString(1, nome);
				ps.setString(2, telefone);
				ps.executeUpdate();

				try (ResultSet chavesGeradas = ps.getGeneratedKeys()) {
					if(chavesGeradas.next()) {

						int idInserido = chavesGeradas.getInt(1);
						System.out.println("Contato inserido com sucesso!");
						System.out.println("ID: " + idInserido);
						System.out.println("Nome: " + nome);
						System.out.println("Telefone: " + telefone.substring(0, telefone.length() - 4) + "-" + telefone.substring(telefone.length() - 4));

					}
				}
			} catch (SQLException e) {
				System.out.println("Erro na criação do contato!" + e.getMessage());
				e.printStackTrace();
			}
		} 

	}

	public void lerContato(Connection conexao) throws SQLException {
		String sql = "SELECT * FROM contatos WHERE id = ?";

		try (Scanner scan = new Scanner(System.in)){
			try(PreparedStatement ps = conexao.prepareStatement(sql)) {
				System.out.println("Entre com o ID que deseja buscar");
				int id = Integer.parseInt(scan.nextLine());
				ps.setInt(1, id);

				try (ResultSet resultSet = ps.executeQuery()) {

					if(resultSet.next()) {
						int contatoId = resultSet.getInt("id");
						String nome = resultSet.getString("nome");
						String telefone = resultSet.getString("telefone");

						System.out.println("ID: " + contatoId);
						System.out.println("Nome: " + nome);
						System.out.println("Telefone: " + telefone);
					} else {
						System.out.println("Nenhum contato encontrado com o ID informado.");
					}
				} catch (SQLException e) {
					System.out.println("Erro ao executar a consulta: " + e.getMessage());
					e.printStackTrace();
				}

			} catch (SQLException e) {
				System.out.println("Problemas com a busca. " + e.getMessage());
				e.printStackTrace();
			}
		} 


	}

	public void atualizarContato(Connection conexao) throws SQLException {
		String sql = "UPDATE contatos SET nome = ?, telefone = ? WHERE id = ?";
		

		try (Scanner scan = new Scanner(System.in)){
			try(PreparedStatement ps = conexao.prepareStatement(sql)) {
				System.out.println("Informe o ID do contato que deseja atualizar");
				int id = Integer.parseInt(scan.nextLine());
				System.out.println("Informe novo nome:");
				String novoNome = scan.nextLine();
				ps.setString(1, novoNome);
				System.out.println("Informe novo telefone:");
				String novoTelefone = scan.nextLine();
				ps.setString(2, novoTelefone);

				ps.setInt(3, id);

				ps.executeUpdate();

				System.out.println("Contato atualizado com sucesso!");

			} catch (SQLException e) {
				System.out.println("Problemas ao atualizar contato." + e.getMessage());
				e.printStackTrace();
			}
		} 
	}

	public void apagarContato(Connection conexao) throws SQLException {
		String sql = "DELETE FROM contatos WHERE id = ?";

		try (Scanner scan = new Scanner(System.in)){
			try (PreparedStatement ps = conexao.prepareStatement(sql)) {
				System.out.println("Informe o ID do contato que deseja apagar:");
				int id = Integer.parseInt(scan.nextLine());

				ps.setInt(1, id);
				ps.executeUpdate();

				System.out.println("Contato apagado com sucesso!");

			} catch(SQLException e) {
				System.out.println("Problemas ao apagar contato. " + e.getMessage() );
				e.printStackTrace();
			}
		}
	}

}

Classe TesteConexao

package controller;

public class TesteConexao {

	public static void main(String[] args) {
		
		Menu.exibirMenu();

	}

}

Erro Apresentado

--- Projeto Agenda ---

1) Iniciar
2) Encerrar


1
Entre com o nome de usuário:
postgres
Entre com a senha:
1234
Conexão bem-sucedida ao banco de dados!

1) Criar Novo Contato
2) Localizar Contato por ID
3) Atualizar Contato por ID
4) Apagar Contato por ID
5) Encerrar aplicação


1
Entre com o nome do contato:
pessoa1
Entre com o telefone do contato:
1234567890
Contato inserido com sucesso!
ID: 12
Nome: pessoa1
Telefone: 123456-7890

1) Criar Novo Contato
2) Localizar Contato por ID
3) Atualizar Contato por ID
4) Apagar Contato por ID
5) Encerrar aplicação


Exception in thread "main" java.util.NoSuchElementException
	at java.base/java.util.Scanner.throwFor(Scanner.java:937)
	at java.base/java.util.Scanner.next(Scanner.java:1594)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
	at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
	at controller.Menu.exibirMenu(Menu.java:52)
	at controller.TesteConexao.main(TesteConexao.java:9)

Alguém pode me ajudar?
Obrigado!

try (Scanner scan = new Scanner(System.in)) - aqui vc usa o try-with-resources, que ao final do bloco fecha o Scanner, o que faz com que também feche o System.in. Isso quer dizer que qualquer tentativa de ler depois disso falhará, pois mesmo que vc crie outro Scanner, não adianta porque o System.in estará fechado. Em vez disso, crie apenas um Scanner e use-o por toda a aplicação (por exemplo, passando-o como argumento para os métodos criarContato, lerContato, etc).

Outro problema é misturar nextInt com nextLine, isso costuma dar problema (veja aqui e aqui), no caso sugiro usar somente nextLine (tem uma linha que vc faz opcao = scan.nextInt(), para evitar o problema citado troque para opcao = Integer.parseInt(scan.nextLine()))

1 curtida