Exceções do sistema EJB3.1 vs javax.ejb.EJBException

Apenas um pouco de fundo sobre as exceções do EJB3.1 antes de fazer a minha pergunta –

As exceções de aplicação incluem

As exceções do sistema incluem

  • java.rmi.RemoteException e suas exceções de subclass

  • Todas as exceções não verificadas

    java.lang.RuntimeException e suas exceções de subclass
    java.lang.Error e suas exceções de subclass

Abaixo está uma declaração que li neste livro

No sistema EJB exceções não são exceções pelo cliente, quando encontradas tais exceções não são passadas para o cliente como estão, mas são wrapaped em um javax.ejb.EJBException.

Minhas perguntas –

  1. Todas as exceções de aplicação descritas acima devem ser lançadas diretamente pelo EJB para o cliente?
  2. Se as exceções do sistema são agrupadas dentro de javax.ejb.EJBException antes de serem lançadas no cliente, então é javax.ejb.EJBException considerada como System Exception?

  1. Sim, mais ou menos é assim que funcionam. Para mais detalhes sobre os comportamentos do EJB, confira a seguinte postagem no blog: Link

Também desta pergunta :

Uma exceção de aplicativo deve ser lançada quando há um erro de lógica de negócios, ao contrário de um erro do sistema.

Há uma diferença importante: as exceções de aplicativo não fazem automaticamente a reversão de uma transação. O cliente tem a oportunidade de recuperar depois que uma exceção de aplicativo é lançada.

Exceções de aplicativo são enviadas ao cliente sem serem reempacotadas como uma exceção EJBException. Portanto, você pode usá-los para relatar erros de validação ou problemas de lógica de negócios e eles atingirão o cliente.

  1. javax.ejb.EJBException estende RuntimeException portanto, sim, é uma exceção do sistema.

Cenário comum associado a isso: se você tiver uma RuntimeException não RuntimeException no código do aplicativo, ela será RuntimeException . É um comportamento padrão bastante útil.

IndoKnight, que embrulho perfeito você deu de como a semântica de Exception no framework Java EE .. funciona.

Aqui estão as duas únicas linhas que um “bean provider”, que é você e eu, precisa saber sobre exceções no Java EE:

Seu bean é totalmente livre para se recuperar de qualquer tipo de exceção ou erro que você achar adequado, com relação a outras restrições que o bean possa estar. Se você se recuperou de uma exceção, então parabéns – não há mais problema =)

Uma restrição relevante poderia, por exemplo, ser que “beans corporativos que usam demarcação de transação gerenciada por contêiner não devem usar nenhum método de gerenciamento de transação que interfira nos limites de demarcação de transação do contêiner” para citar o tutorial do Java EE 7 página 48-2 ( você gostaria para definir programaticamente a reversão de uma transação gerenciada por contêiner, use EJBContext.setRollbackOnly () ).

Você também é desencorajado, como acontece com qualquer tipo de aplicativo Java, para lidar com Throwable ou Error lançado a partir de um nível realmente baixo. RuntimeException é contada teoricamente nesta categoria, como é tão famoso sinaliza um “erro do desenvolvedor” que é como “totalmente totalmente inesperado” – mas todos nós sabemos que não é.

Basicamente, uma exceção inesperada (exceções de tempo de execução + outras merdas que supomos serem originadas de outra pessoa) é considerada não manipulável pelo seu código e deve ser manipulada pelo servidor. O servidor é necessário para lidar com a exceção “unhandleable” ( ver a especificação do EJB 3.2 , página 204 ) imprimindo algo sobre isso no log ( eu vou entrar nos detalhes um pouco mais tarde! ).

Mais especificamente..

Você perguntou (e aqui está o que eu acredito ou é verdade):

Todas as exceções de aplicação descritas acima devem ser lançadas diretamente pelo EJB para o cliente?

Sim. E a transação (se estiver ativa) não deve ser revertida, a menos que você declare explicitamente que deve usar o atributo de reversão da ApplicationException . Código Java lançando exceções é algo muito natural. O Java EE não tem intenção de demolir esse modelo de programação. Portanto, vá em frente, ative as exceções verificadas da maneira que preferir, forçando os clientes a tentar capturá-las ou a marcar as exceções de tempo de execução como sendo exceções de aplicativos e as jogue também. Jogando feliz!

Se as exceções do sistema são agrupadas dentro de javax.ejb.EJBException antes de serem lançadas no cliente, então é javax.ejb.EJBException considerada como System Exception?

Sim , mas não pelo motivo que você fornece. Para ser claro, não há nenhum tipo chamado SystemException. É apenas uma expressão sofisticada para descrever esse tipo de exceção que a maioria dos beans que não estavam lá não poderia acontecer e, muito provavelmente, eles se originam do contêiner EJB. Seu código definitivamente não deve lançar uma exceção EJBException. Fazer isso provavelmente apenas frustraria a mente do servidor. Nem você pode anotar a exceção como sendo @ApplicationException, já que você não possui o código, ele é fornecido pela API do Java EE. Você poderia estender o EJBException, mas não faria sentido disfarçar seu código como parte da base de código do servidor. Mais importante ainda, como o EJBException estende o RuntimeException , acho que é seguro categorizar o EJBException como uma “exceção de nível de sistema”.

Cuidado com o diabo

Alguns clientes remotos receberão o RemoteException em vez do EJBException.

Interceptores que você pode nem mesmo estar ciente em um grande projeto corporativo, poderia engolir exceções lançadas a partir do seu método fazendo uma transação ativa, mesmo que você nunca tenha planos de deixá-lo fazer isso.

Eu aposto que você acha que uma exceção suprimida é sempre recuperável usando Throwable.getCause () . Observe que a especificação do EJB 3.2 não diz que o contêiner deve ou deve poupar uma referência à causa suprimida. Na verdade, a única coisa que o contêiner tem que fazer é registrar a exceção. Então, se o bean não for um singleton, a instância do bean deve ser descartada e nunca usada novamente. Além disso, se o bean for um bean acionado por mensagens, apenas a exceção original será “envolvida”. How-to “wrap” a exceção não é especificada. Código legal super portátil deve provavelmente dar uma olhada no método Throwable.getCause () e Throwable.getSuppressed () também. Não espere cegamente em seu código de manipulação para encontrar sempre a exceção original.

Métodos asynchronouss (methods de bean de session pública anotados como @Aynchronous ) que retornam void não podem propagar uma exceção para seu cliente. Portanto, eles não devem declarar ou lançar exceções de aplicativo ( consulte a página 82 da especificação EJB 3.2 ). Observe que, quando você invoca um método asynchronous, pode ser que o servidor não possa fornecer resources de encadeamento para atender à sua solicitação e, em caso afirmativo, ele é obrigado a lançar um. EJBException ( página 48 )!