Try, catch, como usar corretamente?

Lá vem eu com mais uma dúvida de iniciante.

To desenvolvendo um site com Java e não sei como dar um jeito nos erros. A estrutura do site é a seguinte:

  • classe DBAccess (cone~xao com o DB)
  • classe DBMetodos (procedimentos com o DB, chama o DBAccess)
  • demais classes de regras de negócio (chamam DBAccess e DBMetodos)
  • páginas JSP para exibição dos dados.

Meu problema é: caso ocorra algum erro em alguma das classes, eu queria que ele mostrasse uma página de erro, chamada erro.jsp.

Tentei colocar os throws e throw, mas chega num ponto em que ele dá o erro NullPointException, e não consigo sair daí.

Vou postar os código para vcs verem. Estou com uma série de problemas, uma vez que o erro ocorre e não consigo exibí-lo, daí num sei o que tah errado no programa.

* DBAccess

/*
 * Esta classe é responsável pelo acesso ao banco de dados
 * controlando as conexões existentes.
 */

package dbcontrol;

import java.sql.*;

public class DBAccess {
	private Connection conn = null;

	public DBAccess()
	{
	}
	
	//Abre a conexão retornando o objeto conexão
	public Connection AbreConexao() throws Exception
	{
		try	{
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		}catch (Exception e){throw e;}

		try	{
			conn = DriverManager.getConnection("jdbc:odbc:gsp_db2","","");
		}catch (Exception e){System.out.println(e.getMessage());}

		return conn;		
	}
	
	//Fecha o objeto conexão aberto
	public void FechaConexao(Connection conn) throws Exception
	{
		try{
			if (this.conn == conn){
				conn.close();
			}
		}catch (Exception e){throw e;}
	}
}

*DBMetodos

/*
 * Classe responsável pela execução de métodos referentes
 * a um banco de dados, tais como consultas, inclusões, etc.
 */

package dbcontrol;

import java.sql.*;

public class DBMetodos{

	private Connection conn = null;
	private Statement stmt = null;
	private ResultSet rsTable = null;
		
	public DBMetodos(){
	}
	
	//Define a conexão ativa a ser utilizada
	public void DefineConexao(Connection newconn) throws Exception
	{
		try	{
			conn = newconn;
		}catch (Exception e){throw e;}
	}
	
	//Define o statement ativo a ser utilizado
	public void DefineStat(Statement newstmt) throws Exception
	{
		try	{
			stmt = newstmt;
		}catch (Exception e){throw e;}
	}


	//Retorna um resultset com base na string fornecida	
	public ResultSet RetornaTable(String sql) throws Exception {
		
		try{
			if (conn == null){
				System.out.println("Banco de dados não disponível!");	
			}
			
			stmt = conn.createStatement();
			rsTable = stmt.executeQuery(sql);

		} 
		catch (Exception e){throw e;}

		return rsTable;
	}
	
}

*Login

/*
 * Controla o acesso de usuários ao site, verificando se 
 * o login e a senha são válidos
 */

package regras;

import dbcontrol.*;
import java.sql.*;

public class Login {

	private String strNomeUsu = null;
	private String intIDUsu = null;
		
	public Login(){
	}
	
	// Verifica se o usuário indicado pelos parâmetros 
	// login e senha se encontra no banco de dados
	public boolean VerLogin(String strLogin, String strSenha) throws Exception
	{
		
		boolean bUsuarioOk = false;

		try{
			DBAccess conexao = new DBAccess();
			Connection conn = conexao.AbreConexao();
			
			DBMetodos executa = new DBMetodos();
			executa.DefineConexao(conn);
			Statement stmt = null;
			executa.DefineStat(stmt);
	
			String strSQL = "";

			strSQL = "SELECT CD_USUARIO, NOME FROM USUARIO WHERE LOGIN = '"+strLogin+"' AND SENHA = '"+strSenha+"'";
		
			ResultSet tabela = executa.RetornaTable(strSQL);
			
			boolean bTabela = tabela.next();
			
			if (bTabela){
				bUsuarioOk = true;
				strNomeUsu = tabela.getString("NOME");
				intIDUsu = tabela.getString("CD_USUARIO");
			}else{
				bUsuarioOk = false;
			}
			
			try{stmt.close();}catch(Exception ee){throw ee;}
			conexao.FechaConexao(conn);

		}catch(Exception e){throw e;}
				
		return bUsuarioOk;
	}

	//Retorna o nome do usuário
	public String NomeUsu()
	{
		return strNomeUsu;
	}
	
	//Retorna o ID do usuario
	public String IDUsu()
	{
		return intIDUsu;
	}
	
}

E finalmente a página JSP. Só vou por a parte do código que interessa, o resto é HTML

<%@ page import="regras.Login,javax.servlet.*" session="true" errorPage="error.jsp"%>

<%
	String msgNoLog = "";
	String strLogin = null;
	String strSenha = null;
	boolean bLogado = false;

	strLogin = request.getParameter("login");
	strSenha = request.getParameter("senha");

	try{
		if (strLogin != null){
			Login objVerLogin = new Login();
			bLogado = objVerLogin.VerLogin(strLogin, strSenha);

			if (bLogado){
				String nome = objVerLogin.NomeUsu();
				String codigo = objVerLogin.IDUsu();
				session.setAttribute("nome_usu",nome);
				session.setAttribute("id_usu",codigo);
				msgNoLog = "";
			}else{
				msgNoLog = "Usuário e senha inválidos.";
			}
		}
	}catch (Exception e){throw e;}

%>

O problema é que na página JSP o erro ocorre e aparece a error.jsp com o tal erro de NullPointException.

Que que eu faço? Alguém tem alguma boa idéia?

Ainda não analisei o seu código… mas veja bem…

as exceção que estão no pacote java.lang.Exception

não precisam ter throws declarados para elas serem lançadas

ou seja… em quanlquer ponto do seu código… pode haver exceções deste tipo… sem aviso previo…

vc pode previnir isso usando try{ … } catch (Exception ex) {} no corpo do seu código… mas isso não é elegante…

o ideal é vc ir vendo onde ta rolando o erro…

isso ai que te aconteceu é q em algum momento um variavel estava definida como null … e ele tentou… variavel.metodo() … e como varivel é nula… ele tenta… null.metodo() … o q gera 1 erro de NullPointerException… isso tb ocorre quando vc tenta… varivel.propriedade … e a variavel ta nula…

é bom vc ir fazendo testes… pra previnir o erro…

Faz o seguinte, coloca um try-catch(Exception) em todos os métodos e dentro do catch coloca e.printStackTrace();
Ele irá mapear o erro e mostrará pra vc exatamente onde está ocorrendo essa exceção!

Mas depois de corrigir tira isso, pq é muito feio!

As observações do Heber e do Tomaz estão corretas, mas não sei se elas efetivamente respondem à sua dúvida.
Realmente a forma como vc tem capturado os erros não está correta e as sugestões feitas pelos colegas são válidas e vc deve observá-las.
Mas e quanto aos erros não checados ou aos famigerados SQLException ?
Vc tem razão em se preoculpar em mostrar uma página de erro ao usuário (ou para vc mesmo descrevendo o erro).
Para fazer isso vc deve dentro do catch passar o controle da aplicação para o jsp. Como ? Por exemplo assim:

try
{

}
catch(SQLException ex)
{
ex.printStackTrace();
request.setAttribute(“javax.servlet.jsp.jspException” , new Exception(“Erro no acesso ao banco de dados”));
rd = getServletContext().getRequestDispatcher("/erro.jsp");
}
Isso fará com que o erro seja capturado, impresso no log do conteiner (ou no console da IDE que vc estiver usando para rodar o servlet), seta um obj jspException, cria uma mensagem de erro (vc pode simplesmente colocar a mensagem padrão do erro capturado, mas no caso de uma mensagem para um usuário comum isso não vai dizer grande coisa) e em seguida passa o controle para uma jsp que ira pegar a mensagem e exibí-la.

Valeu galera!!
Vou corrigir essas falhas.