gpt4 book ai didi

java - ServletContextListener 在重启时丢失 JNDI 连接

转载 作者:行者123 更新时间:2023-11-28 22:58:44 28 4
gpt4 key购买 nike

我正在尝试为 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();
}

}

}

最佳答案

尝试在 MailerDaemon 类的 catch block 中添加 break 语句。

    Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}

请注意,中断状态在抛出 InterruptedException 时被清除。所以在contextInitialized中创建的线程永远不会跳出循环。

请参阅 javadoc here .

希望这对您有所帮助。

关于java - ServletContextListener 在重启时丢失 JNDI 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22668479/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com