@Async does not work in Spring

0

From a web application with spring I want to send emails, and I want to do it asynchronously.

For this I want to use the annotation @Async of spring.

This is the configuration I have: servlet-context.xml

<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

<context:component-scan base-package="com.erodrigo.confianza" />

<!-- Anotaciones en tareas programadas -->
<task:annotation-driven/>

<!-- Enables the Spring MVC @Controller programming model -->
<context:annotation-config />
<annotation-driven>
    <message-converters>
        <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
        <beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </message-converters>
</annotation-driven>

Then I have an interface where I declare the methods.

@Service
public interface EmailTaskService {

/**
 * 
 * @param usuario
 * @throws Exception
 */
@Async
public void sendMailNewUser(UsuarioDto usuario) throws Exception;

/**
 * 
 * @param contratista
 * @param tipoDocumento
 * @param nombreDocumento
 * @throws Exception
 */
@Async
public void sendMailDocumentoCaducado(EmpresasDto contratista, String nombreDocumento, String fechaCaducidad) throws Exception;

/**
 * 
 * @param usuario
 * @throws Exception
 */
@Async
public void sendMailResetPass(UsuarioDto usuario) throws Exception;

/**
 * 
 * @throws Exception
 */
@Async
public void sendMailTest() throws Exception;

/**
 * 
 * @return
 * @throws Exception
 */
public MimeMessage createMimeMessage() throws Exception;

/**
 * 
 * @param message
 * @throws Exception
 */
public void send(MimeMessagePreparator message) throws Exception;

/**
 * 
 * @param message
 * @throws Exception
 */
public void send(MimeMessage message) throws Exception;

/**
 * 
 * @param message
 * @throws Exception
 */
public void send(SimpleMailMessage message) throws Exception;
}

And the class that implements them.

@Service
public class EmailTaskServiceImpl implements EmailTaskService {

private PropertiesConfiguration properties;
private MailSender mailSender;
private JavaMailSender javaMailSender;
private VelocityEngine velocityEngine;

@Override
@Async
public void sendMailNewUser(final UsuarioDto usuario) throws Exception {
    MimeMessagePreparator preparator = new MimeMessagePreparator() {
        public void prepare(MimeMessage mimeMessage) throws Exception {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
            message.setTo(usuario.getEmail());
            message.setFrom(new InternetAddress(EmailsConstants.CUENTA_EMAIL, EmailsConstants.APP_NAME));

            Map<String, Object> map = new HashMap<String, Object>();
            System.out.println(usuario.getNombreCompleto());
            map.put("nombreUsuario", usuario.getNombreCompleto());
            map.put("user", usuario.getEmail());
            map.put("userPass", usuario.getPass());
            map.put("enlaceApp", properties.getString(EmailsConstants.URL_APP));

            @SuppressWarnings("deprecation")
            String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
                    EmailsConstants.VM_NUEVO_USUARIO, map);

            message.setSubject(EmailsConstants.SUBJECT_NEW_USER);
            message.setText(text, true);
        }
    };

    send(preparator);
}

@Override
@Async
public void sendMailDocumentoCaducado(final EmpresasDto contratista, final String nombreDocumento, final String fechaCaducidad) throws Exception {
    MimeMessagePreparator preparator = new MimeMessagePreparator() {
        public void prepare(MimeMessage mimeMessage) throws Exception {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
            message.setTo(contratista.getEmail());
            message.setFrom(new InternetAddress(EmailsConstants.CUENTA_EMAIL, EmailsConstants.APP_NAME));

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("nombreContratista", contratista.getRazonSocial());
            map.put("nombreDocumento", nombreDocumento);
            map.put("fechaCaducidad", fechaCaducidad);
            map.put("enlaceApp", properties.getString(EmailsConstants.URL_APP));

            @SuppressWarnings("deprecation")
            String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
                    EmailsConstants.VM_DOCUMENTO_CADUCADO, map);

            message.setSubject(EmailsConstants.SUBJECT_DOCUMENTO_CADUCADO);
            message.setText(text, true);
        }
    };

    send(preparator);
}

@Override
@Async
public void sendMailResetPass(final UsuarioDto usuario) throws Exception {
    MimeMessagePreparator preparator = new MimeMessagePreparator() {
        public void prepare(MimeMessage mimeMessage) throws Exception {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
            message.setTo(usuario.getEmail());
            message.setFrom(new InternetAddress(EmailsConstants.CUENTA_EMAIL, EmailsConstants.APP_NAME));

            Map<String, Object> map = new HashMap<String, Object>();
            System.out.println(usuario.getNombreCompleto());
            map.put("nombreUsuario", usuario.getNombreCompleto());
            map.put("user", usuario.getEmail());
            map.put("userPass", usuario.getPass());
            map.put("enlaceApp", properties.getString(EmailsConstants.URL_APP));

            @SuppressWarnings("deprecation")
            String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
                    EmailsConstants.VM_RESET_PASS, map);

            message.setSubject(EmailsConstants.SUBJECT_RESET_PASS);
            message.setText(text, true);
        }
    };

    send(preparator);
}

@Override
@Async
public void sendMailTest() throws Exception {
    System.out.println("Entro en sendMailTest()");
    MimeMessagePreparator preparator = new MimeMessagePreparator() {
        public void prepare(MimeMessage mimeMessage) throws Exception {
            System.out.println("Entro prepare()");
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true);
            message.setTo("[email protected]");
            message.setFrom(new InternetAddress(EmailsConstants.CUENTA_EMAIL, EmailsConstants.APP_NAME));

            Map<String, Object> map = new HashMap<String, Object>();

            @SuppressWarnings("deprecation")
            String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
                    "/velocity/test.vm", map);

            message.setSubject("Test");
            message.setText(text, true);
        }
    };

    System.out.println("Envio e correo");
    send(preparator);
    System.out.println("FIN envio correo");
}

@Override
public MimeMessage createMimeMessage() throws Exception {
    return javaMailSender.createMimeMessage();
}

@Override
public void send(MimeMessagePreparator message) throws Exception {
    javaMailSender.send(message);
}

@Override
public void send(MimeMessage message) throws Exception {
    javaMailSender.send(message);
}

@Override
public void send(SimpleMailMessage message) throws Exception {
    mailSender.send(message);
}

// GETTERS and SETTERS
public PropertiesConfiguration getProperties() {
    return properties;
}

public void setProperties(PropertiesConfiguration properties) {
    this.properties = properties;
}

public VelocityEngine getVelocityEngine() {
    return velocityEngine;
}

public void setVelocityEngine(VelocityEngine velocityEngine) {
    this.velocityEngine = velocityEngine;
}

public MailSender getMailSender() {
    return mailSender;
}

public void setMailSender(MailSender mailSender) {
    this.mailSender = mailSender;
}

public JavaMailSender getJavaMailSender() {
    return javaMailSender;
}

public void setJavaMailSender(JavaMailSender javaMailSender) {
    this.javaMailSender = javaMailSender;
}
}

Well, I do not know what I have wrongly configured but it does not execute the methods of sending emails asynchronously.

What am I doing wrong?

Thank you very much in advance.

    
asked by Enrique Rodrigo 18.12.2016 в 11:46
source

1 answer

2

Hi, you can review the jhipster implementation, you need to implement AsyncConfigurer and annotate your spring application with @EnableAsync

The @EnableAsync annotation modifies the ability for spring to be able to execute methods asynchronously @Async methods, in background using a thread pool, in this example the AsyncConfigurer interface is implemented or you can extend the AsyncConfigurerSupport class that already implements the interface.

source: link

Steps:

  • Provide an EJM configuration Bean
  • Enable Async config in your spring by providing a configuration object with the following annotations:

Here is an example of how jhipster manages the service implementation for sending emails and the async execution configuration

Implementation reference:

link

@Configuration
@EnableAsync
@EnableScheduling

public class AsyncConfiguration implements AsyncConfigurer {

    private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);

    @Inject
    private JHipsterProperties jHipsterProperties;

    @Override
    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        log.debug("Creating Async Task Executor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
        executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
        executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
        executor.setThreadNamePrefix("codelogs-Executor-");
        return new ExceptionHandlingAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

Reference code impl of mail service:

github.com/jhipster/jhipster-sample-app/blob/40e38a8eed371c51c67b051664b6ec99c4dbadd7/src/main/java/io/github/jhipster/sample/service/MailService.java

@Service

public class MailService {

private final Logger log = LoggerFactory.getLogger(MailService.class);

private static final String USER = "user";

private static final String BASE_URL = "baseUrl";

@Inject
private JHipsterProperties jHipsterProperties;

@Inject
private JavaMailSenderImpl javaMailSender;

@Inject
private MessageSource messageSource;

@Inject
private SpringTemplateEngine templateEngine;

@Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
    log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
        isMultipart, isHtml, to, subject, content);

    // Prepare message using a Spring helper
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    try {
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
        message.setTo(to);
        message.setFrom(jHipsterProperties.getMail().getFrom());
        message.setSubject(subject);
        message.setText(content, isHtml);
        javaMailSender.send(mimeMessage);
        log.debug("Sent e-mail to User '{}'", to);
    } catch (Exception e) {
        log.warn("E-mail could not be sent to user '{}'", to, e);
    }
}

@Async
public void sendActivationEmail(User user) {
    log.debug("Sending activation e-mail to '{}'", user.getEmail());
    Locale locale = Locale.forLanguageTag(user.getLangKey());
    Context context = new Context(locale);
    context.setVariable(USER, user);
    context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
    String content = templateEngine.process("activationEmail", context);
    String subject = messageSource.getMessage("email.activation.title", null, locale);
    sendEmail(user.getEmail(), subject, content, false, true);
}

@Async
public void sendCreationEmail(User user) {
    log.debug("Sending creation e-mail to '{}'", user.getEmail());
    Locale locale = Locale.forLanguageTag(user.getLangKey());
    Context context = new Context(locale);
    context.setVariable(USER, user);
    context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
    String content = templateEngine.process("creationEmail", context);
    String subject = messageSource.getMessage("email.activation.title", null, locale);
    sendEmail(user.getEmail(), subject, content, false, true);
}

@Async
public void sendPasswordResetMail(User user) {
    log.debug("Sending password reset e-mail to '{}'", user.getEmail());
    Locale locale = Locale.forLanguageTag(user.getLangKey());
    Context context = new Context(locale);
    context.setVariable(USER, user);
    context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
    String content = templateEngine.process("passwordResetEmail", context);
    String subject = messageSource.getMessage("email.reset.title", null, locale);
    sendEmail(user.getEmail(), subject, content, false, true);
}

}

answered by 25.12.2016 в 16:38