问题与春@Async方法不要再追/重新抛出异常 [英] Issue with a Spring @Async method not catching/rethrowing an exception

查看:3096
本文介绍了问题与春@Async方法不要再追/重新抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在面临一个问题,因为我启用翻了同步方法为异步之一:如果异常是从方法体中抛出,我不能再重新抛出

I am facing an issue since I enabled turned a synchronous method into an asynchronous one: if an exception is thrown from within the body of the method, I can no longer rethrow it.

让我先显示code:

我的异步/任务执行的配置:

My async/task executor configuration:

@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.initialize();
        return taskExecutor;
    }
}

我的异步方法:

@Async
@Override
public void sendPasswordResetInfo(String email) {
    Assert.hasText(email);
    Member member = memberRepository.findByEmail(email);
    try {
        mailerService.doMailPasswordResetInfo(member);//EXCEPTION THROWN HERE
    } catch (MessagingException | MailSendException e) {
        log.error("MessagingException | MailSendException", e);
        // TODO: not thrown since @Async is used
        throw new MailerException("MessagingException | MailSendException");//NOT CALLED
    }
}

我只在异常时由 mailerService.doMailPasswordResetInfo 提出的控制台中看到如下堆栈跟踪:

All I see in the console when an exception is raised by mailerService.doMailPasswordResetInfo is the following stacktrace:

2014-06-20 18:46:29,249 [ThreadPoolTaskExecutor-1] ERROR com.bignibou.service.preference.PreferenceServiceImpl - MessagingException | MailSendException
org.springframework.mail.MailSendException: Failed messages: javax.mail.SendFailedException: Invalid Addresses;
  nested exception is:
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 Adresse d au moins un destinataire invalide. Invalid recipient. OFR204_418 [418]
; message exception details (1) are:
Failed message 1:
javax.mail.SendFailedException: Invalid Addresses;
  nested exception is:
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 Adresse d au moins un destinataire invalide. Invalid recipient. OFR204_418 [418]

    at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1294)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:635)
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:424)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:346)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:341)
    at com.bignibou.service.mailer.MailerServiceImpl.doMailPasswordResetInfo(MailerServiceImpl.java:82)
    at com.bignibou.service.preference.PreferenceServiceImpl.sendPasswordResetInfo_aroundBody10(PreferenceServiceImpl.java:112)
    at com.bignibou.service.preference.PreferenceServiceImpl$AjcClosure11.run(PreferenceServiceImpl.java:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    at com.bignibou.service.preference.PreferenceServiceImpl.sendPasswordResetInfo_aroundBody12(PreferenceServiceImpl.java:108)
    at com.bignibou.service.preference.PreferenceServiceImpl$AjcClosure13.run(PreferenceServiceImpl.java:1)
    at org.springframework.scheduling.aspectj.AbstractAsyncExecutionAspect.ajc$around$org_springframework_scheduling_aspectj_AbstractAsyncExecutionAspect$1$6c004c3eproceed(AbstractAsyncExecutionAspect.aj:58)
    at org.springframework.scheduling.aspectj.AbstractAsyncExecutionAspect.ajc$around$org_springframework_scheduling_aspectj_AbstractAsyncExecutionAspect$1$6c004c3e(AbstractAsyncExecutionAspect.aj:62)
    at com.bignibou.service.preference.PreferenceServiceImpl.sendPasswordResetInfo(PreferenceServiceImpl.java:108)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:97)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 Adresse d au moins un destinataire invalide. Invalid recipient. OFR204_418 [418]

    at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1145)
    ... 28 more

仅供参考, MailerException 是我在应用程序中使用自定义异常。真正打动我的是,这个 MailerException 例外似乎并不被抓到,也重新抛出...

FYI, MailerException is a custom exception I used in the app. What really strikes me is that this MailerException exception does not appear to be caught nor rethrown...

任何人都可以请帮助?

编辑1:我已经修改我的异步服务方法如下:

edit 1: I have modified my async service method as follows:

@Async
    @Override
    public Future<Void> sendPasswordResetInfo(String email) {
        Assert.hasText(email);
        Member member = memberRepository.findByEmail(email);
        try {
            mailerService.doMailPasswordResetInfo(member);
            return new AsyncResult<Void>(null);
        } catch (MessagingException | MailSendException e) {
            log.error("MessagingException | MailSendException", e);
            //HERE: HOW DO I SEND THE MailerException USING THE FUTURE??
            throw new MailerException("MessagingException | MailSendException");
        }
    }

不过,我的不知道如何将MailerException发送到以上...

However, I am not sure how to send the MailerException to the web layer using the AsyncResult from within the catch block above...

推荐答案

您的日志显示

2014-06-20 18:46:29,249 [ThreadPoolTaskExecutor-1] ERROR com.bignibou.service.preference.PreferenceServiceImpl - MessagingException | MailSendException

这是由

log.error("MessagingException | MailSendException", e);

例外,然后将其抛出

throw new MailerException("MessagingException | MailSendException");//NOT CALLED

是由由基础 ThreadPoolTask​​Executor类执行捕获。这code异步运行,所以异常在不同的线程,然后调用该方法的线程抛出。

is caught by the Thread executed by the underlying ThreadPoolTaskExecutor. This code is run asynchronously so the exception is thrown in a different thread then the thread that invokes the method.

someCode();
yourProxy.sendPasswordResetInfo(someValue()); // exception thrown in other thread
moreCode();

如果你让你的方法返回一个未来如图所示<一个href=\"http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-async\">here你就可以调用的get()就可以了,这将再次引发被里面的 @Async 方法,包裹在一个为ExecutionException

If you make your method return a Future as shown here you'll be able to invoke get() on it and that will rethrow any exception that was thrown inside the @Async method, wrapped in an ExecutionException.

这篇关于问题与春@Async方法不要再追/重新抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆