Hi,
Fundamentally each and ever programmer facing allot of problem to development of any web application this Blog provide such common but strange problem solution which often required to developer. The scenario of Java auto Mailing system is write program how run as demon into server or local machine and send automatically mail to other user with help of Java Mailing API and Thread Model of java. Java has build in functionality for Timer Class which comes under java.util package.
Problem Statement:
1. My thread to send mail has to run at a fixed time interval thus I am using the following method from the Timer class.
scheduleAtFixedRate(TimerTask object, start time, interval)
2. My thread in the class xxx extends TimerTask class reads database and sends mail based on the data received in the run() method.
3. Whenever I send any mail, I log it into a database table that keeps the record of the emails sent.
4. i have put it some logic to filter data form data base after that it will sends me unique data. Data should be email to different uses based on the list.
5. Timer Schedule must be run at once after 15 Min. time intervals.
General Question Arise into Developer Mind:
Before resolve problem need to know the fundamental of the Timer and other things which help to build Auto mailing System.
1. What is timer in Java?
2. How timer Work into java.
3. If we want to implement this into Servlet then how i can do it?
4. How to load Timer on Servlet which start automatically.
5. How I can test Auto Mailing System into local host or LAN.
6. Windows Mail server configuration.
7. What is Java Mail API?
8. How Java Mail API work?
Timer In Java:
A facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals.
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread. This can, in turn, delay the execution of subsequent tasks, which may "bunch up" and execute in rapid succession when (and if) the offending task finally completes.
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the the timer's cancel method.
If the timer's task execution thread terminates unexpectedly, for example, because its stop method is invoked, any further attempt to schedule a task on the timer will result in an IllegalStateException, as if the timer's cancel method had been invoked.
This class is thread-safe: multiple threads can share a single Timer object without the need for external synchronization.
This class does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method.
Implementation note: This class scales to large numbers of concurrently scheduled tasks (thousands should present no problem). Internally, it uses a binary heap to represent its task queue, so the cost to schedule a task is O(log n), where n is the number of concurrently scheduled tasks.
Constructor Summary
Timer()
Creates a new timer.
Timer(boolean isDaemon)
Creates a new timer whose associated thread may be specified to run as a daemon.
Method Summary
void cancel()
Terminates this timer, discarding any currently scheduled tasks.
void schedule(TimerTask task, Date time)
Schedules the specified task for execution at the specified time.
void schedule(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-delay execution, beginning at the specified time.
void schedule(TimerTask task, long delay)
Schedules the specified task for execution after the specified delay.
void schedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-rate execution, beginning at the specified time.
void scheduleAtFixedRate(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay.
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Example
Here, a task is performed once a day at 4 a.m., starting tomorrow morning.
import java.util.Timer;
import java.util.TimerTask;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
public final class FetchMail extends TimerTask {
/**
* Construct and use a TimerTask and Timer.
*/
public static void main (String... arguments ) {
TimerTask fetchMail = new FetchMail();
//perform the task once a day at 4 a.m., starting tomorrow morning
//(other styles are possible as well)
Timer timer = new Timer();
timer.scheduleAtFixedRate(fetchMail, getTomorrowMorning4am(), fONCE_PER_DAY);
}
/**
* Implements TimerTask's abstract run method.
*/
public void run(){
//toy implementation
System.out.println("Fetching mail...");
}
// PRIVATE ////
//expressed in milliseconds
private final static long fONCE_PER_DAY = 1000*60*60*24;
private final static int fONE_DAY = 1;
private final static int fFOUR_AM = 4;
private final static int fZERO_MINUTES = 0;
private static Date getTomorrowMorning4am(){
Calendar tomorrow = new GregorianCalendar();
tomorrow.add(Calendar.DATE, fONE_DAY);
Calendar result = new GregorianCalendar(
tomorrow.get(Calendar.YEAR),
tomorrow.get(Calendar.MONTH),
tomorrow.get(Calendar.DATE),
fFOUR_AM,
fZERO_MINUTES
);
return result.getTime();
}
}
Timer On Servlet:
auto load timer into servlet need to write some line inside web.xml file.
these line are
Installing the servlet
The exact steps vary depending upon your web application server but is essentially the same for all web application servers and for all servlets
1. Place the classes in the classes directory under the app
...\webapps\
i.e.
.......\webapps\cases\WEB-INF\classes\abc.class
2. Update the web.xml to set the servlet params
The init params are actually optional as the code is defaulted to run at 1:00 am every nite). Your web.xml will be in:
...\webapps\
i.e.
C:\alphablox82\webapps\cases\WEB-INF\
Add a new
<servlet-name>TimerEmail </servlet-name>
<servlet-class>TimerEmail </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TimerEmail </servlet-name>
<url-pattern>/TimerEmail </url-pattern>
</servlet-mapping>
servlet file is:
public class TimerEmail extends HttpServlet implements SingleThreadModel{
/**
* Processes requests for both HTTPGET
andPOST
methods.
* @param request servlet request
* @param response servlet response
*/
//private final static long HOURS_24 = 1000 * 60 * 60 * 24; // in msecs
private TimerStart timer;
private static Logger logger = Logger.getLogger(SchduleTimeEmail.class);
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
}
public void init(ServletConfig config) throws ServletException {
super.init(config);
BasicConfigurator.configure();
timer = new TimerStart();
timer.getTimerStart();
}
public void destroy(){
if (timer != null) {
timer.getTimer().cancel();
timer = null;
}
super.destroy();
}
//
/**
* Handles the HTTPGET
method.
* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Handles the HTTPPOST
method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/**
* Returns a short description of the servlet.
*/
public String getServletInfo() {
return "Short description";
}
//
}
public class TimerStart {
private Timer timer = null;
private long delay=15 * 1000 * 60; // in msecs;
static Hashtable instances = new Hashtable(); // also shared
public void getTimerStart() {
// Timer Must start combination of 15,30,45,00 min for check schdule
Date dalayTimeMinSec = new Date();
int currentMin = dalayTimeMinSec.getMinutes();
int totalDelayTime = 0;
dalayTimeMinSec.setSeconds(0);
if(currentMin%15!=0 || currentMin%15 != 15){
int delayMin = currentMin % 15;
totalDelayTime = (15-delayMin) * 1000 * 60;
RunLogger.info("Total Waiting MIlisecond Second is:"+totalDelayTime);
//System.out.println("Total Waiting MIlisecond Second is:"+totalDelayTime);
}
//Start Timer from this time
timer = new Timer();
Date time = new Date();
try{
timer.scheduleAtFixedRate( new checkDBSendEmail(), totalDelayTime, delay );
RunLogger.info("TimerServlet: Timer has been set for " + time.getTime() + " '(" + delay + ")'");
}
catch( Exception e ){
RunLogger.error(e.toString());
}
}
public Timer getTimer() {
return this.timer;
}
public class checkDBSendEmail extends TimerTask {
public void run()
{
try{
synchronized(this){
RunLogger.info("Entering into DB for sending Email");
instances.put(this, this);
RunLogger.info("There are currently " + instances.size() + " instances.");
Connection conn = null;
DbServiceBean dbService = new DbServiceBean();
Class.forName (dbService.driver).newInstance ();
conn = DriverManager.getConnection (dbService.url, dbService.dbUserName, dbService.dbPassword);
// Your Db Operation Whatever you want
// Call Send Mail Function as well
res.close();
stm.close();
conn.close();
}catch(Exception ex){
System.out.println("error :"+ex.toSting());
}
}
}
}
public class SendMail {
private static final String SMTP_HOST_NAME = "localhost";
RunLogger rLogger = new RunLogger();
Date logdateTime;
public void postMail(String toEmailList, String subject, String message, String from) throws MessagingException {
try {
SmtpClient smtp = new SmtpClient(SMTP_HOST_NAME);
smtp.from(from);
smtp.to(toEmailList);
PrintStream msg = smtp.startMessage();
msg.println("From: " + from + "<" + (toEmailList) + ">");
msg.println("Subject:" + subject);
msg.println();
msg.println("Your friend wants you to read");
msg.println();
msg.println("This is remainder informmation");
msg.println();
msg.println(message);
msg.println();
smtp.closeServer();
} catch (IOException ex) {
RunLogger.error(ex.toString());
}
}
}
Window mail server:
hMail Server for Windows
hMailServer is a free e-mail server for Microsoft Windows. It's used by Internet service providers, companies, governments, schools and enthusiasts in all parts of the world.
It supports the common e-mail protocols (IMAP, SMTP and POP3) and can easily be integrated with many existing web mail systems. It has flexible score-based spam protection and can attach to your virus scanner to scan all incoming and outgoing email.
Integrating hMailServer
hMailServer comes with an easy-to-use and broad API which can be used for integration with other software in your environment. As an example, many Internet service providers connect hMailServer to their existing administration system to reduce manual work involved with managing user accounts. hMailServer also has a built-in Active Directory integration.
Java Mail API:
Introducing the JavaMail API
The JavaMail API is an optional package (standard extension) for reading, composing, and sending electronic messages. You use the package to create Mail User Agent (MUA) type programs, similar to Eudora, Pine, and Microsoft Outlook. Its main purpose is not for transporting, delivering, and forwarding messages like sendmail or other Mail Transfer Agent (MTA) type programs. In other words, users interact with MUA-type programs to read and write emails. MUAs rely on MTAs to handle the actual delivery.
The JavaMail API is designed to provide protocol-independent access for sending and receiving messages by dividing the API into two parts:
* The first part of the API is the focus of this course. Basically, how to send and receive messages independent of the provider/protocol.
* The second part speaks the protocol-specific languages, like SMTP, POP, IMAP, and NNTP. With the JavaMail API, in order to communicate with a server, you need a provider for a protocol. The creation of protocol-specific providers is not covered in this course as Sun provides a sufficient set for free.
Reviewing Related Protocols
Before looking into the JavaMail API specifics, step back and take a look at the protocols used with the API. There are basically four that you'll come to know and love:
* SMTP
* POP
* IMAP
* MIME
You will also run across NNTP and some others. Understanding the basics of all the protocols will help you understand how to use the JavaMail API. While the API is designed to be protocol agnostic, you can't overcome the limitations of the underlying protocols. If a capability isn't supported by a chosen protocol, the JavaMail API doesn't magically add the capability on top of it. (As you'll soon see, this usually is a problem when working with POP.)
SMTP
The Simple Mail Transfer Protocol (SMTP) is the mechanism for delivery of email. In the context of the JavaMail API, your JavaMail-based program will communicate with your company or Internet Service Provider's (ISP's) SMTP server. That SMTP server will relay the message on to the SMTP server of the recipient(s) to eventually be acquired by the user(s) through POP or IMAP. This does not require your SMTP server to be an open relay, as authentication is supported, but it is your responsibility to ensure the SMTP server is configured properly. There is nothing in the JavaMail API for tasks like configuring a server to relay messages or to add and remove email accounts.
POP
POP stands for Post Office Protocol. Currently in version 3, also known as POP3, RFC 1939 defines this protocol. POP is the mechanism most people on the Internet use to get their mail. It defines support for a single mailbox for each user. That is all it does, and that is also the source of most confusion. Much of what people are familiar with when using POP, like the ability to see how many new mail messages they have, are not supported by POP at all. These capabilities are built into programs like Eudora or Microsoft Outlook, which remember things like the last mail received and calculate how many are new for you. So, when using the JavaMail API, if you want this type of information, you have to calculate it yourself.
IMAP
IMAP is a more advanced protocol for receiving messages. Defined in RFC 2060, IMAP stands for Internet Message Access Protocol, and is currently in version 4, also known as IMAP4. When using IMAP, your mail server must support the protocol. You can't just change your program to use IMAP instead of POP and expect everything in IMAP to be supported. Assuming your mail server supports IMAP, your JavaMail-based program can take advantage of users having multiple folders on the server and these folders can be shared by multiple users.
Due to the more advanced capabilities, you might think IMAP would be used by everyone. It isn't. It places a much heavier burden on the mail server, requiring the server to receive the new messages, deliver them to users when requested, and maintain them in multiple folders for each user. While this does centralize backups, as users' long-term mail folders get larger and larger, everyone suffers when disk space is exhausted. With POP, saved messages get offloaded from the mail server.
MIME
MIME stands for Multipurpose Internet Mail Extensions. It is not a mail transfer protocol. Instead, it defines the content of what is transferred: the format of the messages, attachments, and so on. There are many different documents that take effect here: RFC 822, RFC 2045, RFC 2046, and RFC 2047. As a user of the JavaMail API, you usually don't need to worry about these formats. However, these formats do exist and are used by your programs.
NNTP and Others
Because of the split of the JavaMail API between provider and everything else, you can easily add support for additional protocols. Sun maintains a list of third-party providers that take advantage of protocols that Sun doesn't provide support for, out-of-the-box. There, you'll find support for NNTP (Network News Transport Protocol) [newsgroups], S/MIME (Secure Multipurpose Internet Mail Extensions), and more.
more details..