您好我在异步发送电子邮件时遇到问题。我按照this tutorial.
中的说明设置了所有内容我已使用@Service
注释了我的电子邮件服务,将其设置为bean,并使用@Async
注释该方法。
然后我将@Autowired
服务到控制器并使用该方法。虽然它不会异步执行,但需要两秒钟才能超过emailSerivce.sendMail();
任何想法我做错了什么?
我的电子邮件服务设置如下。
@Service
public class EmailService {
//get log4j handler
private static final Logger logger = Logger.getLogger(EmailService.class);
// Sends an email with the following parameters
@Async
public Future<Page> sendEmail(CustomPropertiesForm cpf, String [] recipients, MimeBodyPart attachment, String subject, String content){
// Initialise local variables
Boolean success = false;
Boolean isAuthenticationRequired = false;
String smtpAuthUsername = null;
String smtpAuthPassword = null;
try{
Thread.sleep(5000);
logger.info("Sending Email");
// Build properties
Properties props = new Properties();
if(cpf.getSmtpAuthenticationRequired().equals("YES")){
isAuthenticationRequired = true;
props.put("mail.smtp.auth", "true");
smtpAuthUsername = cpf.getSmtpAuthUsername();
smtpAuthPassword = cpf.getSmtpAuthPassword();
} else {
props.put("mail.smtp.auth", "false");
}
if (cpf.getSmtpSSLRequired().equalsIgnoreCase("YES")) {
//- See more at: http://www.jvmhost.com/articles/how-to-send-mail-with-javamail-and-tomcat#sthash.3IN3wreU.dpuf
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.transport.protocol", cpf.getSmtpProtocol());
props.put("mail.smtps.port", cpf.getSmtpHostPort());
props.put("mail.smtps.ssl.trust", cpf.getSmtpHostName());
} else {
props.put("mail.smtp.ssl.enable", "false");
}
props.put("mail.smtp.host", cpf.getSmtpHostName());
props.put("mail.smtp.port", cpf.getSmtpHostPort());
props.put("mail.transport.protocol", cpf.getSmtpProtocol());
// Create mail Session
Session mailSession = Session.getDefaultInstance(props);
mailSession.setDebug(false);
Transport transport = mailSession.getTransport();
// Create Message
MimeMessage message = new MimeMessage(mailSession);
// Add recipients
for(String string : recipients){
message.addRecipient(Message.RecipientType.TO,new InternetAddress(string));
}
// Set From Address
message.setFrom(new InternetAddress(cpf.getDefaultApplicationEmailAddress()));
// Set subject
message.setSubject(subject);
// Set content
MimeBodyPart mbpText = new MimeBodyPart();
mbpText.setText(content);
MimeMultipart mp = new MimeMultipart();
mp.addBodyPart(mbpText);
message.setContent(mp);
// Add attachment
if(attachment != null){
mp.addBodyPart(attachment);
}
// Connect to mail server and send email
if(isAuthenticationRequired){
transport.connect(cpf.getSmtpHostName(), Integer.parseInt(cpf.getSmtpHostPort()), smtpAuthUsername, smtpAuthPassword);
transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
transport.close();
} else {
transport.connect();
transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
transport.close();
}
success = true;
logger.info("Email Sent");
} catch (Exception e){
logger.error(e.getMessage() + " " + e.getCause() + " " + e.fillInStackTrace());
System.out.println(e.getMessage() + " " + e.getCause() + " " + e.fillInStackTrace());
}
}
Page result = new Page();
result.setName("name");
result.setWebsite("website.com");
return new AsyncResult<Page>(result);
}
在我的调度程序servlet中,我将其设置为bean,
<bean id="emailService"
class="ie.premiumpower.services.EmailService">
</bean>
然后我从我的控制器中使用这个电子邮件服务,
@Controller
public class NotSecureController extends AbstractController {
@Autowired
private EmailService emailService;
@RequestMapping("notsecure/taskSummary/shareTaskSummary.json")
public String getQuestions(
@RequestParam("taskInstanceId") int taskInstanceId,
@RequestParam("emailAdresses[]") String emailAddresses[]) {
try {
long currTime = System.currentTimeMillis();
System.out.println("Email being sent at time: " + currTime);
Future<Page> sendEmail = emailService.sendEmail(cpf, emailAddresses, null, subject, content);
while (!(sendEmail.isDone())) {
Thread.sleep(10);
}
long aftTime = System.currentTimeMillis();
aftTime = aftTime - currTime;
System.out.println("Email finished being sent in time: " + aftTime);
System.out.println(": " + sendEmail.get());
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
e.printStackTrace();
}
即使我改变它以返回未来,它仍然需要7秒(带睡眠)。
我的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<resource-ref>
<description>ArcFlashMap DB Connection</description>
<res-ref-name>jdbc/AFM_DB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<servlet>
<servlet-name>LoadResourcesServlet</servlet-name>
<servlet-class>ie.premiumpower.services.reports.common.LoadResourcesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
-1
</session-timeout>
</session-config>
我的applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<context:annotation-config />
<mvc:annotation-driven />
<mvc:interceptors>
<bean id="webContentInterceptor"
class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0"/>
<property name="useExpiresHeader" value="true"/>
<property name="useCacheControlHeader" value="true"/>
<property name="useCacheControlNoStore" value="true"/>
</bean>
</mvc:interceptors>
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="7"/>
我的dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="ie.premiumpower.controllers" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonHttpMessageConverter"/>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="false"/>
</bean>
</list>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="10000000"/>
</bean>
<bean id="emailService"
class="ie.premiumpower.services.EmailService">
</bean>
尝试使用component-scan pointent将程序运行到ie.premiumpower时出现异常。
Sep 23, 2015 11:20:02 AM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /SafeSiteLive threw load() exception
java.lang.IllegalStateException: Annotation-specified bean name 'emailService' for bean class [ie.premiumpower.services.scheduledTaskServices.EmailService] conflicts with existing, non-compatible bean definition of same name and class [ie.premiumpower.services.EmailService]
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:274)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:215)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1335)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1325)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:93)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:124)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:93)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:442)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:458)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:339)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:306)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5229)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5516)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:672)
at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1862)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
答案 0 :(得分:1)
试试这个:
好的,你可以尝试一件事,通过调用Thread.sleep(5000)让异步线程休眠5秒钟。这样,您就会知道,这不仅仅是创建异步任务需要2秒。如果这没有帮助,那么删除Thread.sleep,并执行以下操作。
如果您想要获得结果,请使用Future标记,如下所述:
@Async
public Future<Page> sendEmail(params) throws InterruptedException{
return new AsyncResult<Page>(your_result);
}
在您的控制器中:
Future<Page> sendEmail = sendEmail(params);
并检查这种方式,如果他们完成了:
while (!(sendEmail.isDone() ) {
Thread.sleep(10);
}
Lemme知道。
答案 1 :(得分:0)
看看片段,似乎缺少异步设置。我想添加@EnableAsync注释可能会解决问题。
@EnableAsync
@Service
public class EmailService
答案 2 :(得分:0)
似乎问题是因为您没有指定使用Future
类型的返回类型。
查看您提供的网址,有一句话说
方法的返回类型是Future而不是Page,这是对任何异步服务的要求。此代码使用AsyncResult的具体实现来包装Facebook查询的结果。
因此,请尝试更改您的退货方式,然后重试。
答案 3 :(得分:0)
好的我知道了。
我将applicationContext更改为此
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="ie.premiumpower.services" />
<mvc:annotation-driven />
<mvc:interceptors>
<bean id="webContentInterceptor"
class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0"/>
<property name="useExpiresHeader" value="true"/>
<property name="useCacheControlHeader" value="true"/>
<property name="useCacheControlNoStore" value="true"/>
</bean>
</mvc:interceptors>
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="10" queue-capacity="10"/>
<task:scheduler id="myScheduler" pool-size="10"/>
<bean id="emailService"
class="ie.premiumpower.services.EmailService">
</bean>
将bean放在此处并对打包的服务进行扫描,
我使用@Service注释了我的服务,使用@Async注释了方法。
我公开了@Autowired EmailService(不知道这是否重要)。
最后我获得了Asm库(clib需要)。
(我从dispatcher-servlet中删除了EmailService bean。)