Criss!
Photo credit: Criss!
del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | 3 | Next »
Software Development

AOP 101: Speeding Up Spring's JavaMailSenderImpl with AOP

Use AOP to eliminate the noticeable delay when sending e-mail via JavaMailSenderImpl.send().

In this short article we're going to learn how we can speed up Spring's JavaMailSenderImpl with some thread-forking AOP. Though we're using JavaMail as an example, this tutorial should be useful to people looking for a code-based introduction to Spring's support for AOP. Note at the outset that I don't really go into AOP concepts and terminology, but I do show some simple code that you should be able to follow if you already know the basic concepts and just want to see what the code looks like.

There are lots of situations in which we want our application to send out an automated e-mail. You might for instance want to send a confirmation e-mail in response to new user registrations or mailing list subscriptions and unsubscriptions. In Spring this probably means that you would use one of the various JavaMailSenderImpl.send() methods. Listing 1 shows a sample applicationContext.xml file.

Listing 1. applicationContext.xml, showing how to set up JavaMail
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-2.5.xsd>
    
    <jee:jndi-lookup id="mailSession" jndi-name="mail/Session" resource-ref="true"/>
    
    <bean id="mailSender"
        class="org.springframework.mail.javamail.JavaMailSenderImpl"
        p:session-ref="mailSession"/>
    
    <bean id="mailingListService"
        class="app.service.MailingListServiceImpl"
        p:mailSender-ref="mailSender"/>
        
    ...
    
</beans>

And listing 2 shows how it looks from the Java side:

Listing 2. A service bean
package app.service;

... imports ...

public class MailingListServiceImpl implements MailingListService {
	private JavaMailSender mailSender;
	
	public void setMailSender(JavaMailSender mailSender) {
		this.mailSender = mailSender;
	}
	
	private void sendConfirmSubscriptionEmail(Subscriber subscriber) {
		MimeMessage message = mailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message);
		
		String text = ...
		
		try {
			helper.setSubject("Please confirm your subscription");
			helper.setTo(subscriber.getEmail());
			helper.setFrom(noReplyEmailAddress);
			helper.setSentDate(subscriber.getDateCreated());
			helper.setText(text, true);
		} catch (MessagingException e) {
			throw new RuntimeException(e);
		}
		
		mailSender.send(message);
	}
	
	...
}

(For more information on Spring/JavaMail integration, please see my article Send E-mail Using Spring and JavaMail.)

This works fine, but one thing your end users might notice is a fairly significant delay while JavaMailSenderImpl.send() does whatever it's doing to send your e-mail (presumably negotiating with the SMTP server and sending the actual e-mail). While the delay probably isn't large enough to provoke rioting in the streets, it's certainly noticeable, and in many use cases it's unnecessary. E-mail is itself an asynchronous communications medium, so unless there's an important reason to let the end user know about errors that may occur while trying to send the e-mail (and there may be), one option you might consider is making the send() call on a separate thread.

Now let's look at a few different ways to do that.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | 3 | Next »

Comments (13)

Hi Willie.

Nice article: a good illustration of AOP in action.

Unfortunately, the expected Listing 3 does not contain the expected AspectJForkAdvice source code!
By Guillaume Grussenmeyer on Nov 23, 2008 at 6:49 AM PST
Oh, ha ha ha... ugh. I'll fix that one after I'm off kid duty. :-D Thanks for the catch.
By Willie Wheeler on Nov 23, 2008 at 9:18 AM PST
OK, fixed. Thanks again Guillaume.
By Willie Wheeler on Nov 23, 2008 at 12:14 PM PST

Hi Willie.

I really like your page. Hope to find more and more articles here.

This example is nice but have one disadvantage - we will have as much threads as requests in specified time t, where t is time needed to send mail. In peak hours this can be troublesome. It would be better to have thread pool but can we do this here?

By Daniel on Jan 6, 2009 at 1:49 PM PST

Hi Daniel. Thanks for the kind words about the article. As to the disadvantage you mention—funny you mention it. We're actually putting a version of this article in the upcoming book and I had the same thought you mention. What I'm planning to do with the recipe is replace the Thread/Runnable part with Executor/Callable. Then we can do Executors.newCachedThreadPool() instead of creating threads directly. So yep, I think we're on the same page.

As to additional articles, I'll definitely be adding more. I need to get a couple of chapters written for the book but I have an article in the pipeline.

By Willie Wheeler on Jan 6, 2009 at 7:04 PM PST

Hi Willie,

Thx for reply:) Good idea! Can we see this solution also here?

By Daniel on Feb 25, 2009 at 3:22 AM PST

Hi Daniel, welcome back. That's a great idea for a quick article. I'll try to post something on that this weekend. Thanks for the suggestion!

By Willie Wheeler on Feb 25, 2009 at 7:03 AM PST

Great article! It worked perfectly using the annotation-config!!!

By Daniel Camargo on Mar 5, 2009 at 5:21 AM PST

Willie, thanks for an excellent AOP example! I've been working with Spring framework for a few months now, but I'm still quite new to AOP, and learning by working examples seems to work the best for me.

Now to my question: as you already described in your article, when sending out email, sometimes you need to do it synchronously (with feedback) and sometimes asynchronously and with the manual ways (i.e. creating a wrapper to fork new threads) it's easy to have the control.

What is the best way to do this with AOP? I'm already using my own MailSender wrapper to provide utility methods to send email and not have to deal with SimpleMailMessage etc. - one of my methods looks like this: sendMail(String to, String subject, String body). The easiest way to have 2 ways of sending (synchronous and asynchronous) would probably be to create an additional method - for example sendMailFork(String to, String subject, String body) - this would only pass the call to sendMail() - and configure the forkAdvice only for the sendMailFork methods. This way, the caller would use the sendMail methods to send email synchronously, and sendMailForked to send mail asynchronously.

But I was wondering - isn't there a better and more elegant way to achieve the same goal with AOP? Thanks for any advice in advance! :)

By Rado on Aug 6, 2009 at 12:56 AM PDT

Nice Article. good way to do modular programming, the module being the aop advice.

By G Sunderam on Oct 4, 2009 at 6:02 PM PDT

Thanks for the nice article.But my concern is whether this can be used in production environment. My problem is that the server can ran out of maximum Thread limit . Is there anyway to use Thread Pooling along with this ?

Thanks

By umanga on Oct 22, 2009 at 2:07 AM PDT

he myth of pandora is ancient, appears in several distinct Greek versions, pandora armbandand has been interpreted in many ways. In all literary versions, Neu Eingetroffen however, Pandora Armbänder the myth is a rosetta stone kind of theodicy, addressing the question pop information, web easy get, sports fashion, news-fashionof why there is evil in the world. In the seventh hot-winter century BC, Hesiod, both in his Theogony (briefly, without naming Pandora outright rosetta stone language, rosetta stone spanish, abercrombie and fitch, Abercrombie Fitch

By pandora schmuck on Aug 30, 2010 at 11:02 PM PDT

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring Annotations RefCard
Check out the new DZone Spring Annotations Refcard by Craig Walls!

What's New?

2009-08-30 - Check out my two-part series on DZone: Spring Integration: A Hands-On Tutorial.
2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.