Email filtering using Aspect and Spring Profile
However, sometimes the database is populated by data from production and there is a risk of sending emails to real customers during email test execution.
This post will explain how to avoid it without explicitly write code in the send email function.
We would use 2 techniques:
- Spring Profiles – a mechanism to indicate what the running environment is (i.e. development, production,..)
- AOP – in simplified words its a mechanism to write additional logic on methods in decoupled way.
I would assume you already have Profiles set on your projects and focus on the Aspect side.
In that example the class which sends emails is EmailSender with the method send, as specified below:
public class EmailSender { //empty default constructor is a must due to AOP limitation public EmailSender() {} //Sending email function //EmailEntity - object which contains all data required for email sending (from, to, subject,..) public void send(EmailEntity emailEntity) { //logic to send email } }
Now, we will add the logic which prevent sending email to customers where code is not running on production.
For this we will use Aspects so we won’t have to write it in the send method and by that we would maintain the separation of concern principle.
Create a class that will contain the filtering method:
@Aspect @Component public class EmailFilterAspect { public EmailFilterAspect() {} }
Then create a PointCut for catching the send method execution:
@Pointcut("execution(public void com.mycompany.util.EmailSender.send(..))") public void sendEmail(){}
Since we need to control whether the method should be executed or not, we need to use the Arround annotation.
@Around("sendEmail()") public void emailFilterAdvice(ProceedingJoinPoint proceedingJoinPoint){ try { proceedingJoinPoint.proceed(); //The send email method execution } catch (Throwable e) { e.printStackTrace(); } }
As a last point, we need to access the send method input parameter (i.e. get the EmailEntity) and verify we don’t send emails to customers on development.
@Around("sendEmail()") public void emailFilterAdvice(ProceedingJoinPoint proceedingJoinPoint){ //Get current profile ProfileEnum profile = ApplicationContextProvider.getActiveProfile(); Object[] args = proceedingJoinPoint.getArgs(); //get input parameters if (profile != ProfileEnum.PRODUCTION){ //verify only internal mails are allowed for (Object object : args) { if (object instanceof EmailEntity){ String to = ((EmailEntity)object).getTo(); if (to!=null && to.endsWith("@mycompany.com")){//If not internal mail - Dont' continue the method try { proceedingJoinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); } } } } }else{ //In production don't restrict emails try { proceedingJoinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); } } }
That’s it.
Regarding configuration, you need to include the aspect jars in your project.
In Maven it’s look like this:
org.aspectj aspectjrt ${org.aspectj.version} org.aspectj aspectjweaver ${org.aspectj.version} runtime
and in your spring application configuration xml file, you need to have this:
Good luck!
Reference: Email filtering using Aspect and Spring Profile from our JCG partner Gal Levinsky at the Gal Levinsky’s blog blog.