Como pegar o Exception do TopLInk?

Não estou conseguindo pegar a exceção que dá na persistência/TopLink que vem do meu DAO.

Código no DAO:

public boolean inserir(T obj) throws Exception { Vendedor item = (Vendedor) obj; EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); try { this.gerenciador.persist(item); transacao.commit(); return true; } catch (Exception ex) { transacao.rollback(); // essa é a linha 33 no DAO // quero pegar no View a exceção gerada aqui return false; } }

Código no View:

try { salvo = new VendedorDAO().inserir(vendedor); // linha 468 } catch (Exception ex) { Logger.getLogger(VendedorUI.class.getName()).log(Level.SEVERE, null, ex); Lib.Warning(frame, "Erro ao salvar", Lib.getStackTrace(ex), 1); }

Exception disparada no DAO:

[TopLink Warning]: 2009.12.17 11:47:09.968--UnitOfWork(17957281)--Local Exception Stack: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.DatabaseException Internal Exception: java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Duplicate entry '115.393.028-57' for key 'CPF'" Error Code: 1062 Call: INSERT INTO VENDEDOR (CALCULAR_SOBRE_VALOR_FRETE, OBSERVACAO, TELEFONE, LOGRADOURO, CPF, NUMERO, PERCENTUAL_COMISSAO, BAIRRO, NOME, CIDADE, RG, ESTADO, EMAIL, COMPLEMENTO, INCLUIR_TAXAS, CEP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) bind => [true, , , , 115.393.028-57, 0, 3.0, , JOSÉ DA SILVA, , , SP, , null, true, ] Query: InsertObjectQuery([ Cadastro de Vendedor ]) at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311) at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654) at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703) at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492) at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452) at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690) at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228) at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214) at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:346) at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:191) at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:205) at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:564) at oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(InsertObjectQuery.java:89) ...

Exception mostrada no View:

java.lang.IllegalStateException: Exception Description: No transaction is currently active at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.rollback(EntityTransactionImpl.java:140) at horus.dao.VendedorDAO.inserir(VendedorDAO.java:33) at horus.ui.VendedorUI.setSalvar(VendedorUI.java:468) at horus.ui.VendedorUI.btnSalvarActionPerformed(VendedorUI.java:362) at horus.ui.VendedorUI.access$200(VendedorUI.java:30) at horus.ui.VendedorUI$3.actionPerformed(VendedorUI.java:189) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) ...
Eu sei que esse forum é um pouco “lento” mas será que alguém tem alguma dica?

Ué, mas seu código engole a exception! Como você espera captura-la na view?

Comece removendo os “return true” e “return false” do método inserir, e deixe a exception subir de camada.

Outra coisa “throws Exception” é feio hein?

O que o ViniGodoy falou está certo, mas eu acho que não tem como capturar essa exception. Ao menos eu nunca consegui.

PALPITE é que essa saída ocorre não porque a exception é disparada, mas é a maneira que o Toplink (Eclipselink no meu caso) trata: com uma impressão no console.

É mesmo “feio”? Como melhoro isso? :frowning:

Corrigindo, falei um pouco de besteira. O meu post anterior se refere a exception do DAO.
A segunda exception (que ocorre no rollback) é sim tratável.

Se eu deixar assim:

public boolean inserir(T obj) throws Exception { Vendedor item = (Vendedor) obj; EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); this.gerenciador.persist(item); transacao.commit(); return true; } Eu capturo a Exception correta no view porém não tem como dar o rollback na transação.

a idéia é vc empacotar essa SQLException na sua própria exception e subir isso pra view. se vc ficar fazendo esses upcastings de exceção vai transformar tudo no mesmo tipo de erro. é importante voce classificar para poder tratar da melhor forma.

a idéia é vc empacotar essa SQLException na sua própria exception e subir isso pra view. se vc ficar fazendo esses upcastings de exceção vai transformar tudo no mesmo tipo de erro. é importante voce classificar para poder tratar da melhor forma.[/quote]
Entendi mais ou menos, teria um exemplo simples para me mostrar?

a idéia é vc empacotar essa SQLException na sua própria exception e subir isso pra view. se vc ficar fazendo esses upcastings de exceção vai transformar tudo no mesmo tipo de erro. é importante voce classificar para poder tratar da melhor forma.[/quote]
Entendi mais ou menos, teria um exemplo simples para me mostrar?[/quote]
sim

public void inserir(T obj) throws SuaDaoException { try{ //persistencia } catch(SQLException e){ throws new SuaDaoException("SQL Exception: erro inserindo blablabla...",e); } }

a idéia é vc empacotar essa SQLException na sua própria exception e subir isso pra view. se vc ficar fazendo esses upcastings de exceção vai transformar tudo no mesmo tipo de erro. é importante voce classificar para poder tratar da melhor forma.[/quote]
Entendi mais ou menos, teria um exemplo simples para me mostrar?[/quote]
sim

public void inserir(T obj) throws SuaDaoException { try{ //persistencia } catch(SQLException e){ throws new SuaDaoException("SQL Exception: erro inserindo blablabla...",e); } } [/quote]

Seria isso?

[code]public class HorusDAOException extends Exception {

public HorusDAOException() {
}

public HorusDAOException(Throwable e) {
    super(e);
}

public HorusDAOException(String msg, Throwable e) {
    super(msg, e);
}

public HorusDAOException(String msg) {
    super(msg);
}

}[/code]

public boolean inserir(T obj) throws HorusDAOException { EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); try { this.gerenciador.persist(obj); transacao.commit(); return true; } catch (Exception ex) { transacao.rollback(); // Parece que ta dando uma Exception aqui... throw new HorusDAOException("ERRO SALVANDO VENDEDOR", ex); } }

cara nem esquenta com essa própria exceção então… simplesmnte jogue o SQLException pra frente e seja feliz :wink:

fiquei arrependido de ajudar alguém a complicar algo simples :smiley:

Ou você lança a própria SQL, ou lança uma RuntimeException, como o colega indicou. Tipicamente, só vale a pena lançar exceptions verificadas para coisas que a aplicação poderá tratar.
Dá uma lida:



Muitíssimo obrigado pelas respostas, fiz o tratamento “aparentemente” correto, porém ele dispara uma outra Exception na linha do rollback, por isso a Exception que chega na View não é a mesma que dispara no DAO, quando eu removo o rollback a Exception do primeiro erro (a verdadeira) é enviada para a camada de cima.

Eu preciso dar esse rollback porque a inserção (ou qualquer outra operação) precisa ser cancelada, senão o atributo Id fica sendo auto-incrementado sem necessidade.

Coloquei o lançamento da Exception no catch e o rollback no finally, pelo que entendi sempre que houver uma Exception o finally é executado, isso resolveria o problema do rollback se não desse essa outra Exception (IllegalStateException: Exception Description: No transaction is currently active).

Mostrada no DAO com ex.printStackTrace():

avax.persistence.RollbackException: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.DatabaseException Internal Exception: java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Duplicate entry '115.393.028-57' for key 'CPF'" Error Code: 1062 Call: INSERT INTO VENDEDOR (CALCULAR_SOBRE_VALOR_FRETE, OBSERVACAO, TELEFONE, LOGRADOURO, CPF, NUMERO, PERCENTUAL_COMISSAO, BAIRRO, NOME, CIDADE, RG, ESTADO, EMAIL, COMPLEMENTO, INCLUIR_TAXAS, CEP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) bind => [true, , , , 115.393.028-57, 0, 5.0, , ANTONIO, , , SP, , null, true, ] Query: InsertObjectQuery([ Cadastro de Vendedor ]) at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:120) at oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:60) at horus.dao.VendedorDAO.inserir(VendedorDAO.java:31) at horus.ui.VendedorUI.setSalvar(VendedorUI.java:468) ...

Capturada no View:java.lang.IllegalStateException: Exception Description: No transaction is currently active at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.rollback(EntityTransactionImpl.java:140) at horus.dao.VendedorDAO.inserir(VendedorDAO.java:40) // Essa é a linha do rollback at horus.ui.VendedorUI.setSalvar(VendedorUI.java:468) at horus.ui.VendedorUI.btnSalvarActionPerformed(VendedorUI.java:362) at horus.ui.VendedorUI.access$200(VendedorUI.java:30)
Método no DAO:

public boolean inserir(T obj) throws HorusDAOException { EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); try { this.gerenciador.persist(obj); transacao.commit(); return true; } catch (Exception ex) { ex.printStackTrace(); throw new HorusDAOException("ERRO SALVANDO VENDEDOR", ex); } finally { // Ao invés de mandar para o View a Exception do catch está dando: // IllegalStateException: Exception Description: No transaction is currently active // Nessa linha linha do rollback transacao.rollback(); System.out.println("--------------- Fez o Rollback no DAO");// Nunca chega nessa linha } } A pergunta é: se ocorreu a exception porque a transação não está mais ativa no rollback?

Dando mais uma lida internet a fora consegui montar esse método que envia a exceção correta, meu problema agora é que quando ocorre a exception e dou o rollback o meu campo de auto-incremento NÃO deveria ser incrementado, está certo isso?
Nessa caso específico é uma entidade simples com um atributo código que deve ser sequencial.

public boolean inserir(T obj) throws HorusDAOException { EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); try { this.gerenciador.persist(obj); transacao.commit(); } catch (RuntimeException ex) { if (transacao.isActive()) { try { transacao.rollback(); } catch (RuntimeException e) { } } throw ex; } finally { gerenciador.close(); } return true; }

[quote=javer]Dando mais uma lida internet a fora consegui montar esse método que envia a exceção correta, meu problema agora é que quando ocorre a exception e dou o rollback o meu campo de auto-incremento NÃO deveria ser incrementado, está certo isso?
Nessa caso específico é uma entidade simples com um atributo código que deve ser sequencial.

public boolean inserir(T obj) throws HorusDAOException { EntityTransaction transacao = this.gerenciador.getTransaction(); transacao.begin(); try { this.gerenciador.persist(obj); transacao.commit(); } catch (RuntimeException ex) { if (transacao.isActive()) { try { transacao.rollback(); } catch (RuntimeException e) { } } throw ex; } finally { gerenciador.close(); } return true; } [/quote]

bixo a transação não fica dentro dos métodos do dao, é fora :wink: e como te falei antes, esquece essa história de própria exception :slight_smile:

vc só precisa disso:

public void inserir(T obj) throws SQLException { this.gerenciador.persist(obj); }
e depois na view…

public void salvar(){ EntityTransaction transacao = this.gerenciador.getTransaction(); try { transacao.begin(); new Dao(gerenciador).inserir(obj); //vc tem q ver certinho um jeito de passar a sessão do toplink, eh apenas um exemplo transacao.commit(); } catch (SQLException ex) { //seu tratamento } }

e outra não existe transação pra fazer rollback quando vc está fazendo apenas uma operação no banco :wink: