del.icio.us Digg DZone Reddit StumbleUpon
AOP 101: Speeding Up Spring's JavaMailSenderImpl with AOP - Willie Wheeler
« Previous | 1 | 2 | 3 | Next »

Method 1: Spawn a new thread manually

One possibility would be to spawn a new thread manually whenever you want to call JavaMailSenderImpl.send(). In other words, you implement the Runnable interface with a call to send(), you pass it into a Thread, and then you start the thread.

This technique has some advantages. It's conceptually straightforward. Also it's easy to be selective about the cases in which you do and don't want to fork. Again, there may well be times where you want the end user to know if the send() call generated an exception, and if that's true, then you simply refrain from forking the thread.

If you're not careful, the approach can lead to widespread violation of the DRY principle. You might end up rewriting the same thread-forking code every time you send an e-mail. You can of course control this by creating one or more utility methods to send an e-mail on a separate thread, and that is a good approach.

One drawback with this approach, though, is that it may be either inconvenient or else a non-option. If you have an existing app with lots of calls to create e-mail, then you'd need to update all the instances of that code with the new code. In most cases that's probably doable though it may be inconvenient. But it may be that you're not in a position to change the client code. (Maybe it's a third-party library, for instance.) The client code calls an injected JavaMailSender instance, say, and that's the way it is. In that event you'll want to consider one of the two following alternative methods.

Method 2: Create a JavaMailSender wrapper

Another method would be to implement a JavaMailSender wrapper. (JavaMailSender is of course the interface to which JavaMailSenderImpl conforms.) The JavaMailSender interface has six different send() methods (here are the Javadocs), and so you can just implement the thread-forking code for each of the six methods. (Probably each method would create a Runnable and then pass that to a thread-forking utility method.) Then you inject your wrapper into your service beans instead of injecting the JavaMailSenderImpl bean directly.

This approach is pretty good. It's still straightforward, and it allows you to avoid violating DRY. Also, because it's entirely transparent to client code, it can deal with cases in which you either can't or else don't want to modify said client code.

One possible challenge is that you may find it a little tough to exercise fine-grained control over the cases in which you use the wrapper and the cases in which you don't. If it's important for your code to exercise that kind of control, then arguably it would be reasonable to associate the forking/non-forking semantics injected JavaMailSender beans. You might for example inject two JavaMailSender instances into the service bean—one forking and one non-forking.

A minor grumble about the wrapper method is that it ties the thread-forking behavior to specific interfaces, such as JavaMailSender. That's not too big a deal in this particular case, since it's not such a problem to spawn a new thread. But if you have other cases where you decide you want to create a new thread, you might decide that you'd like to factor thread-forking out as a separate behavior and be able to apply that in multiple contexts.

So let's see how to do that using Spring's support for AspectJ-flavored AOP.

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

Comments (11)

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

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 in Practice
My brother and I are writing Spring in Practice for Manning!

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.