在Servlet中生成的线程中使用EJB - 不好的做法?

时间:2012-11-28 16:44:25

标签: servlets thread-safety ejb-3.0

我们有一个servlet如下:

public class CacheRefresher extends HttpServlet {
    private static final long START_TIMEOUT = 120*1000;

    public void init(ServletConfig servletConfig) throws ServletException {
        super.init(servletConfig);
        new Thread(new Worker()).start();

    }

    private class Worker implements Runnable {
        public Worker() { }
        public void run() {   
            try {
                Thread.sleep(START_TIMEOUT);
            } catch (InterruptedException e) {
            }

            while(true) {
                MyService myService = null;
                try {
                    myService = ServiceFactory.getInstance().getMyService();
                    myService.doSomething();
                } catch (Exception ex){
                    ex.printStackTrace();
                }finally {
                    ServiceFactory.getInstance().releaseMyService(myService);
                }

                try {
                    Thread.sleep(timeout);
                } catch (InterruptedException e) {
                }
            }
        }

    }
} 

其目的是定期呼叫服务。这个Servlet只有一个实例,它将在服务器启动时创建。 MyService是一个EJB。

这有多糟糕?我知道不允许来自EJB的产生线程,但另一种方法呢?服务器关闭会发生什么?

1 个答案:

答案 0 :(得分:0)

Conceptualy我没有看到从多个线程调用ejb方法的问题(即使你自己创建了线程)。对于ejb容器来说,这将是另一个客户端。

从你的例子来看,你看起来servlet的灵魂目的是启动一堆计时器。如果你可以使用ejb 3.1,那就有java ee标准的方法来做到这一点。

首先是一个在启动时启动计时器的Singleton ejb

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;


@Singleton
@Startup
public class SingletonBean {

    @EJB
    LabBean labBean;

    @PostConstruct
    public void init() {
        long interval = 4000;
        long initialExpiration = 2000;
        labBean.startTimer(initialExpiration, interval, "MyTimer");
    }
}

然后是处理超时的SLSB:

import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;


@Stateless
public class LabBean {
    @Resource
    protected TimerService timerService;

    @Timeout
    public void timeoutHandler(Timer timer) {
        String name = timer.getInfo().toString();
        System.out.println("Timer name=" + name);
    }

    public void stopTimer(String name) {
        for (Object o : this.timerService.getTimers())
            if (((Timer) o).getInfo().toString().startsWith(name)){
                ((Timer)o).cancel();
            }       
    }

    public void startTimer(long initialExpiration, long interval, String name){
        stopTimer(name);        
        TimerConfig config = new TimerConfig();
        config.setInfo(name);
        config.setPersistent(false);
        timerService.createIntervalTimer(initialExpiration, interval, config);
    }
}