Java 如何从线程外部以编程方式启动EJB计时器
我有一个EJB计时器,每天在一天中的特定时间运行两次。 我希望能够通过网页请求手动启动此计时器,但我不知道如何实现 我不想让它在Web线程中运行,因为计时器可能是一个很长的进程,所以最好让它在后台的EJB进程中运行。我可以在EJB中获得Java 如何从线程外部以编程方式启动EJB计时器,java,jakarta-ee,timer,ejb,Java,Jakarta Ee,Timer,Ejb,我有一个EJB计时器,每天在一天中的特定时间运行两次。 我希望能够通过网页请求手动启动此计时器,但我不知道如何实现 我不想让它在Web线程中运行,因为计时器可能是一个很长的进程,所以最好让它在后台的EJB进程中运行。我可以在EJB中获得TimerService,但我不能从web上下文访问它 我必须使用计时器,而不是线程。 我正在使用JBoss 7和WebSphere 8.5。我们有3个选项可以在部署应用程序时自动创建计时器 通过调用EJB方法创建计时器:Invokeinitializetime
TimerService
,但我不能从web上下文访问它
我必须使用计时器,而不是线程。
我正在使用JBoss 7和WebSphere 8.5。我们有3个选项可以在部署应用程序时自动创建计时器
initializetime
在web的ServletContextListener
的contextInitialized
方法中
模块属性
servlet,用于在web模块运行时自动启动servlet
开始
ServletContextListener
(选项1)自动安排计时器:
public class MyLifeCycleEventExample
implements ServletContextListener
{
ServletContext servletContext;
/* Methods from the ServletContextListener */
public void contextInitialized(ServletContextEvent sce)
{
servletContext = sce.getServletContext();
try
{
Context context = new InitialContext();
TimerDemoHome timerDemoHome =
(TimerDemoHome)PortableRemoteObject.narrow(
context.lookup("java:comp/env/TimerDemo"),
TimerDemoHome.class);
TimerDemo timerDemo;
// Use one of the create() methods below to
// create a new instance
timerDemo = timerDemoHome.create();
Date firstDate= new java.util.Date();
// Call any of the Remote methods below to access
// the EJB this code does not check whether the timer
// has already been scheduled.
// You should check this for duplicate timers
timerDemo.initializeTimer( firstDate, 1800000, "MyTimer" );
timerDemo.getTimerInfo();
//Cancel Timer
//timerDemo.cancelTimer("MyTimer");
}
catch(Throwable ex)
{
ex.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce)
{
}
protected void log(String msg)
{
System.out.println("[" + getClass().getName() +
"] " + msg);
}
}
但是您需要使用以下配置在web模块(web.xml)的部署描述符中注册侦听器
<listener>
<listener-class>
TimerWeb.MyLifeCycleEventExample
</listener-class>
</listener>
TimerWeb.MyLifeCycleEventExample
我们有3个选项可以在部署应用程序时自动创建计时器
initializetime
在web的ServletContextListener
的contextInitialized
方法中
模块属性
servlet,用于在web模块运行时自动启动servlet
开始
ServletContextListener
(选项1)自动安排计时器:
public class MyLifeCycleEventExample
implements ServletContextListener
{
ServletContext servletContext;
/* Methods from the ServletContextListener */
public void contextInitialized(ServletContextEvent sce)
{
servletContext = sce.getServletContext();
try
{
Context context = new InitialContext();
TimerDemoHome timerDemoHome =
(TimerDemoHome)PortableRemoteObject.narrow(
context.lookup("java:comp/env/TimerDemo"),
TimerDemoHome.class);
TimerDemo timerDemo;
// Use one of the create() methods below to
// create a new instance
timerDemo = timerDemoHome.create();
Date firstDate= new java.util.Date();
// Call any of the Remote methods below to access
// the EJB this code does not check whether the timer
// has already been scheduled.
// You should check this for duplicate timers
timerDemo.initializeTimer( firstDate, 1800000, "MyTimer" );
timerDemo.getTimerInfo();
//Cancel Timer
//timerDemo.cancelTimer("MyTimer");
}
catch(Throwable ex)
{
ex.printStackTrace();
}
}
public void contextDestroyed(ServletContextEvent sce)
{
}
protected void log(String msg)
{
System.out.println("[" + getClass().getName() +
"] " + msg);
}
}
但是您需要使用以下配置在web模块(web.xml)的部署描述符中注册侦听器
<listener>
<listener-class>
TimerWeb.MyLifeCycleEventExample
</listener-class>
</listener>
TimerWeb.MyLifeCycleEventExample
您能重构和拆分EJB吗
根据EjbTimer的常规计划调用它。EjbTimer向处理长时间运行的进程的MdbWorker发送异步消息
然后,从一个web页面可以有一个简单的servlet,它也知道如何生成消息(一些与EjbTimer共享的代码),该消息由EjbWorker获取。由于消息是异步的,web线程立即返回
有并发的长时间运行的实例可以吗?如果没有,那么您可能应该将MdbWorker设置为仅1个实例(在jboss/WAS配置中的某个地方)。您能重构并拆分EJB吗 根据EjbTimer的常规计划调用它。EjbTimer向处理长时间运行的进程的MdbWorker发送异步消息 然后,从一个web页面可以有一个简单的servlet,它也知道如何生成消息(一些与EjbTimer共享的代码),该消息由EjbWorker获取。由于消息是异步的,web线程立即返回
有并发的长时间运行的实例可以吗?如果没有,那么您可能应该将MdbWorker设置为仅1个实例(在jboss/WAS配置中的某个位置)。向EJB添加一个方法,该方法具有您现有的超时方法,该方法调用的持续时间很短(可能是10ms?): 然后从页面控制器调用这个方法
编辑:@S.Kadakov的解决方案在Java EE 6+环境中更好。在EJB中添加一个方法,该方法具有现有的超时方法,该方法调用的持续时间很短(可能是10毫秒?): 然后从页面控制器调用这个方法 编辑:@S.Kadakov的解决方案在Java EE 6+环境中更好。非常简单:
import javax.ejb.Asynchronous;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
/**
*
* @author s.kadakov
*/
@Stateless
public class TimerBean {
@Schedule(hour = "*/12", minute = "0", second = "0")
public void longTermJob() {
// do something
}
@Asynchronous
public void fireJob() {
longTermJob();
}
}
然后将TimerBean注入servlet:
@EJB
private TimerBean timerBean;
...
timerBean.fireJob()
这很容易:
import javax.ejb.Asynchronous;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
/**
*
* @author s.kadakov
*/
@Stateless
public class TimerBean {
@Schedule(hour = "*/12", minute = "0", second = "0")
public void longTermJob() {
// do something
}
@Asynchronous
public void fireJob() {
longTermJob();
}
}
然后将TimerBean注入servlet:
@EJB
private TimerBean timerBean;
...
timerBean.fireJob()