Patrick Reck
Patrick Reck

Reputation: 303

MySQL - Must be caught or declared to be thrown

I have built this class up from various post as good as i could.

I am trying to get a list of usernames from a MySQL database.

Here is the method retrieving them:

public ArrayList<String> LoadUsers() throws SQLException {
    ArrayList<String> players = new ArrayList<String>();
    try {
        Connection conn = null;
        ResultSet rs = null;

        try {
            conn = getConnection();
            Statement s = conn.createStatement ();
            s.executeQuery ("SELECT * FROM NFT_users");
            rs = s.getResultSet ();

            while(rs.next ()){
                players.add(rs.getString("name"));
            }
            rs.close ();
            s.close ();
        }

        catch (SQLException ex) { 
            System.out.println(ex.toString()); 
        }

        finally { 
            try { 
                if (conn != null) conn.close(); 
            } 

            catch (SQLException ex) { 
                System.out.println("On close: " + ex.toString()); 
            } 
        }
    } 

    catch(Exception ex) { 
        //trace(ex); 
    }

    return players;
}

And this is the code in my mainclass which retrieves it from the method:

    ArrayList<String> players = database.LoadUsers();

However, i get the error Must be caught or declared to be thrown. What do i do wrong?

Upvotes: 0

Views: 588

Answers (3)

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

As I mentioned in a previous comment, it's not a good idea to declare that the LoadUsers method throws an exception, and then to never throw it. This raises the expectation that the caller should be prepared to handle the exception, and indeed, the compiler will demand that the caller either surround the call with a try/catch block, or declare that it throws the exception.

So, there are (at least) three options. The first is to have the LoadUsers method actually throw the exception, like this:

public ArrayList<String> LoadUsers() throws SQLException {
    ArrayList<String> players = new ArrayList<String>();
    try {
        Connection conn = null;
        ResultSet rs = null;

        try {
            conn = getConnection();
            Statement s = conn.createStatement ();
            s.executeQuery ("SELECT * FROM NFT_users");
            rs = s.getResultSet ();

            while(rs.next ()){
                players.add(rs.getString("name"));
            }
            rs.close ();
            s.close ();
        } finally { 
            try { 
                if (conn != null) conn.close(); 
            } catch (SQLException ex) { 
                // eat the exception - we can't do anything about it here 
            } 
        }
    } 

    return players;
}

and in the caller:

public void processPlayers() {
   try{
       ArrayList<String> players = database.LoadUsers();
      // do something with the players

   } catch(SQLException ex){

     ex.printStackTrace();
  }
}

The second option uses the same LoadUsers() method, but doesn't catch the exception in the caller either - it passes it on to its caller:

public void processPlayers() throws SQLException {
      ArrayList<String> players = database.LoadUsers();
      // do something with the players
}

The third option is to catch the exception in the LoadUsers method, and not in the caller. The problem here is that the caller won't know that there was problem - it will just get an empty list:

public ArrayList<String> LoadUsers() throws SQLException {
    ArrayList<String> players = new ArrayList<String>();
    try {
        Connection conn = null;
        ResultSet rs = null;

        try {
            conn = getConnection();
            Statement s = conn.createStatement ();
            s.executeQuery ("SELECT * FROM NFT_users");
            rs = s.getResultSet ();

            while(rs.next ()){
                players.add(rs.getString("name"));
            }
            rs.close ();
            s.close ();
        } catch(SQLException ex) {
            ex.printStackTrace(); // but the caller won't know...
        }
          finally { 
            try { 
                if (conn != null) conn.close(); 
            } catch (SQLException ex) { 
                // eat the exception - we can't do anything about it here 
            } 
        }
    } 

    return players;
}

and

public void processPlayers() throws SQLException {
      ArrayList<String> players = database.LoadUsers(); // an empty list if something went wrong
      // do something with the players
}

This last option is not recommended.

Upvotes: 0

Rohit Jain
Rohit Jain

Reputation: 213401

Your method: -

public ArrayList<String> LoadUsers() throws SQLException {

has declared an SQLException in it's throws clause. So, from whichever method you call this method from, you would either need to enclose the invocation in a try-catch block to handle this exception, or declare this exception in the throws clause of that method also.

So, suppose you are calling your method from a method caller().

So, you have two options: -

  1. Declare exception in throws clause of caller: -

    public void caller() throws SQLException {
         ArrayList<String> players = database.LoadUsers();
    }
    
  2. Enclose the method invocation in a try-catch. In this case, remember to declare your list outside the block first:

    public void caller() {
         ArrayList<String> players = null;
         try {
              players = database.LoadUsers();
         } catch (SQLException e) {
              e.printStackTrace();
         }
    }
    

Note that, if you are using the first option, then you will again face same problem in the method that called caller. There also you would have to follow this thing.

In general, an exception raised inside a method is - either handled there using try-catch block, or is propagated up the stack trace to the immediate caller method, but not both. You are doing both in your method. You are handling the exception, and have declared it to be thrown in the throws clause too. You should never do that.

Upvotes: 3

Robin Chander
Robin Chander

Reputation: 7425

try this

try{
   ArrayList<String> players = database.LoadUsers();
}catch(SQLException e){e.printStackTrace();}

This is because your loadUsers method is throwing an exception. So, wherever you will call this method you need to surround it with try catch

Upvotes: 0

Related Questions