2012-06-01 143 views
1

我想从Quartz工作内部执行一个Struts2 Action - 从任何不是处理HTTP请求的上下文中推广。如何在Quartz作业中执行Struts 2 Action。如何获得集装箱?

我从这里开始http://struts.apache.org/2.0.6/docs/how-can-we-schedule-quartz-jobs.html但文件似乎已经过时了。

我相信,(但我可能是错的)我煮下来到需要获得容器对象:

import java.util.HashMap; 
import com.opensymphony.xwork2.ActionProxy; 
import com.opensymphony.xwork2.DefaultActionProxyFactory; 

... 

HashMap ctx = new HashMap(); 
DefaultActionProxyFactory factory= new DefaultActionProxyFactory(); 
factory.setContainer(HOW DO I GET THE CONTAINER??); 
ActionProxy proxy = factory.createActionProxy("", "scheduled/myjob", ctx); 

一个解决方案是发出一个HTTP请求(通过TCP)对本地主机。我宁愿避免这种情况。

+2

你为什么要这么做? S2具体是一个网页层;可以被任意进程调用的功能应该被隔离在服务中。您需要复制什么S2功能?注射?使用Spring。拦截器? –

+0

我需要渲染一个FreeMarker模板来生成电子邮件的HTML。我可以做到这一点 - 使用一些我继承的代码,但我只能理解 - 从一个Action中,但它在其他地方不起作用。 – jsalvata

+0

最近我在Quartz上工作了很多,我没有看到你的需求和S2之间有任何关系.Quartz主要用于触发某种Job,它们独立于你使用的容器,因为它与Quartz更相关将成为你的服务层。在一个奇怪的笔记你为什么要执行你的行动? –

回答

2

我有些担心提供这个答案的内容可能会鼓励一些人去做,但是作为一个概念的证明,并且实际上为任何人提供了一个解决方案,无论出于什么原因(也许他们正在继承一些应用程序,是否需要?),需要在正常请求上下文之外执行Struts2操作。

但是,这里是原始(它是作为一个起点,而不是一个最优的实现),但工作,解决方法:

首先,这三个类添加到一个名为com.stackoverflow.struts2包。石英:

一个简单的工作,只是要求对于给定的工作方面的代理,并执行它:

package com.stackoverflow.struts2.quartz; 

import org.quartz.Job; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 

public class ActionJob implements Job { 

    @Override 
    public void execute(JobExecutionContext context) throws JobExecutionException { 

     try { 
      QuartzActionProxyFactory.getActionProxy(context).execute(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      throw new JobExecutionException(e); 
     } 

    } 

} 

一些常数绕过动作细节:

package com.stackoverflow.struts2.quartz; 

public class QuartzActionConstants { 

    public static final String NAMESPACE = "struts.action.namespace"; 
    public static final String NAME = "struts.action.name"; 
    public static final String METHOD = "struts.action.method"; 

} 

,可以静态地从ActionJob访问自定义ActionProxyFactory:

package com.stackoverflow.struts2.quartz; 

import java.util.HashMap; 
import java.util.Map; 

import org.apache.struts2.impl.StrutsActionProxyFactory; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 

import com.opensymphony.xwork2.ActionContext; 
import com.opensymphony.xwork2.ActionProxy; 
import com.opensymphony.xwork2.ActionProxyFactory; 

public class QuartzActionProxyFactory extends StrutsActionProxyFactory { 

    private static ActionProxyFactory actionProxyFactory; 

    public QuartzActionProxyFactory() { 
     actionProxyFactory = this; 
    } 

    public static ActionProxy getActionProxy(JobExecutionContext context) throws JobExecutionException { 

     ActionProxy actionProxy = null; 

     try { 
      @SuppressWarnings("unchecked") 
      Map<String, Object> actionParams = context.getJobDetail().getJobDataMap(); 
      Map<String, Object> actionContext = new HashMap<String, Object>(); 
      actionContext.put(ActionContext.PARAMETERS, actionParams); 

      actionProxy = actionProxyFactory.createActionProxy(
        (String) actionParams.get(QuartzActionConstants.NAMESPACE), 
        (String) actionParams.get(QuartzActionConstants.NAME), 
        (String) actionParams.get(QuartzActionConstants.METHOD), 
        actionContext, 
        false, //set to false to prevent execution of result, set to true if this is desired 
        false); 

     } catch (Exception e) { 
      throw new JobExecutionException(e); 
     } 

     return actionProxy; 
    } 

} 

然后,在你的struts.xml中,添加:

<bean name="quartz" type="com.opensymphony.xwork2.ActionProxyFactory" class="com.stackoverflow.struts2.quartz.QuartzActionProxyFactory"/> 
<constant name="struts.actionProxyFactory" value="quartz"/> 

然后你就可以安排动作执行一些简单的代码:

SchedulerFactory sf = new StdSchedulerFactory(); 
Scheduler scheduler = sf.getScheduler(); 
scheduler.start(); 
JobDetail jobDetail = new JobDetail("someActionJob", Scheduler.DEFAULT_GROUP, ActionJob.class); 

@SuppressWarnings("unchecked") 
Map<String, Object> jobContext = jobDetail.getJobDataMap(); 
jobContext.put(QuartzActionConstants.NAMESPACE, "/the/action/namespace"); 
jobContext.put(QuartzActionConstants.NAME, "theActionName"); 
jobContext.put(QuartzActionConstants.METHOD, "theActionMethod"); 

Trigger trigger = new SimpleTrigger("actionJobTrigger", Scheduler.DEFAULT_GROUP, new Date(), null, SimpleTrigger.REPEAT_INDEFINITELY, 1000L); 
scheduler.deleteJob("someActionJob", Scheduler.DEFAULT_GROUP); 
scheduler.scheduleJob(jobDetail, trigger); 

就是这样。这段代码将导致无限期地每秒执行一次该操作,拦截器将全部触发并且依赖关系将被注入。当然,依赖于Servlet对象(如HttpServletRequest)的任何逻辑或拦截器都无法正常运行,但是无论如何,将这些操作安排在servlet上下文之外没有任何意义。

+0

谢谢。我花了一段时间来解开这个问题,但它现在正在工作。 本质上,它归结为创建一个类(QuartzActionProxyFactory)并配置struts以将其实例化为其代理工厂。然后在创建实例后立即获取实例(请参阅QuartzActionProxyFactory的构造函数),以便可以在其他位置使用它。 在设置适当的堆栈等时会遇到一些麻烦,所以这些无需请求的会话较少的动作就可以工作。 – jsalvata

相关问题