我正在使用JBoss 4.2.3和JDK 1.5。我创建了一个无状态EJB,其目的是在指定的时间段(以毫秒为单位)后删除文件。
EJB代码是:
import java.io.File;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import org.jboss.annotation.ejb.LocalBinding;
@Stateless
@LocalBinding(jndiBinding = "TimedFileDeletion")
public class TimedFileDeletionBean implements TimedFileDeletionBeanLocal {
@Resource
TimerService timerService;
File fileToDelete;
public void setRequiredInfo(long intervalDuration, File fileToDelete) {
timerService.createTimer(intervalDuration, "Created new timer");
this.fileToDelete = fileToDelete;
}
@Timeout
public void timeout(Timer timer) {
System.out.println("Timeout occurred");
if(fileToDelete.exists()) {
fileToDelete.delete();
}
}
}
本地界面是:
import java.io.File;
public interface TimedFileDeletionBeanLocal {
public void setRequiredInfo(long intervalDuration, File fileToDelete);
}
当我通过Web容器(我使用Stripes框架)调用bean时,在指定的时间之后调用timeout方法,但它只打印“Timeout occurred”,它不会删除文件并引发异常。这是控制台输出:
INFO [STDOUT] Timeout occurred
ERROR [TimerImpl] Error invoking ejbTimeout: javax.ejb.EJBException: java.lang.NullPointerException
任何建议都将受到赞赏。
答案 0 :(得分:0)
可能存在问题的一件事是您将setRequiredInfo方法传递给File的引用。然后使用调试器在本地存储该引用,我将在计时器触发时验证引用值是否相同。我怀疑它可能不再是引用的文件相同,或者File对象可能是瞬态的。
此外,只是对EJBTimers和JBoss的一点警告。这个版本的JBoss为每个带有计时器的EJB都会旋转一个线程。因此,如果您要使用这些EJB删除500个文件,JBoss将启动500个线程。这种行为虽然不受欢迎,但确实符合EJB规范(在实现上不明确)。如果容器重新启动并且计时器仍在等待触发,则将重新创建这些线程。
答案 1 :(得分:0)
在无状态会话bean中,不维护会话状态。无状态bean实例变量在调用之间共享,因此它们可能重叠。
因此,即使您使用setRequiredInfo()设置文件,在超时时它会将fileToDelete设为null。
在执行操作之前尝试检查null。 以下是一些代码段可能会对您有所帮助。
class FileUtility {
// Make singleton class to store list of files to delete
public static List<File> files;
//-- get/set accessing methods
}
// ---------------------
public void setRequiredInfo(long intervalDuration, File fileToDelete) {
timerService.createTimer(intervalDuration, fileToDelete.getName()+Math.random());
FileUtility.files.add(fileToDelete);
}
// ---------------------
@Timeout
public void timeout(Timer timer) {
System.out.println("Timeout occurred");
for(File fileToDelete : Fileutility.files){
if(fileToDelete.exists()) {
fileToDelete.delete();
}
}
}