2012-06-01 54 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

相關問題