我正在尝试为Tomcat 7,MySQL应用程序(和Eclipse)构建一个简单的邮件程序守护程序。这是我第一次尝试使用ServletContextListener。
一切都很完美。除非,如果我更改我的邮件代码,Tomcat重新加载该类。然后它会在JNDI异常中轰炸,无法找到数据库。我不习惯按原样使用它。我不希望类重新加载来杀死服务器上的任务。
重启后和重新加载之前一切正常。所以我必须错过某些东西或以错误的顺序做事。
数据库连接在DAO中完成。所以重新启动后,DAO必须被切断?
任何帮助都会非常感激......
我得到的错误是:
Name [comp/env/jdbc/somedb] is not bound in this Context. Unable to find [comp].
javax.naming.NameNotFoundException: Name [comp/env/jdbc/somedb] is not bound in this Context. Unable to find [comp].
PooledConnection has already been closed.
at org.apache.naming.NamingContext.lookup(NamingContext.java:819)
at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:156)
at javax.naming.InitialContext.lookup(Unknown Source)
at util.DbUtil.getConnection(DbUtil.java:23)
at dao.NoticeDao.getNoticesByEvent(NoticeDao.java:49)
at dao.NoticeDao.getNoticesByStatus(NoticeDao.java:46)
at util.AppMailer.sendMailQueue(AppMailer.java:88)
at util.AppMailer.run(AppMailer.java:71)
at java.lang.Thread.run(Unknown Source)
java.sql.SQLException: PooledConnection has already been closed.
at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:86)
at com.sun.proxy.$Proxy7.prepareStatement(Unknown Source)
at dao.NoticeDao.getNoticesByEvent(NoticeDao.java:60)
at dao.NoticeDao.getNoticesByStatus(NoticeDao.java:46)
at util.AppMailer.sendMailQueue(AppMailer.java:88)
at util.AppMailer.run(AppMailer.java:71)
at java.lang.Thread.run(Unknown Source)
更新:对于第二次尝试,我简化并将守护进程与应用程序逻辑分开。应用程序逻辑现在完全独立。但我有同样的问题。
public class AppMailerRunner implements ServletContextListener {
private ServletContext context = null;
private Thread mailerThread;
public AppMailerRunner() {}
@Override
public void contextInitialized(ServletContextEvent event) {
this.context = event.getServletContext();
System.out.printf("Starting: %s\n",this.getClass());
mailerThread = new Thread(new MailerDaemon());
mailerThread.setDaemon(true);
mailerThread.start();
}
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.printf("Stopping: %s\n",this.getClass());
mailerThread.interrupt();
this.context = null;
}
class MailerDaemon implements Runnable {
@Override
public void run() {
AppMailer appMailer = new AppMailer();
while(!Thread.currentThread().isInterrupted()){
try {
appMailer.sendMailQueue();
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
...
<listener>
<listener-class>util.AppMailerRunner</listener-class>
</listener>
...
public class AppMailer{
private NoticeDao noticeDao;
private Session mailSession;
private Boolean sending;
...
public AppMailer() {
super();
noticeDao = new NoticeDao();
sending = false;
}
do stuff...
...
public class NoticeDao {
public NoticeDao() {
}
...
public List<Notice> getNotices() {
Connection conn = DbUtil.getConnection();
List<Notice> notices = new ArrayList<Notice>();
try {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM notices");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Notice notice = mapFields(rs);
notices.add(notice);
}
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} finally {
DbUtil.close(conn);
}
return notices;
}
private static Notice mapFields(ResultSet rs) throws SQLException {
Notice notice = new Notice();
notice.setId( rs.getLong("id"));
notice.setItemid( rs.getLong("itemid"));
notice.setItemtype( rs.getString("itemtype"));
notice.setTestmode( rs.getBoolean("testmode"));
notice.setName( rs.getString("name"));
notice.setStatus( rs.getString("status"));
notice.setError( rs.getString("error"));
notice.setCreated( rs.getDate("created"));
notice.setModified( rs.getDate("modified"));
notice.setLog( rs.getString("log"));
return notice;
}
...
}
...
public class DbUtil {
private static Connection conn = null;
public DbUtil() {
}
public static Connection getConnection() {
InitialContext ctx;
try {
ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/somedb");
conn = ds.getConnection();
} catch (NamingException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return conn;
}
public static void close(Connection conn){
if(conn!=null)
try {
conn.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
尝试在MailerDaemon类的catch块中添加break
语句。
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
请注意,抛出InterruptedException时会清除中断状态。所以在contextInitialized中创建的线程永远不会脱离循环。
请参阅javadoc here。
希望这有帮助。