Hallo,
ich erhalte wie im Titel des Themas beschrieben eine IndexOutOfBoundsException, wenn ich neue Daten in eine JTable lade.
Folgende Anwendung:
Es ist eine Server/Client Anwendung.
Die Anwendung dient zum verwalten von so genannten Jobs.
Aktuell besteht das Problem beim löschen eines Jobs. Vom Client wird ein Command an den Server geschickt, der das löschen dieses Jobs veranlasst. Der Server gibt einen Command an alleine mit dem Server verbundenen Clients zurück, dass die ihre JobListe, diese wird in der JTable dargestellt, neuladen.
Und genau bei diesem neuladen tritt die o.g. Fehlermeldung auf.
Ich weiß nicht, wo ich den Bug habe, werde hier die passenden relevanten Klassen posten. Ich verzweifle an diesem Problem, bin seit vorgestern morgen dran und komme nicht weiter.. Viele SystemOuts gemacht, aber der Fehler tritt immer und immer wieder auf.
Meine Vermutung ist, dass der Ordner vom Server nocht nicht gelöscht ist, wenn der Client die liste neu zeichnen soll. Aber das ist nur eien Vermutung.. Aber eigentlich sollte der Server doch erst die Message an den Client senden, wenn dieser Job auch wirklich gelöscht ist. Vielleicht habe ich dort auch den Fehler gemacht. Ist meine erste Server/Client Anwendung.
habt Nachsicht, wenn der Code nicht gut ist.. ;(
Folgende Fehlermeldung
ServerSocket
ServerThread
ClientSocket
JobController - habe hier nur die relevanten Methoden stehen lassen
JTableModel
JTable
Wenn noch andere Dinge am Code auffallen, ich bin für jeden Ratschlag dankbar...
Hoffe ich kann das Problem mit eurer Hilfe nun endlich beenden.. :rtfm:
Viele Grüße
ich erhalte wie im Titel des Themas beschrieben eine IndexOutOfBoundsException, wenn ich neue Daten in eine JTable lade.
Folgende Anwendung:
Es ist eine Server/Client Anwendung.
Die Anwendung dient zum verwalten von so genannten Jobs.
Aktuell besteht das Problem beim löschen eines Jobs. Vom Client wird ein Command an den Server geschickt, der das löschen dieses Jobs veranlasst. Der Server gibt einen Command an alleine mit dem Server verbundenen Clients zurück, dass die ihre JobListe, diese wird in der JTable dargestellt, neuladen.
Und genau bei diesem neuladen tritt die o.g. Fehlermeldung auf.
Ich weiß nicht, wo ich den Bug habe, werde hier die passenden relevanten Klassen posten. Ich verzweifle an diesem Problem, bin seit vorgestern morgen dran und komme nicht weiter.. Viele SystemOuts gemacht, aber der Fehler tritt immer und immer wieder auf.
Meine Vermutung ist, dass der Ordner vom Server nocht nicht gelöscht ist, wenn der Client die liste neu zeichnen soll. Aber das ist nur eien Vermutung.. Aber eigentlich sollte der Server doch erst die Message an den Client senden, wenn dieser Job auch wirklich gelöscht ist. Vielleicht habe ich dort auch den Fehler gemacht. Ist meine erste Server/Client Anwendung.
habt Nachsicht, wenn der Code nicht gut ist.. ;(
Folgende Fehlermeldung
Java:
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Invalid index
at javax.swing.DefaultRowSorter.convertRowIndexToModel(Unknown Source)
at javax.swing.JTable.convertRowIndexToModel(Unknown Source)
at javax.swing.JTable.getValueAt(Unknown Source)
at javax.swing.JTable.prepareRenderer(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent._paintImmediately(Unknown Source)
at javax.swing.JComponent.paintImmediately(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
ServerSocket
Java:
package de.ernsting.network;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;
import org.apache.log4j.Level;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import de.ernsting.command.JobCommand;
import de.ernsting.util.Config;
import de.ernsting.util.Log4JLogger;
public class Server {
private Config config = Config.getInstance();
private Log4JLogger logger = Log4JLogger.getInstance();
private Hashtable outputStreams = new Hashtable();
private ServerSocket serverSocket;
private Scheduler sched;
public void listen(){
try {
serverSocket = new ServerSocket(Integer.parseInt(config.getProperty("network.socket.port")));
System.out.println("Server gestartet auf " + serverSocket.getInetAddress().getHostAddress() + ":" + serverSocket.getLocalPort());
String timeout = config.getProperty("network.socket.timeout");
if(!timeout.equalsIgnoreCase("never")) {
serverSocket.setSoTimeout(Integer.parseInt(timeout));
}
while(true){
Socket socket = serverSocket.accept();
System.out.println("Verbunden mit " + socket.getInetAddress().getHostAddress());
ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream());
outputStreams.put(socket, oOut);
new ServerThread(this, socket);
}
} catch (NumberFormatException e) {
logger.log(Level.ERROR, this.getClass(), "Servern konnte nicht auf dem Port gestartet werden...", e);
System.exit(1);
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "ServerSocket konnte nicht gestartet werden. da er schon läuft", e);
System.exit(1);
}
try {
serverSocket.close();
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "ServerSocket konnte nicht geschlossen werden.", e);
System.exit(1);
}
}
/**
* Gibt die Outputstreams als
* Enumeration zurück
*
* @return
*/
public Enumeration getOutputstreams(){
return outputStreams.elements();
}
/**
* Sendet das übergebene Objekt an alle
* verbundenen Clients
*
* @param object
*/
public void sendToAll(JobCommand command){
synchronized (outputStreams) {
for(Enumeration e = getOutputstreams(); e.hasMoreElements();){
ObjectOutputStream oos = (ObjectOutputStream) e.nextElement();
try {
oos.writeObject(command);
oos.flush();
} catch (IOException ex) {
logger.log(Level.ERROR, this.getClass(), "Probleme beim Senden des Jobs an die Clients", ex);
}
}
}
}
/**
* Socketverbindung wird getrennt
*
* @param socket - zu trennendes Socket
*/
public void removeConnection(ServerThread socket) {
outputStreams.remove(socket);
synchronized (outputStreams) {
System.out.println("Trenne Verbindung zum Client " + socket.getSocket().getInetAddress());
try {
socket.close();
logger.log(Level.INFO, this.getClass(), "Der ServerThread wurde erfolgreich beendet.");
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Konnte die Verbindung zum Client-Socket nicht schließen", e);
}
}
}
}
ServerThread
Java:
package de.ernsting.network;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import org.apache.log4j.Level;
import org.ietf.jgss.Oid;
import de.ernsting.command.JobCommand;
import de.ernsting.fileaccess.FileIO;
import de.ernsting.upload.Upload;
import de.ernsting.util.Log4JLogger;
public class ServerThread extends Thread {
private Log4JLogger logger = Log4JLogger.getInstance();
private Socket socket;
private Server server;
private FileIO fileIO;
private ObjectInputStream oIn;
public ServerThread(Server server, Socket socket){
this.socket = socket;
this.server = server;
// Thread starten
start();
}
@Override
public void run() {
fileIO = new FileIO();
try {
oIn = new ObjectInputStream(this.socket.getInputStream());
while(true){
JobCommand commandFromClient = (JobCommand) oIn.readObject();
JobCommand commandToClient = new JobCommand();
if(commandFromClient != null){
boolean result = false;
// if( commandFromClient.getMessage().equals("upload") && commandFromClient.getJob() != null){
// System.out.println("ServerThread.run() - UPLOAD");
// Upload upload = new Upload();
// boolean result = upload.upload(commandFromClient.getJob());
// if(result){
// commandToClient.setMessage("reload");
// }
if( commandFromClient.getMessage().equals("delete") && commandFromClient.getJob() != null){
System.out.println("ServerThread.run() - DELETE");
result = fileIO.deleteDirectory(commandFromClient.getJob().getSourceDirectory());
commandToClient.setMessage("reload");
System.out.println("LÖSCHRESULT: " + result);
logger.log(Level.INFO, this.getClass(), commandFromClient.getJob().getName() + " wurde erfolgreich gelöscht!");
} else if( commandFromClient.getMessage().equals("reload")){
System.out.println("ServerThread.run() - RELOAD");
commandToClient.setMessage("reload");
}
if(result){
logger.log(Level.INFO, this.getClass(), "MESSAGE to Clients");
server.sendToAll(commandToClient);
}
}
}
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Der Job wurde nicht verarbeitet", e);
} catch (ClassNotFoundException e) {
logger.log(Level.ERROR, this.getClass(), "Die Klasse des Commands wurde nicht gefunden", e);
}finally {
server.removeConnection(this);
}
}
public void close() throws IOException{
oIn.close();
socket.close();
}
private JobCommand getDataFromClient( ObjectInputStream oIn ) throws IOException {
JobCommand commandFromClient = null;
while ( commandFromClient == null ){
try {
commandFromClient = (JobCommand) oIn.readObject();
} catch ( ClassNotFoundException e ) {
logger.log(Level.ERROR, this.getClass(), "Konnte den Command nicht finden", e);
}
}
System.out.println( "Get: " + commandFromClient.getMessage() );
return commandFromClient;
}
public Socket getSocket() {
return socket;
}
}
ClientSocket
Java:
public class Client implements Runnable{
private Config config = Config.getInstance();
private Log4JLogger logger = Log4JLogger.getInstance();
private Socket clientSocket;
private ObjectOutputStream oOut;
private ObjectInputStream oIn;
private JobController controller;
public Client(JobController controller){
this.controller = controller;
connect();
}
/**
* Verbindet das Socket mit dem
* ServerSocket
*/
public void connect(){
try {
clientSocket = new Socket(config.getSocketHost(), config.getServerPort());
oOut = new ObjectOutputStream(clientSocket.getOutputStream());
oIn = new ObjectInputStream(clientSocket.getInputStream());
controller.setFrametitle(clientSocket.getInetAddress().getHostAddress());
new Thread(this).start();
} catch (UnknownHostException e) {
logger.log(Level.ERROR, this.getClass(), "Host konnte nicht gefunden werden.", e);
e.printStackTrace();
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Konnte nicht mit dem Host verbunden werden.", e);
}
}
/**
* Schickt einen Command an den Server
*
* @param job
*/
public void sendCommandToServer(JobCommand commandToServer){
if(clientSocket.isConnected()){
try {
System.out.println("Client.processJob()");
oOut.writeObject(commandToServer);
oOut.flush();
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Job konnte nicht an den Server geschickt werden", e);
}
}
}
/**
* Schließ die Input- und OutputStream
* und die Verbindung zum Socket
*/
public void close(){
try {
oOut.close();
oIn.close();
clientSocket.close();
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Probleme beim Schließen der Verbindung zum Server", e);
}
}
/**
* Thread um Sendungen vom Server
* anzunehmen und abzuarbeiten
*/
public void run(){
while(true){
System.out.println("Client.run() - while()");
try {
JobCommand commandFromServer = (JobCommand) oIn.readObject();
if(commandFromServer.getMessage().equals("reload")){
logger.log(Level.INFO, this.getClass(), "Client.run() - RELOAD");
controller.updateJobList();
}
} catch (IOException e) {
logger.log(Level.ERROR, this.getClass(), "Der Job konnte nicht verarbeitet werden.", e);
} catch (ClassNotFoundException e) {
logger.log(Level.ERROR, this.getClass(), "Der Job konnte nicht verarbeitet werden.", e);
}
}
}
}
JobController - habe hier nur die relevanten Methoden stehen lassen
Java:
public class JobController {
private JMain view;
private JobService service;
private FileIO fileIO;
private Config config = Config.getInstance();
private Log4JLogger logger = Log4JLogger.getInstance();
private Client socket;
public JobController(){
this.view = new JMain();
this.service = JobService.getInstance();
this.fileIO = new FileIO();
view.getTable().getModel().setJobList(service.listJobs());
view.getTblJobDelete().getModel().updateJobList(service.listJobsToDelete());
addListener();
socket = new Client(this);
}
public void addListener(){
view.getBtnBar().setUploadStartListener(new UploadStartListener());
view.getBtnBar().setCreateFolderListener(new CreateFolderListener());
view.getBtnBar().setRefreshListener(new RefreshListener());
view.getBtnBar().setDeleteListener(new DeleteFolderListener());
}
private class DeleteFolderListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
ArrayList<Job> selectedJobs = view.getTable().getModel().getSelectedJobs();
for (Job job : selectedJobs) {
socket.sendCommandToServer(getCommandToServer("delete", job));
}
// updateJobList();
}
}
/**
* Liest die Jobs neu ein
*/
public void updateJobList(){
System.out.println("JobController.updateJobList()");
view.getTable().getModel().updateJobList(service.listJobs());
}
private JobCommand getCommandToServer(String command, Job job){
JobCommand commandToServer = new JobCommand();
commandToServer.setMessage(command);
commandToServer.setJob(job);
return commandToServer;
}
JTableModel
Java:
public class JobTableModel extends AbstractTableModel {
//Columns Number.
public static final int JOB_SEL_COL = 0;
public static final int JOB_NAME_COL = 1;
public static final int JOB_SOURCE_COL = 2;
public static final int JOB_FOLDERS_COL = 3;
public static final int JOB_DATE_COL = 4;
private String[] columnNames = new String[]{"Upload", "Job Name", "Verzeichnis", "Unterordner", "Datum" };
private ArrayList<Job> jobList;
private ArrayList<Job> jobListSeleted;
public JobTableModel(){
super();
this.jobList = new ArrayList<Job>();
this.jobListSeleted = new ArrayList<Job>();
this.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
int column = e.getColumn();
int row = e.getFirstRow();
//aktuellen Job holen
Job job = (Job) getValueAt(row);
if(job.isUpload())
jobListSeleted.add(job);
else
jobListSeleted.remove(job);
}
});
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return jobList.size();
}
/**
* Aktualisiert die Daten im TableModel
* nachdem diese in der Tabelle geändert
* wurden
*/
public void setValueAt(Object value, int row, int col){
Job job = jobList.get(row);
switch(col){
case JOB_SEL_COL: job.setUpload((Boolean)value); break;
case JOB_NAME_COL: job.setName((String)value); break;
case JOB_SOURCE_COL: job.getSourceDirectory(); break;
case JOB_FOLDERS_COL: value.toString(); break;
case JOB_DATE_COL: job.setDate((String)value); break;
}
fireTableCellUpdated(row, col);
}
/**
* Gibt den Wert, welcher sich in den
* übergebenen Parametern befindet zurück
*
*/
@Override
public Object getValueAt(int row, int column) {
Job job = jobList.get(row);
String folders = "";
if(job.getSourceFolders().length > 0){
for (File folder : job.getSourceFolders()) {
if(folders.isEmpty())
folders += folder.getName();
else
folders += "\n" + folder.getName();
}
}
switch(column){
case JOB_SEL_COL: return job.isUpload();
case JOB_NAME_COL: return job.getName();
case JOB_SOURCE_COL: return job.getSourceDirectory();
case JOB_FOLDERS_COL: return folders;
case JOB_DATE_COL: return job.getDate();
default: return new Object();
}
}
/**
* Gibt das Object zurück, was sich
* in der übergebenen Zeile befindet
* zurück
*
* @param row
* @return
*/
public Object getValueAt(int row){
return jobList.get(row);
}
public String getColumnName(int iColumn){
return columnNames[iColumn];
}
// passendes Format in der Spalte wird angezeigt
public Class getColumnClass(int columnIndex){
switch(columnIndex){
case 0: return Boolean.class;
default: return String.class;
}
}
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
return col == 0;
}
public ArrayList<Job> getSelectedJobs() {
System.out.println("JobTableModel.getSelectedJobs() " + jobListSeleted.size());
return jobListSeleted;
}
public void setSelectedJobs(ArrayList<Job> arrlSelectedJobs) {
this.jobListSeleted = arrlSelectedJobs;
}
public ArrayList<Job> getJobList() {
return jobList;
}
public void setJobList(ArrayList<Job> jobList){
this.jobList = jobList;
}
public void updateJobList(ArrayList<Job> jobList) {
this.jobList.clear();
this.jobListSeleted.clear();
if(!jobList.isEmpty()){
this.jobList = jobList;
this.fireTableDataChanged();
} else if(jobList.size() > 0){
this.fireTableDataChanged();
}
}
}
JTable
Java:
public class JobTable extends JTable {
private JobTableModel model;
private Config config = Config.getInstance();
private FileIO fileIO = new FileIO();
public JobTable(){
init();
}
private void init() {
model = new JobTableModel();
this.setModel(model);
this.setAutoCreateRowSorter(true);
this.setSurrendersFocusOnKeystroke(true);
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Setzen der passenden Ausrichtung innerhalb der Zelle
this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
/* Sollten die Spalten durch den User neu sortiert sein,
* dann haben die spalten einen neuen Index. Man benötigt den Modelindex
*/
final int modelColumn = table.convertColumnIndexToModel(column);
switch (modelColumn)
{
/* alignment left setzen */
default :
setVerticalAlignment(JLabel.TOP);
}
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
});
// Tabellen Header Einstellungen - aktuellen holen, von der JTable um damit abreiten zu können
JTableHeader tblHeader = this.getTableHeader();
tblHeader.setResizingAllowed(false);
tblHeader.setReorderingAllowed(false);
// Spaltenbreite setzen
this.getColumnModel().getColumn(0).setMaxWidth(43);
this.getColumnModel().getColumn(1).setMinWidth(120);
this.getColumnModel().getColumn(2).setMinWidth(380);
this.getColumnModel().getColumn(3).setMinWidth(100);
this.getColumnModel().getColumn(4).setMinWidth(20);
TableColumn column = this.getColumnModel().getColumn(3);
column.setCellRenderer(new TwoLinesCellRenderer());
}
public JobTableModel getModel(){
return model;
}
/**
* Renderer für eine mehrzeilige Zellen.
*
* @author leifken
*
*/
private class TwoLinesCellRenderer extends JTextArea implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (isSelected){
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
}
else{
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
setText(value.toString());
// Passt die Zellenhöhe nur an, wenn die aktuelle ungleich der TA ist und die Tabelle Daten hat
if (table.getRowHeight() != (int) this.getMinimumSize().height && table.getModel().getRowCount() > 0){
table.setRowHeight(row, (int) this.getMinimumSize().height);
}
return this;
}
}
}
Wenn noch andere Dinge am Code auffallen, ich bin für jeden Ratschlag dankbar...
Hoffe ich kann das Problem mit eurer Hilfe nun endlich beenden.. :rtfm:
Viele Grüße