Edmond
Edmond

Reputation: 645

Quartz job to send email using Javamail, but Javamail is synchronous

The title basically sums up my issue at the moment. If I have multiple instances of the Job running at/around the same time, Javamail throws an exception as it's meant to be used synchronously. Is there a way I can make it run asynchronously? Or is there an alternative to Javamail that is asynchronous?

Upvotes: 0

Views: 714

Answers (2)

sagneta
sagneta

Reputation: 1701

I do this sort of thing with Quartz all the time. All you need to do is spin-off another thread. How you do that greatly depends upon your environment. Are you running on an App server or are you simply running a vanilla Java?

If the later then you simply spin-off a thread and there are numerous tutorials on that.

If you are running on an App Server like Wildfly, use the @Asynchronous tag on a Session bean. The only tricky bit is that you can't CDI into a Quartz scheduled job so you will need to use JNDI to obtain the container proxy for the session bean you desire. Something like this:

    @NoArgsConstructor
    @ApplicationScoped
    @Slf4j
    public class YourJob implements Job {


    public void execute(JobExecutionContext context) throws JobExecutionException      
{
    String message = "";
    try {
        final InitialContext ctx = new InitialContext();
        final IYourSessionBean yoruSessionBean = (IYourSessionBean) ctx.lookup("java:global/server-core/YourSessionBean!com.somecompany.interfaces.IYourSessionBean");

        final JobKey key = context.getJobDetail().getKey();      
        final JobDataMap dataMap = context.getJobDetail().getJobDataMap();      

        String taskID   = dataMap.getString(BjondQuartzService.TASKID);      
        String descr    = dataMap.getString(BjondQuartzService.DESCRIPTION);

        yourSessionBean.assignTaskAsync(taskID, descr);

        context.setResult("SUCCESS");
    } catch(Exception e) {
        log.error("Could not assign task: {}", message, e);
        context.setResult("FAILURE");
    }
}      

}

And then on the receiving end:

@Asynchronous
@TransactionAttribute(REQUIRED)
@Override
public void assignTaskAsync(@NotNull(message="taskID must not be null")
                            final String taskID,
                            @NotNull(message="descr must not be null")
                            final String descr
                            ) throws Exception {

      Do some stuff here.
}

Note the @Asychronous tag. Each container has a number of threads available to it that can and will be extracted from a pool and used for asynch invocations like this. I find this easier than dealing with Runnable's directly.

Upvotes: 2

toootooo
toootooo

Reputation: 196

I think there are several ways to deal with such kind of tasks:

  1. wrap up into a service which then periodically send batch of emails;
  2. send each email in its on thread, i.e. imply separate SMTP connection;

    @Async
    public void sendEmail(String smtpServer, String to,String from,String subject, String body) {
          send(smtpServer, to, from, subject, body);
    }
    

Upvotes: 1

Related Questions