0

So, I have a method that (should) return a String containing a data from a sqlite database:

public String getLesson() throws ClassNotFoundException {
    ArrayList list = new ArrayList();

    int selectedColumn = tblOpenLesson.getSelectedColumn();
    int selectedRow = tblOpenLesson.getSelectedRow();
    String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn);

    try {
        Class.forName("org.sqlite.JDBC");
        Connection con = DriverManager.getConnection("jdbc:sqlite:sql_items.sqlite");
        Statement stmtGetLesson = con.createStatement();
        ResultSet rs = stmtGetLesson.executeQuery("SELECT * FROM lessons WHERE lesson_id  = '" + name + "';");

        if (rs.next()) {
            list.add(rs.getString("lesson"));
        }
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null, e);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(openLesson.class.getName()).log(Level.SEVERE, null, ex);
    }

    return (String) list.get(0);
}

and I would use that string to locate a text file by which its content will be displayed on a JTextPane that is located from another class

private void btnOpenLessonPopUpActionPerformed(java.awt.event.ActionEvent evt) {                                                   

    try {
        FileReader fr = new FileReader("Lessons\\" + getLesson() + ".txt"); //this is Line 126

        try (BufferedReader br = new BufferedReader(fr)) {
            mainScreen.lessonPane.read(br, null); //  lessonPane is from another class
            br.close();
        } catch (IOException e) {
            System.out.println(e);
            this.setVisible(false);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(openLesson.class.getName()).log(Level.SEVERE, null, ex);
        }  
    } 

however I am getting this error:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(ArrayList.java:657) at java.util.ArrayList.get(ArrayList.java:433) at mainWindow.openLesson.getLesson(openLesson.java:204) at mainWindow.openLesson.btnOpenLessonPopUpActionPerformed(openLesson.java:126) at mainWindow.openLesson.access$000(openLesson.java:19) at mainWindow.openLesson$1.actionPerformed(openLesson.java:60) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) at java.awt.Component.processMouseEvent(Component.java:6539) at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) at java.awt.Component.processEvent(Component.java:6304) at java.awt.Container.processEvent(Container.java:2239) at java.awt.Component.dispatchEventImpl(Component.java:4889) at java.awt.Container.dispatchEventImpl(Container.java:2297) at java.awt.Component.dispatchEvent(Component.java:4711) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476) at java.awt.Container.dispatchEventImpl(Container.java:2283) at java.awt.Window.dispatchEventImpl(Window.java:2746) at java.awt.Component.dispatchEvent(Component.java:4711) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760) 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$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84) at java.awt.EventQueue$4.run(EventQueue.java:733) at java.awt.EventQueue$4.run(EventQueue.java:731) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74) at java.awt.EventQueue.dispatchEvent(EventQueue.java:730) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205) 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)

I don't think I have any idea of why this is happening. I'm still new to programming.

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
  • If you are only wanting one column then don't do `SELECT * FROM lessons`, just `select column` – Scary Wombat Mar 13 '20 at 08:26
  • It's not an error, but you shouldn't use ArrayList as a type (on the left) of a variable because it's a concrete class rather than an interface. You should use List instead. Also, this list is only going to hold strings, so it should be futher constrained with generics (`<>`). So, `ArrayList list = new ArrayList();` should be `List list = new ArrayList<>;` – Software Engineer Mar 13 '20 at 08:43

3 Answers3

3

If the sql query doesn't return any rows the last line will throw an exception because your list is empty.

 return (String) list.get(0);

So either change it to

if (!list.isEmpty() {
    return (String) list.get(0);
}
return null; //If list is empty

or even better since you are only interested in the first row you can skip the list and replace

if (rs.next()) {
    list.add(rs.getString("lesson"));
}

with

if (rs.next()) {
    return rs.getString("lesson");
}

You still need to return at the end of the method

return null;

Than you use it like this

try {
    String lesson = getLesson();
    if (lesson != null) {
         //open file...
    }
...
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • and for Pete's sake, make your SQL safe by using a PreparedStatement - talking to OP, not you Joakim – Scary Wombat Mar 13 '20 at 08:25
  • I've tried that. It is now giving me java.io.FileNotFoundException: Lessons\.txt (The system cannot find the file specified). I think this is because the last return statement contains nothing, and that's what the method is getting. I've also tried to put it on string but it returns null: java.io.FileNotFoundException: Lessons\null.txt (The system cannot find the file specified) – itskenleton Mar 13 '20 at 08:27
  • Also use if you were going to use an `ArrayList` then use `ArrayList list = ..;` In most cases if you see a cast, then there is something wrong with your code. – Scary Wombat Mar 13 '20 at 08:28
  • That's because the query that you have doesn't return anything. Check that the DB actually contains data and also confirm that the query you have in your application returns the data you'd expect it to – npinti Mar 13 '20 at 08:29
  • @itskenleton You shouldn't ask several questions at once but since the method might not return anything (empty string) you must of course check the result before proceeding. In this context it might be better if the method returns null rather than an empty string. Answer updated – Joakim Danielson Mar 13 '20 at 08:32
  • You're definitely right. My JTable doesnt have the "lesson_id" on it. I fixed it and it is working now. thank you so much! – itskenleton Mar 13 '20 at 08:41
2

Difficult to say without knowing the structure of your data, however, from your query: "SELECT * FROM lessons WHERE lesson_id = '" + name + "';" it seems that you are trying to match the lesson_id with the name of the lesson your are getting.

It could also be that String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn); doesn't give you what you'd expect.

On another note, you really need to look into Prepared Statements. As is, your application is prone to SQL injection.

Personally, I would also refactor the code so that:

if (rs.next()) {
    list.add(rs.getString("lesson"));
}

Becomes:

if (rs.next()) {
    return rs.getString("lesson");
}

And this: return (String) list.get(0); becomes return "";.

npinti
  • 51,780
  • 5
  • 72
  • 96
  • This solved both of the problem. IndexOutOfBounds was fixed when I moved the return statement. and also String name = (String) tblOpenLesson.getModel().getValueAt(selectedRow, selectedColumn); is taking data from wrong column/row. Thank you so much! – itskenleton Mar 13 '20 at 08:44
  • @itskenleton: You're welcome. Please do be sure you address your SQL Injection issue in your code. – npinti Mar 13 '20 at 09:00
  • Yes. thank you for the advice, I have no idea of anything about SQL Injection and such. Good to know. – itskenleton Mar 13 '20 at 09:01
0

You are throwing an IndexOutOfBounds exception when trying to retrieve the value at index 0. This would mean that nothing has been added to your ArrayList. Your data is more than likely not a valid row when next() is called.

trm_
  • 21
  • 4