#java #transactions #jax-rs #ejb #jta
#java #транзакции #jax-rs #ejb #jta
Вопрос:
Каковы обстоятельства: На Wildfly 15 развернуты REST API и серверный компонент EJB. Вызов REST запускает транзакцию и запускает пользовательское событие CDI. В моем серверном компоненте существует метод транзакционного наблюдателя с фазой транзакции ДО_COMPLETION. При некоторых условиях внутри этого метода намеренно генерируется исключение во время выполнения пользовательского типа с определенным сообщением. Я ожидаю, что транзакция будет откатана в этом случае (что также правильно происходит). Исключение, которое вызвало откат, я хочу обработать в устройстве отображения исключений JAX-RS и, наконец, отправить определенный код ответа HTTP и сообщение из исключения.
Теперь почти все работает так, как я хочу: транзакция откатывается, подключается метод сопоставления исключений и обрабатывает исключение.
Но моя большая проблема в том, что исключение, которое я получаю в качестве аргумента в преобразователе исключений, имеет тип javax.transaction.RollbackException
, а не мой ожидаемый пользовательский тип, который был изначально выдан. Точное сообщение таково: « javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
» Кроме того, мое исключение, похоже, нигде не вложено, например, в качестве причины или в стеке вызовов полученного исключения, поэтому я не могу понять, в чем заключается мое сообщение, а также я не смог бы отличить этот откат от других потенциальных откатов по другим причинам (например, ошибки базы данных и т.д.)
Вопрос: возможна ли вообще моя желаемая идея, описанная выше? Может быть, я совершенно неправильно понимаю, как работает фреймворк, из-за отсутствия у меня опыта работы с Java EE, и этот сценарий принципиально не может работать таким образом? Знать это уже было бы полезно для меня. В противном случае, что я должен сделать, чтобы заставить это работать, или как я мог бы достичь желаемого результата с помощью другого подхода?
Вот мой текущий код:
Серверный компонент
import javax.ejb.Stateless;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.transaction.Transactional;
import my.custom.package.CustomRuntimeException
@Stateless
@Transactional
public class CustomBean
{
public void onNewCustomEvent(
@Observes( during = TransactionPhase.BEFORE_COMPLETION ) CustomEvent event )
{
// do something
if ( isSomeError )
{
throw new CustomRuntimeException("Some important detail message.");
}
}
}
Преобразователь исключений
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class CustomRuntimeExceptionMapper implements ExceptionMapper< Throwable >
{
@Override
public Response toResponse( Throwable e ) // <--- Expect: CustomRuntimeException, receive: RollbackException
{
// evaluate the exception and send proper HTTP code
return Response.status( Response.Status.NOT_FOUND ).build();
}
}
Класс исключений
public class CustomRuntimeException extends RuntimeException
{
public CustomRuntimeException(String errorReason)
{
super (errorReason);
}
}
2020-08-17. Дополнительное замечание.
В журналах сервера я заметил это сообщение об ошибке, возможно, это полезно для лучшего понимания причины. Я поискал это в Google, но не смог найти ничего полезного.
WELD-000401: Failure while notifying an observer [UnbackedAnnotatedMethod] public CustomBean.onCustomEvent(@Observes CustomEvent) of event null.
CustomRuntimeException
Ответ №1:
На самом деле вы можете поместить эту аннотацию в свое пользовательское исключение
@javax.ejb.ApplicationException(rollback=true)
public class CustomRuntimeException extends RuntimeException{...}
Так что об исключении будет сообщено клиенту напрямую (развернуто).
По умолчанию контейнер EJB обернет ваше пользовательское исключение с помощью EJBException, и при использовании этой аннотации исключение не будет обернуто.
Но в вашем случае может быть другое исключение или причиной является откат, а не исключение CustomAppException попробуйте отладить выполнение вашего кода, чтобы выяснить, что на самом деле происходит, или предоставить полный код, чтобы мы могли попытаться помочь.
Комментарии:
1. Спасибо за ответ, к сожалению, это не изменило предыдущее поведение каким-либо существенным образом.
2. На самом деле я протестировал этот вариант использования для вас на wildfly 15.0.0.Final, и он работает так, как указано в документации Java
3. Когда вы определяете пользовательское исключение без аннотации, я получаю EJBException, оборачивающий мое пользовательское исключение, и если я использовал аннотацию, я получаю пользовательское исключение, развернутое в сопоставителе исключений jax-rs
4. Может быть, возникает другое исключение, а не ваше CustomException, поэтому вы не можете найти исключение в getCause() исключения отката
5. Не могли бы вы, пожалуйста, поместить полный код, который выполняется в обработчике событий?