Tuesday, September 29, 2009

An API to store primitive types in Collections

Found a project on source forge which allows you to store primitive data types within collections. What this does is consume less memory. You can find the project at the following link.

http://trove4j.sourceforge.net/

Spring Mail API Wrapper

Recently it was needed at my working place to have a module to send SMTP mails. I found out that Spring provides a nice wrapper around the Java Mail API so you do not need to deal with boilerplate code. Hence after a few hours of Googling and coding I was able to come up with an API which sends mail using Spring. Following I give you the code snippets required.


package com.test.commons.mailservices.core.remoting.ejb.service;

import com.test.commons.mailservices.core.exceptions.MailSenderException;

public interface MailSenderService {

/**
* This method sends the mail to multiple recipients with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessage(String mailMsg,String[] recipientAddresses,String subject)throws MailSenderException;

/**
* This method sends the mail to a single recipient with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessage(String mailMsg,String recipientAddress,String subject)throws MailSenderException;

/**
* This method sends the mail to multiple recipients which are given as comma separated values, with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessageWithCommaSeparatedMailAddresses(String mailMsg,String recipientAddress,String subject)throws MailSenderException;
}

This is the main contract which any calling party can use to send mails. The method is overloaded so that clients can call with different functionality. Next I show you the implmentation of this interface as well as the exception class that i have defined which wraps the MailException thrown by Spring. I wrapped it so that any calling party only needs to know about the MailSending module and not about Spring exceptions.


package com.test.commons.mailservices.core.remoting.ejb.bl;

import org.apache.log4j.Logger;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;

import com.test.commons.mailservices.core.exceptions.MailSenderException;
import com.test.commons.mailservices.core.remoting.ejb.service.MailSenderService;

/**
* This is the Main class involved in sending email message to the outside world<br>
* The class uses the Spring Framework which wraps the java mail API to send mails.
* Common functionality of obtaining a SimpleMailMessage object is given by the parent<br>
* class named MailSenderCommon. The instance variables of the class are instantiated with<br>
* through a spring config. The spring config file responsible is mailconfig.spring.xml found <br>
* under the resources directory.
*
* @author dinuka
*
*/
public class MailSenderImpl extends MailSenderCommon implements MailSenderService {

private static final Logger log = Logger.getLogger(MailSenderImpl.class);

private MailSender mailSender;

private String fromAddress;

public MailSenderImpl() {

}

/**
* {@inheritDoc}
*/
public void sendMessage(String mailMsg, String[] recipientAddresses, String subject)throws MailSenderException {
if (mailMsg == null || recipientAddresses == null) {
log.error("Input parameters received for sendMessage(String,String[]) are null");
}

sendEmail(mailMsg, subject, recipientAddresses);

}

/**
* {@inheritDoc}
*/
public void sendMessage(String mailMsg, String recipientAddress, String subject)throws MailSenderException {
if (mailMsg == null || recipientAddress == null) {
log.error("Input parameters received for sendMessage(String,String) are null");
throw new IllegalArgumentException("Received Input Parameters Are Null");
}
sendEmail(mailMsg.trim(), subject, recipientAddress);
}

/**
* {@inheritDoc}
*/
public void sendMessageWithCommaSeparatedMailAddresses(String mailMsg, String recipientAddress, String subject)throws MailSenderException {

if (mailMsg == null || recipientAddress == null) {
log
.error("Input parameters received for sendMessageWithCommaSeparatedMailAddresses(String,String) are null");
throw new IllegalArgumentException("Received Input Parameters Are Null");
}
sendEmail(mailMsg, subject, recipientAddress.split(","));

}

public MailSender getMailSender() {
return mailSender;
}

public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}

public String getFromAddress() {
return fromAddress;
}

public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}

private void sendEmail(String mailMsg, String subject, String... address)throws MailSenderException {

try {
mailSender.send(getSimpleMessage(mailMsg, fromAddress, subject, address));
} catch (MailException ex) {
log.error("MailSenderImpl: sendMessage() Exception occured" + ex.getMessage());
throw new MailSenderException(ex.getMessage());
}
}

}





package com.test.commons.mailservices.core.remoting.ejb.bl;

import java.util.Date;

import org.springframework.mail.SimpleMailMessage;

public class MailSenderCommon {

/**
* This is the common method which creates a simple message object which is used to send mails out
* Note that var arg is used as the second parameter to facilitate String[] and normal String object parsing
* to the same method. Also please note that you should always keep the var arg parameter as the last parameter in
* this method as the specification requires it.
* @param mailMsg
* @param addresses
* @return
*/
protected SimpleMailMessage getSimpleMessage(final String mailMsg, final String fromAddress,String subject,final String... addresses) {
SimpleMailMessage message = new SimpleMailMessage();
message.setSentDate(new Date());
message.setTo(addresses);
message.setFrom(fromAddress);
message.setSubject(subject);
message.setText(mailMsg);


return message;
}

}




package com.test.commons.mailservices.core.exceptions;

public class MailSenderException extends Exception{

/**
*
*/
private static final long serialVersionUID = -6281925344129197510L;

private String message;





public MailSenderException(String message){
this.message = message;
}

@Override
public String getMessage() {
return message;
}
}



Then we have the SMTP Authenticator class which is used for mail authentication. It is as follows;


package com.jkcs.commons.mailservices.core.remoting.ejb.bl;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class SmtpAuthenticator extends Authenticator {
private String username;
private String password;

public SmtpAuthenticator(String username, String password) {
super();
this.username = username;
this.password = password;
}

public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}

}


And finally you the following spring xml shows how to configure and integrate all this together.



<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
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">


<!-- our Authenticator implementation -->
<bean id="smtpAuthenticator"
class="com.test.commons.mailservices.core.remoting.ejb.bl.SmtpAuthenticator">
<constructor-arg>
<value>${outgoing.mail.server.userid}</value>
</constructor-arg>
<constructor-arg>
<value>${outgoing.mail.server.password}</value>
</constructor-arg>

</bean>

<!-- now setup an authenticated session -->
<bean id="mailSession" class="javax.mail.Session"
factory-method="getInstance">
<constructor-arg>
<props>
<prop key="mail.smtp.auth">true</prop>
<!-- <prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">
javax.net.ssl.SSLSocketFactory
</prop>
<prop key="mail.smtp.socketFactory.fallback">
false
</prop> -->
</props>
</constructor-arg>
<constructor-arg ref="smtpAuthenticator" />
</bean>


<bean id="mailService" class="com.test.commons.mailservices.core.remoting.ejb.bl.MailSenderImpl">
<property name="mailSender" ref="mailSender"/>
<property name="fromAddress">
<value>${outgoing.mail.server.userid}</value>
</property>
</bean>

<!-- Mail service -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host">
<value>${outgoing.mail.server.ip}</value>
</property>
<property name="port">
<value>${outgoing.mail.server.port}</value>
</property>
<property name="username">
<value>${outgoing.mail.server.userid}</value>
</property>
<property name="password">
<value>${outgoing.mail.server.password}</value>
</property>
<property name="session" ref="mailSession" />
<property name="javaMailProperties">
<props>
<!-- Use SMTP-AUTH to authenticate to SMTP server -->
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.sendpartial">true</prop>
<!-- Use TLS to encrypt communication with SMTP server -->
<!-- <prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.sendpartial">true</prop> -->

</props>
</property>
</bean>

</beans>


As you can see i have used parameters as ${var_name}. This is because i have used Spring property file loading mechanism. Hence those variables are taken from a .property file. To configure that use the following;


<bean id="PropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!--
The order of these properties files is important, as properties
will override one another
-->
<value>xxx.properties</value>
<value>mail.properties</value>
</list>
</property>
</bean>


Thats about it. Hope this would be helpful to someone who is looking to do the same.