[Resolvido] Erro :Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException

3 respostas Resolvido
java
M

Boa noite, vi que teve muita gente com esse erro por aqui mas depois de ler muitos dos tópicos não achei nenhuma solução, uma vez que o problema sempre parecia algo bem especifico de cada situação.
Bem, na minha é o seguinte, minha tabela é criada em tempo de execução através de um select e usando um tablemodel de uma biblioteca que eu vi numa vídeo aula,ate então eu tinha um método que fazia essa atualização da tabela num botão e funcionava 100%, agora eu criei um job para rodar esse método a cada 5 s (vou aumentar esse tempo depois dos testes) utilizando o framework Quartz. O código continua rodando e funcionando mas as vezes ele da esse erro de que estourou o array, sei que o job ta de boa porque pedi para ele printar “teste” sempre que rodasse.

erro :

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
	at java.util.Vector.elementAt(Vector.java:474)
	at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
	at javax.swing.JTable$2.getUpperBoundAt(JTable.java:3221)
	at javax.swing.JTable$5.getUpperBoundAt(JTable.java:3321)
	at javax.swing.JTable.adjustSizes(JTable.java:3334)
	at javax.swing.JTable.adjustSizes(JTable.java:3326)
	at javax.swing.JTable.setWidthsFromPreferredWidths(JTable.java:3240)
	at javax.swing.JTable.doLayout(JTable.java:3128)
	at java.awt.Container.validateTree(Container.java:1693)
	at java.awt.Container.validateTree(Container.java:1702)
	at java.awt.Container.validateTree(Container.java:1702)
	at java.awt.Container.validate(Container.java:1628)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:704)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:702)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:701)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1719)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Construtor da classe principal onde é referenciado o Job:

public TelaSistema() throws SchedulerException {
        initComponents();
        conexao = ModuloConexao.conector();
        //Define um job e referecnia a classe job
        JobDetail job= JobBuilder.newJob(QuartzJob.class).build();
        //executa job a cada 5 segundos
      Triggert1=TriggerBuilder.newTrigger().withIdentity("TriggerCronológico").withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(05).repeatForever()).build();
        Scheduler sc=StdSchedulerFactory.getDefaultScheduler();
        sc.start();
        sc.scheduleJob(job, t1);
    }

Job :

public class QuartzJob implements Job {

    //variaveis de uso no BD
    Connection conexao = null;
    PreparedStatement pst = null;
    ResultSet rs = null;

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        conexao = ModuloConexao.conector();
        String sql = "SELECT ocorrencia.numero as 'Número', cliente.nome as 'Cliente',ocorrencia.categoria as 'Categoria',ocorrencia.descricao as 'Descrição',ocorrencia.historico as 'Histórico',DATE_FORMAT(ocorrencia.data_abertura, '%d/%m/%Y %H:%i') AS 'Abertura', usuario_ocorrencia.nome as 'Usuário',usuario_responsavel.nome as 'Responsável', ocorrencia.status as 'Status' FROM ocorrencia inner join cliente ON cliente.id_cliente_pk=ocorrencia.id_cliente_ocorrencia_fk inner join usuario usuario_ocorrencia on usuario_ocorrencia.id_usuario_pk=ocorrencia.id_usuario_ocorrencia_fk inner join usuario usuario_responsavel on usuario_responsavel.id_usuario_pk = ocorrencia.id_responsavel_ocorrencia_fk WHERE ocorrencia.id_responsavel_ocorrencia_fk= ?";
        try {
            pst = conexao.prepareStatement(sql);
            //passando o conteudo da  cx de pesquisa para o ?
            pst.setString(1, txtPKUsuarioLogado.getText());
            rs = pst.executeQuery();
            //usando biblioteca DbUtils; para preencher a tabela
            tableServicosAbertos.setModel(DbUtils.resultSetToTableModel(rs));
            rs.close();
            pst.close();
            conexao.close();
        } catch (Exception e) {
             e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
        }

        System.out.println("testeJob"+new Date());

    }
}

3 Respostas

S

A JTable tentou renderizar a primeira coluna mas o modelo não possui coluna nenhuma e não está tratando isso no método getColumn(int col).

Dica: Não usa DefaultTableModel, cria sua própria implementação de TableModel.
Além de ficar mais rápido, é mais fácil de fazer manutenção.
Dá uma olhada neste exemplo

M

Primeiramente obrigado pela última resposta. Passei umas horas lendo sobre e teoricamente criei meu modelo Table mas ai para passar ele como modelo para o método que monta a tabela usando o Select tive que tentar reescrever a classe da biblioteca que usava antes para fazer isso, já que esse método usa um DefaultTableModel. Até rodou mas na hora de executar ele dá erro de NullPointerException, vou colocar eles e dizer o que acho que pode ser.

Classe com o método:

public class QuartzJob implements Job {

    //variaveis de uso no BD
    Connection conexao = null;
    PreparedStatement pst = null;
    ResultSet rs = null;

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        conexao = ModuloConexao.conector();
        String sql = "SELECT ocorrencia.numero as 'Número', cliente.nome as 'Cliente',ocorrencia.categoria as 'Categoria',ocorrencia.descricao as 'Descrição',ocorrencia.historico as 'Histórico',DATE_FORMAT(ocorrencia.data_abertura, '%d/%m/%Y %H:%i') AS 'Abertura', usuario_ocorrencia.nome as 'Usuário',usuario_responsavel.nome as 'Responsável', ocorrencia.status as 'Status' FROM ocorrencia inner join cliente ON cliente.id_cliente_pk=ocorrencia.id_cliente_ocorrencia_fk inner join usuario usuario_ocorrencia on usuario_ocorrencia.id_usuario_pk=ocorrencia.id_usuario_ocorrencia_fk inner join usuario usuario_responsavel on usuario_responsavel.id_usuario_pk = ocorrencia.id_responsavel_ocorrencia_fk WHERE ocorrencia.id_responsavel_ocorrencia_fk= ?";
        try {
            pst = conexao.prepareStatement(sql);
            //passando o conteudo da  cx de pesquisa para o ?
            pst.setString(1, txtPKUsuarioLogado.getText());
            rs = pst.executeQuery();
            //usando biblioteca DbUtils; para preencher a tabela
            tableServicosAbertos.setModel(TabelaResultSet.resultSetToTableModel(rs));
            rs.close();
            pst.close();
            conexao.close();
        } catch (Exception e) {
             e.printStackTrace();
            JOptionPane.showMessageDialog(null, e);
        }

        System.out.println("testeJob"+new Date());

    }
}

Classe responsável pelo método “resultSetToTableModel(rs)”

public class TabelaResultSet {
    
    public static TableModel resultSetToTableModel(ResultSet rs) {
	try {
	    ResultSetMetaData metaData = rs.getMetaData();
	    int numberOfColumns = metaData.getColumnCount();
	    Vector<String> columnNames = new Vector<String>();

	    // Get the column names
	    for (int column = 0; column < numberOfColumns; column++) {
		columnNames.addElement(metaData.getColumnLabel(column + 1));
	    }

	    // Get all rows.
	    Vector<Vector<Object>> rows = new Vector<Vector<Object>>();

	    while (rs.next()) {
		Vector<Object> newRow = new Vector<Object>();

		for (int i = 1; i <= numberOfColumns; i++) {
		    newRow.addElement(rs.getObject(i));
		}

		rows.addElement(newRow);
	    }

	    //return new ModeloTabela(rows, columnNames);
            return new ModeloTabela(rows, columnNames);
	} catch (Exception e) {
	    e.printStackTrace();

	    return null;
	}
    }

    public static List<List<Object>> resultSetToNestedList(ResultSet rs, boolean includeColumnNames) {
	try {
	    // To contain all rows.
	    List<List<Object>> rows = new ArrayList<List<Object>>();
	    ResultSetMetaData metaData = rs.getMetaData();
	    int numberOfColumns = metaData.getColumnCount();

	    // Include column headers as first row if required
	    if (includeColumnNames) {
		List<Object> columnNames = new ArrayList<Object>();

		// Get the column names
		for (int column = 0; column < numberOfColumns; column++) {
		    columnNames.add(metaData.getColumnLabel(column + 1));
		}
		rows.add(columnNames);
	    }

	    // Get the data
	    while (rs.next()) {
		List<Object> newRow = new ArrayList<Object>();

		for (int i = 1; i <= numberOfColumns; i++) {
		    newRow.add(rs.getObject(i));
		}

		rows.add(newRow);
	    }
	    return rows;
	} catch (Exception e) {
	    e.printStackTrace();

	    return null;
	}
    }

    public static List<List<Object>> resultSetToNestedList(ResultSet rs) {
	try {
	    // To contain all rows.
	    List<List<Object>> rows = new ArrayList<List<Object>>();
	    ResultSetMetaData metaData = rs.getMetaData();
	    int numberOfColumns = metaData.getColumnCount();

	    // Get the data
	    while (rs.next()) {
		List<Object> newRow = new ArrayList<Object>();

		for (int i = 1; i <= numberOfColumns; i++) {
		    newRow.add(rs.getObject(i));
		}

		rows.add(newRow);
	    }
	    return rows;
	} catch (Exception e) {
	    e.printStackTrace();

	    return null;
	}
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
	ResultSet rs = new DummySimplestPlusMetaData();
	TableModel tm = TabelaResultSet.resultSetToTableModel(rs);
	System.out.println(tm.getValueAt(0, 0));
    }
}

Meu modelo de JTable

import java.util.Vector;
import javax.swing.table.AbstractTableModel;

public class ModeloTabela extends AbstractTableModel{

    public ModeloTabela(Vector data,
                         Vector columnNames) {
    }


        @Override
        public int getRowCount() {
            
           return 10000;
        }

        @Override
        public int getColumnCount() {
            
            return 9;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return "célula (" +rowIndex + ", " + columnIndex + ")";    
        }
     
    }

Pelo o que entendi o método resultSetToTableModel(ResultSet rs) tem como retorno um return new DefaultTableModel(rows, columnNames); E quando eu substitui o Default pelo meu modelo o netbeans acusou erro de falta de construtor, ai cliquei para ele construir ele. Parou de dar erro mas na execução deu Exception como disse acima.
Tem alguma ideia do que ta havendo?

S
Solucao aceita

Não deverias mudar o teu código pra agradar o NetBeans…
Não inicializa o teu modelo customizado através dele, inicializa manualmente mesmo

Sobre teu modelo, acho que ainda não ficou claro pra ti como funciona um TableModel, a JTable “pede” pro TableModel as “coisas” que ela quer renderizar.

Eu implementaria assim:

public class ModeloTabela extends AbstractTableModel {

	private final List itens;

	public ModeloTabela(List itens) {
		this.itens = itens;
	}

	@Override
	public int getRowCount() {
		return itens.size();
	}

	@Override
	public int getColumnCount() {
		return quantidadeDeColunas;
	}
	
	@Override
	public String getColumnName(int col) {
		switch (col) {
			case 0 :
				return "nome da coluna 0";
			case 1 :
				return "nome da coluna 1";
			case N :
				return "nome da coluna N";
			default :
				return null;
		}
	}

	@Override
	public Object getValueAt(int lin, int col) {
		// verifica se o parametro lin  dentro dos limites da lista de itens
		if (lin < 0 || lin >= itens.size()) {
			return null;
		}
		MeuObjeto objeto = itens.get(lin);
		switch (col) {
			case 0 :
				return objeto.getValorDoAtributoDaColuna0();
			case 1 :
				return objeto.getValorDoAtributoDaColuna1();
			case N :
				return objeto.getValorDoAtributoDaColunaN();
			default :
				return null;
		}
	}
}

O mais bacana de usar TableModel dessa forma, é que quando você alterar o conteúdo da lista que passou por parâmetro, é só chamar o método fireTableDataChanged do modelo, que sua JTable vai se redesenhar com os valores atualizados :smiley:

Criado 22 de novembro de 2016
Ultima resposta 23 de nov. de 2016
Respostas 3
Participantes 2