EJB 3定时器问题

发布于 2024-10-04 20:04:12 字数 1375 浏览 0 评论 0原文

我正在使用 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容器调用bean时(我使用Stripes框架),在指定时间后调用超时方法,但它只打印“超时发生”,它不会删除文件它抛出一个异常。这是控制台输出:

INFO  [STDOUT] Timeout occurred
ERROR [TimerImpl] Error invoking ejbTimeout: javax.ejb.EJBException: java.lang.NullPointerException

任何建议将不胜感激。

I am using JBoss 4.2.3 with JDK 1.5. I have created a stateless EJB whose purpose is to delete a file after a specified period of time (in milliseconds).

The EJB code is:

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();
        }
    }
}

The local interface is:

import java.io.File;

public interface TimedFileDeletionBeanLocal {

    public void setRequiredInfo(long intervalDuration, File fileToDelete);
}

When I call the bean through the web container (I use the Stripes framework) the timeout method is called after the specified time but it only prints "Timeout occurred", it does not delete the file and it throws an exception. This is the console output:

INFO  [STDOUT] Timeout occurred
ERROR [TimerImpl] Error invoking ejbTimeout: javax.ejb.EJBException: java.lang.NullPointerException

Any advice would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

_畞蕅 2024-10-11 20:04:12

在无状态会话 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();
        }
    }
}

In stateless session bean, conversational state is not maintained. Stateless bean instance variables are shared between invocations, so they may overlap.

Therefore even if you set file using setRequiredInfo(), on timeout it gets the fileToDelete null.

Try checking null before doing operation.
Below is some code snippet might help you.

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();
        }
    }
}
森林迷了鹿 2024-10-11 20:04:12

可能出现问题的一件事是您将对 File 的引用传递给 setRequiredInfo 方法。然后将该引用存储在本地,使用调试器我将验证定时器触发时的引用值是否相同。我怀疑它可能不再是引用的同一个文件,或者文件对象可能是暂时的。

另外,还有一点关于 EJBTimers 和 JBoss 的警告。此版本的 JBoss 通过计时器为每个 EJB 旋转一个线程。因此,如果您要使用这些 EJB 删除 500 个文件,JBoss 将启动 500 个线程。这种行为虽然不受欢迎,但确实符合 EJB 规范(该规范在实现上不明确)。如果容器重新启动并且计时器仍在等待触发,则将重新创建这些线程。

One thing that appears that might be a problem is that you're passing into the setRequiredInfo method a reference to a File. That reference is then stored locally, using a debugger I would verify that the reference value is the same when the timer fires. I suspect that it may no longer be the same file referenced or that the File object may be transient.

Also, just a little warning with EJBTimers and JBoss. This version of JBoss spins a thread for every EJB with a timer. So, if you have 500 files to delete with these EJBs, JBoss will spin up 500 threads. This behavior, while undesirable, does comply with the EJB spec (which is ambiguous on implementation). These threads will be recreated if the container restarts and the timers are still waiting to fire.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文