Get the Source
The source for these projects can be found at my GitHub spring-amazon-services project.
Background
I've been using Amazon Web Services (AWS) for the last 8 months now. The offering was initially attractive with EC2, EBS and S3. However, over that time they have continued to add more and more functionality.
As a developer, one of the key notification systems we use is email. Sending email with JavaMail is fairly simple, sending it with Spring Mail is even easier. Normally I've been in environments that have SMTP servers setup so it's simply a case of configuring Spring to connect to them and away you go.
However, should you not have an SMTP server handily available, they're fairly daunting to setup.
Simple Email Service (SES) to the rescue!
Amazon SES is a great service, simple to use and extraordinarily cheap! If you're a developer of any ilk, I'd recommend setting up an Amazon account at the least and having a play with their services.
The only issue I have so far is that their sample code isn't production ready (IMO). Given Spring have simple integration, I thought I'd see if I could extend their JavaMailSenderImpl.
Include the AWS jar
I'm a maven fan (love me or hate me), and its simple enough to include the AWS jar:
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
</dependencies>
I've also included spring-context-support, which is required for the next section.Extending JavaMailSenderImpl
JavaMailSenderImpl is at the core of sending simple mail with Spring. I'll cover a very simple use-case a little further down. Let's get stuck into getting the class ready for SES though.
Firstly, we need to extend the class:
public class AmazonMailSender extends JavaMailSenderImpl { }
Second, we need to ensure that AWSJavaMailTransport is used as the Transport:
@Override
protected Transport getTransport(Session session) throws NoSuchProviderException {
return new AWSJavaMailTransport(session, null);
}
Then, we expose the AWS Access ID and the Secret Key. These are both unique to your AWS account and can be found in the security settings of your AWS account. Also, important to note that you should never publish your secret key anywhere unsafe:
private String awsAccessKeyId;
private String awsSecretKey;
public void setAwsAccessKeyId(String awsAccessKeyId) {
this.awsAccessKeyId = awsAccessKeyId;
}
public void setAwsSecretKey(String awsSecretKey) {
this.awsSecretKey = awsSecretKey;
}
Finally, we configure the java mail properties after the bean has been constructed: @PostConstruct
public void init() {
Properties props = getJavaMailProperties();
props.setProperty(MAIL_TRANSPORT_PROTOCOL_KEY, "aws");
props.setProperty(AWSJavaMailTransport.AWS_ACCESS_KEY_PROPERTY, awsAccessKeyId);
props.setProperty(AWSJavaMailTransport.AWS_SECRET_KEY_PROPERTY, awsSecretKey);
// set port to -1 to ensure that spring calls the equivalent of transport.connect().
setPort(-1);
}
Putting it all together and we have: public class AmazonMailSender extends JavaMailSenderImpl {
public static final String MAIL_TRANSPORT_PROTOCOL_KEY = "mail.transport.protocol";
private String awsAccessKeyId;
private String awsSecretKey;
public void setAwsAccessKeyId(String awsAccessKeyId) {
this.awsAccessKeyId = awsAccessKeyId;
}
public void setAwsSecretKey(String awsSecretKey) {
this.awsSecretKey = awsSecretKey;
}
@PostConstruct
public void init() {
Properties props = getJavaMailProperties();
props.setProperty(MAIL_TRANSPORT_PROTOCOL_KEY, "aws");
props.setProperty(AWSJavaMailTransport.AWS_ACCESS_KEY_PROPERTY, awsAccessKeyId);
props.setProperty(AWSJavaMailTransport.AWS_SECRET_KEY_PROPERTY, awsSecretKey);
// set port to -1 to ensure that spring calls the equivalent of transport.connect().
setPort(-1);
}
@Override
protected Transport getTransport(Session session) throws NoSuchProviderException {
return new AWSJavaMailTransport(session, null);
}
}
Spring Configuration
I generally like to configure framework beans as XML, just my preference. This bean can be configured as follows:
<bean id="mailSender"
class="au.com.dt.amazon.AmazonMailSender"
p:awsAccessKeyId="#{applicationProperties['amazon.accessKey']}"
p:awsSecretKey="#{applicationProperties['amazon.secretKey']}"/>
where applicationProperties is a reference to a Spring Properties bean. Sending Mail
A brief example of how to send mail with the mailSender we've just configured:
@Resource(name = "mailSender")
private MailSender mailSender;
public void sendMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("me@home.com");
message.setFrom("me@home.com");
message.setText("My Amazon SES email!");
message.setSubject("SES to the rescue!");
try {
mailSender.send(message);
} catch (MailException me) {
log.error("Fail to send activation mail.", me);
}
}
And there you have it, a nice simple integration of Amazon SES using Spring. Don't forget that you're able to download this source at my GitHub spring-amazon-services repository.
No comments:
Post a Comment