Using Timer and Timertask
I've got a new website where I want a service to run once a day to check which orders have shipped and then email the customer the shipping details.
I've tested the email service and order details pulling, all is working fine. My question is whether or not I have properly used the Timer and TimerTask classes.
First I created the task, subclassing the TimerTask class:
OrderNotificationThread.java
publicclass OrderNotificationThreadextends TimerTask{
private String mailfrom;
public OrderNotificationThread(String mailfrom){
this.mailfrom = mailfrom;
}
publicvoid run(){
...
}
}
As you can see the task requires a parameter in it's constructor, the mailfrom address. Next I've created a Servlet that loads on startup, pulling the mailfrom from the web.xml.
TimerServlet.java
publicclass TimerServletextends HttpServlet{
publicvoid init(ServletConfig config)throws ServletException{
super.init(config);
String mailfrom = getInitParameter("mailfrom");
Timer timer =new Timer(true);
Calendar now = Calendar.getInstance();
now.setLenient(true);
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 1);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
now.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH) + 1);
timer.schedule(new OrderNotificationThread(mailfrom), now.getTime(), ((60 * 60) * 24) * 1000);
}
}
The Calendar object is setup to initialize to 12:01 AM the day after the servlet is loaded. And then should run at 12:01AM each day.
The web.xml for the TimerServlet looks like this:
web.xml
...
<servlet>
<display-name>TimerServlet</display-name>
<servlet-name>TimerServlet</servlet-name>
<servlet-class>com.mysite.servlets.TimerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>mailfrom</param-name>
<param-value>blah@blah.com</param-value>
</init-param>
</servlet>
...
So does it look like I've got something that will run properly once a day?
[3155 byte] By [
linxpdaa] at [2007-10-2 8:01:11]

The answer is no.
1) The variable timer is local to the init method and willpass out of scope once the servlet is initialized. It should be a class level variable. Better make it static which means a check to see if it has been instantaited before instantiating.
2) You used the schedule command. From the JavaDoc:
"In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate). "
You probably want to use the scheduleAtFixedRate method
"Fixed-rate execution is appropriate for recurring activities that are sensitive to absolute time, such as ringing a chime every hour on the hour, or running scheduled maintenance every day at a particular time."
Hello,
I am trying to iterate over the list object in the database, and I keep get NullPointerException stack. My code is as follows:
/*
* SearchDocumentService.java
*
* Created on December 5, 2005, 12:18 PM
*
* To change this template, choose Tools | Options and locate the template under
* the Source Creation and Management node. Right-click the template and choose
* Open. You can then make changes to the template in the Source Editor.
*/
package net.doc.dms.service;
import java.util.*;
import java.io.*;
import java.net.*;
import java.sql.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;
import net.doc.dms.DocumentBean;
/**
*
* @author WelcomeToUse
*/
public class SearchDocumentService
{
private List results;
private DataSource ds;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs;
/** Creates a new instance of SearchDocumentService */
public SearchDocumentService() throws DocumentException
{
try
{
ds = getDms();
}
catch(NamingException ne)
{
throw new DocumentException(ne.getMessage());
}
}
public Collection getDocuments() throws DocumentException
{
results = new ArrayList();
try
{
con = ds.getConnection();
String sqlString = "SELECT * FROM Documents";
pstmt = con.prepareStatement(sqlString);
rs = pstmt.executeQuery();
//DocumentBean docBean = new DocumentBean();
while(rs.next())
{
/*String name = rs.getString(3);
String title = rs.getString(4);
String type = rs.getString(5);
String category = rs.getString(6);
docBean.setName(name);
docBean.setTitle(title);
docBean.setType(type);
docBean.setCategory(category);
results.add(docBean);*/
results.add(new DocumentBean(rs.getString(3), rs.getString(4), rs.getString(5), rs.getString(6)));
}
}
catch(SQLException sqle)
{
throw new DocumentException(sqle.getMessage());
}
finally
{
try
{
if(con != null)
con.close();
}
catch(SQLException ce)
{
ce.printStackTrace();
}
try
{
if(pstmt != null)
pstmt.close();
}
catch(SQLException pe)
{
pe.printStackTrace();
}
}
return results;
}
//Search for Documents by name
public ArrayList searchByName(String name)
{
ArrayList resultList = new ArrayList();
for(Iterator i = rs.iterator(); i.hasNext();)
{
DocumentBean docBean = (DocumentBean) i.next();
if(docBean.getName().toUpperCase().indexOf(name.toUpperCase()) != -1)
{
resultList.add(docBean);
}
}
return resultList;
}
//Search for documents by title
public ArrayList searchByTitle(String title)
{
ArrayList resultList = new ArrayList();
for(Iterator j = results.iterator(); j.hasNext();)
{
DocumentBean docBean = (DocumentBean) j.next();
if(docBean.getTitle().toUpperCase().indexOf(title.toUpperCase()) != -1)
{
resultList.add(docBean);
}
}
return resultList;
}
//Search for documents by Type.
public ArrayList searchByType(String type)
{
ArrayList resultList = new ArrayList();
for(Iterator k = results.iterator(); k.hasNext();)
{
DocumentBean docBean = (DocumentBean) k.next();
if(docBean.getType().toUpperCase().indexOf(type.toUpperCase()) != -1)
{
resultList.add(docBean);
}
}
return resultList;
}
//Search for documents by category.
public ArrayList searchByCategory(String category)
{
ArrayList resultList = new ArrayList();
for(Iterator l = results.iterator(); l.hasNext();)
{
DocumentBean docBean = (DocumentBean) l.next();
if(docBean.getCategory().toUpperCase().indexOf(category.toUpperCase()) != -1)
{
resultList.add(docBean);
}
}
return resultList;
}
private void addDocument(String name, String title, String type, String category)
{
results.add(new DocumentBean(name, title, type, category));
}
private javax.sql.DataSource getDms() throws javax.naming.NamingException {
javax.naming.Context c = new javax.naming.InitialContext();
return (javax.sql.DataSource) c.lookup("java:comp/env/jdbc/dms");
}
}
Please, I need your help
> Please, I need your helpIf you are expecting help, you should:1. Post the code within code tags to make it readable. http://forum.java.sun.com/help.jspa?sec=formatting2. Post the stack trace which points to (or hints at) the line where the exception is
> I am trying to iterate over the list object in the> database, and I keep get NullPointerException stack.Also, how is your problem related to the original question?
Hi all,
In my web application, I have been asked to retrieve data from the database in the JSP page. The data are stored in the ArrayList. I have a query screen where I select begin year, end year, and quarter. Each year has 4 quarters. I am able to retrieve data for 1 year, but I am not able to retrieve data for multiple years. For example, if I choose startyear=2000 and endyear=2003, I see only the 2000 data copied 4 times in the 4 columns. Is any body who can give me an example to put ArrayList inside a Vector. The years are stored in the vector, but the data are stored in the ArrayList.
Here's my source code:
public class Quarter implements java.io.Serializable {
private int year;
private int endyear;
private int quarter;
public Quarter(int year, int endyear, int quarter){
this.year = year;
this.endyear = endyear;
this.quarter = quarter;
}
public Vector getYearsAfter(int numberOfYears){
int b_year = this.year;
int e_year = this.endyear;
Vector years = new Vector(numberOfYears);
for(int i = 0; i < numberOfYears; i++){
years.addElement(new Integer(b_year));
if(numberOfYears > 1){
b_year++;
}
}
return years;
}
}
Business Logic
public SDBean getData(Quarter quarter) throws Exception{
mylogger.debug("getData:"+quarter);
SDBean ret = null;
Connection con = null;
PreparedStatement ps1 = null;
ResultSet rs = null;
try {
con = ConnectionUtil.getConnection();
ps1 = con.prepareStatement(q1);
mylogger.debug("ar581: rptdate = "+quarter.getLastDay());
ps1.setDate(1, java.sql.Date.valueOf(quarter.getLastDay()));
ps1.setString(2, st);
rs = ps1.executeQuery();
if (rs.next()){
ret = new SDBean();
ret.setSD1(new Double(rs.getDouble(1)));
.......
........
}
Action class
String state = req.getParameter("state");
String qtr = req.getParameter("qtr");
String startyear = req.getParameter("startyear");
String endyear = req.getParameter("endyear");
int s_year = Integer.parseInt(startyear);
int e_year = Integer.parseInt(endyear);
int rpt_qtr = Integer.parseInt(qtr);
int diff_year = ((e_year) - (s_year)+1);
quarter = new Quarter(startyear, endyear, qtr);
quarters = quarter.getYearsAfter(diff_year);
mylogger.debug("years:"+quarters);
req.setAttribute("quarter", quarter);
req.setAttribute("quarters", quarters);
req.setAttribute("startyear", startyear);
req.setAttribute("endyear", endyear);
req.setAttribute("stateName", stateName);
req.setAttribute("missingdata", missingRpt);
JSP:
<logic:greaterThan collection='<%= cmValues1 %>' minimal = '0'>
<it:iterate collection="<%=quarters%>" id='startyear'>
<td align=center width=9% headers='R1 C<%=c_idx%>'><%=cmValues1.get(0)%></td>
<td align=center width=9% headers='R1 C<%=c_idx%>'><%=nocmValues1.get(0)%></td>
<% c_idx++; %>
</it:iterate>
</tr>
Please help me on this.
Thanks,
