Tenho que lançar uma exceção (própria) entre três módulos, em camadas diferentes, assim:
Camada de Infra - UsuarioDAOJdbc ( onde a excessão pode ocorrer )
public Usuario obterUsuarioPorUsername(String username) throws DAOException{
Usuario usuario = null;
String sql = "select * from usuario where login = ?";
PreparedStatement st = null;
ResultSet rs = null;
Connection con = DBUtil.getInstance().getConnection();
try {
st = con.prepareStatement(sql);
st.setString(1, username);
rs = st.executeQuery();
if (rs.next()) {
String nome = "";
String user = "";
String senha = "";
usuario= new Usuario(nome,user,senha);
usuario.setNome(rs.getString("nome"));
usuario.setUsername(rs.getString("login"));
usuario.setPassword(rs.getString("senha"));
}
} catch (SQLException ex) {
throw new DAOException(ex);
} finally {
try {
con.close();
DBUtil.getInstance().limpaCon();
} catch (SQLException e) {
throw new DAOException(ex);
}
}
return usuario;
}
Camada de Domínio - UsuarioRepositório (a “ponte” entre a camada da aplicação e a de infra)
public class UsuarioRepositorio {
private IUsuarioDAO usuarioDao = new UsuarioDAOJdbc();
public Usuario obterUsuarioPorUsername(String username) throws RepositorioException
{
return usuarioDao.obterUsuarioPorUsername(username);
}
}
Camada de aplicação- UsuarioRepositório (a “ponte” entre a camada da aplicação e a de infra)
...
UsuarioRepositorio ur = new UsuarioRepositorio();
try {
Usuario usuario = ur.obterUsuarioPorUsername(username);
if (usuario == null) {
return "/login.jsp?mensagem=Acesso Restrito";
} else {
System.out.println("Menu!!!!");
request.getSession().setAttribute("username", username);
return "/menu.jsp";
}
// Onde a exceção deve ser tratada
} catch (RepositorioException e) {
String message = "Houve um erro.";
return "/login.jsp?mensagem=Deu problema de excessão !!!!";
}
}
A questão é: Como “escrevo” as classes DAOException e RepositorioException , afim de que lançem a exceção desde a camada de DAO (usando DAOException) até a camada da aplicação (usando RepositorioException) ?
Anida não consegui compreender bem esse esquema de “lançar” exceções para uma outra classe “tratar”.
O ideial seria criar uma classe abstrata (classe pai) que extenda Exception. A partir dai, você cria suas classes extendendo da classe abstrata e que lança um determinado tipo de excessão. Mas se o seu problema está em lidar com Exception, use as que o próprio Java possiu. Um exemplo simples é você utilizar Exception em um determinado método, exemplo, método Inserir.
A partir do seu DAO, que seria a camada de nível mais baixo, você já faz esse tratamento, assim:
public void Inserir throws Exception{
//seu código
}
Quando usar o delegate para chamar este método obrigatoriamente terá que existir throws Exception e obriga você a usar try-catch ou throws mesmo no seu Servlet, se ocorrer uma excessão no seu DAO ele vai lançar essa excessão até a sua camada de mais alto nível, ai depois a questão é como você vai tratar isso
Vc está no bom caminho.
Vc já tem a estrutrua necessária.
A sua DAOException recebe uma SQLException no construtor.
Só precisa que a sua RepositorioException tb receba Exception no construtor.
Você pode criar uma filha de RepositorioException chamada DataAccessRepositoryException para marcar que é uma exceção de acesso aos dados. Mas isso fica a seu critério. A unica laterção que precisa fazer no seu codigo é:
No meu caso eu criei uma extrutura muito semelhante. Eu não tenho DAOs porque uso JPA, então apenas repositórios e os EJBs acessando esses repositórios. E ao invés de trabalhar com Exception tenho usado RuntimeException. Na camada web possui um exception-handlers que trata as exceptions.
abstract class AbstractApplicationException extends RuntimeException; - classe abstrata que todas herdam
public class InfraestructureException extends AbstractApplicationException; - erros de infra
public class RepositoryException extends AbstractApplicationException; - erros na camada repository
public class ServiceException extends AbstractApplicationException; - erros de regra de negócio
Eu já até tinha feito umas classes baseadas em exception (DAOException e RepositorioException) , mas não
consegui “repassar” a exceção do DAO para o Repositorio , e deste para o Servlet que esta na camada
mais “alta”.
Não deveria seria assim: ( sou newbie msmo em exceções - e ainda em mta coisa em java )
Classe DAOException
[code]public class DAOException extends Exception {
public DAOException(Exception e) throws RepositorioException
{
throw new RepositorioException(e);
}
}[/code]
Classe RepositorioException
[code]public class RepositorioException extends Exception {
public RepositorioException(Throwable cause)
{
cause.printStackTrace();
}
}[/code]
Vou tentar essas dicas de vcs sobre criar uma abstrata na qual as especificas se baseiam.
Eu já até tinha feito umas classes baseadas em exception (DAOException e RepositorioException) , mas não
consegui “repassar” a exceção do DAO para o Repositorio , e deste para o Servlet que esta na camada
mais “alta”.
Não deveria seria assim: ( sou newbie msmo em exceções - e ainda em mta coisa em java )
[/quote]
Então parabéns, porque seu codigo é melhor estruturado que muito codigo java que já vi por ai de pessoas que não se dizem newbies.
Veja bem, uma Exception é uma classe como qualquer outra.
Porquê o construtor da DAOException deveria lançar RepositorioException ?
Além disso ser uma violação das camadas ( o que já deveria ser um alerta) não faz sentido já que é impossivel criar um objeto da classe DAOException. Outra regra que vc está violando aqui é lançar exception no construtor. Embora possivel, isso é indicativo que ha algum problema com o design da sua classe.
Como o mario.fts já falou basta chamar o construtor da classe mãe através de super() Repare como o código correto não lança exceções no construtor, não usa throw no corpo do construtor e não viola camadas.
As exceções que advém de comunicação com outros sistemas tendem a ser verificadas. Neste caso as DAOException seriam verificadas, filhas de Exception.
As de repositório podem ser não verificadas já que o repositório não comunica diretamente com outros sistemas. Estas seria filhas de RuntimeException.
Uma outra forma de analisar é pensar que repositórios estão na layer de dominio, enquanto que DAO na de integração que está abaixo da de dominio. São layers diferentes e isso tem implicações na hierarquia de exceções.
O padrão Layer SuperType - em que ha um tipo master para a layer - tb se aplica a exceptions (aliás é essencial ser aplicado a exceptions) por isso cada layer deve ter um tipo de exceção que derive diretamente das exceções do java padrão. Ter um abstractException para todas as exceções do sistema não é boa prática porque fere uma das diretivas ao criar exceções : ser especifico.
Usar exceções verificadas é opcional em Java, vc pode sempre declarar como filha de runtime e escrever seu codigo sem problemas, contudo se vc seguir a regra de que camadas que comunicam com outros sistemas lançam exceções verificadas vc terá um controle melhor porque esse tipo de tratamento é feito apenas na fronteira das camadas e não polui o resto do sistema com tratamento redundante. O exemplo de encapsular DAOException em RepositoryException mostra isto claramente. Se DAOException for verificada o uso de try-catch para encapsular é obrigatório já que o Repositorio recebe essa exceçõa , mas não a pode declarar no throws do método. Isto leva a um otimo controle do fluxo de exceções e a uma boa programação.