struts 2とjbpm 4の単純統合

9931 ワード

あるプロジェクトの表示層としてstruts 2を使用することを指定した会社のリーダーが技術を実現する時、このプロジェクトはjbpmを使用しました.
jbpmを使用すると、通常は未知数のサービスフォームページが表示されます.
一般的には、struts 2を使用する場合(本人が使用する場合)は、ページ制御はstrutsの設定ファイルに既に書いてあり、つまり表示するページは基本的に既知です(未知ページは、明らかに設定できません)ので、通常は、新規サービスがある場合や、業務フローが変化した場合(タスクノードの新規作成と削除など)、業務フォームページの新規作成と削除につながるので、このようなxml構成では、明らかに需要を満たすことができません.
私達はspringmvcを使う時、viewnameはプログラムの中で指定することができて、このように業務のフォームもプログラムの中で指定することができて、xmlの配置の効き目がない活性を免れることができます.明らかにstruts 2もこのような方式を提供したはずです.
次の2つのクラスを拡張すればいいです.
1、StrutsアクションProxyFactory;
2、DefaultアクションInvocation;
私たちはDefault Action Invocations.reateResult方法をカバーする必要があります.
この方法のデフォルトの実装は、reultmappingsからresultcode(action関連方法の戻り値)によってビューを取得するため、トラヒックフォームがstruts 2のプロファイルに配置されている場合には、異常が発生するはずです.したがって、私たちはこの方法をカバーして、そのビューを探しています.一般的に、reultcodeは、ビジネスフォームページの相対パスとすることができる.
私たち自身のアクションインストラクターを使用するためには、Struts Actory.createActoryメソッドをカバーする必要があります.この方法は既に指定されているので、Struts Actoryに戻ります.
具体的な実現は以下の通りです.
public class IcomStrutsActionInvocation extends DefaultActionInvocation {

	public static final String JBPM_PREFIX = "icom:";

	public IcomStrutsActionInvocation(Map<String, Object> extraContext, boolean pushAction) {
		super(extraContext, pushAction);
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public Result createResult() throws Exception {

		if (resultCode != null && resultCode.startsWith(JBPM_PREFIX)) {//         (       icom:   )
			Map<String, String> resultParams = new HashMap<String, String>();
			resultParams.put("location", resultCode.replace(JBPM_PREFIX, ""));
			ResultConfig resultConfig = new ResultConfig.Builder(resultCode,
					ServletDispatcherResult.class.getName()).addParams(resultParams)
					.build();

			return objectFactory.buildResult(resultConfig, invocationContext
					.getContextMap());
		} else {
			return super.createResult();
		}

	}

}
public class IcomStrtuts2ActionFactory extends StrutsActionProxyFactory {

	public ActionProxy createActionProxy(String namespace, String actionName,
			String methodName, Map<String, Object> extraContext,
			boolean executeResult, boolean cleanupContext) {
		
		ActionInvocation inv = new IcomStrutsActionInvocation(extraContext, true);
        container.inject(inv);
        
        return super.createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
	}
	
	
}
struts-default.xmlファイルは私達自身の実現クラスを配置していないので、strutsの設定ファイルに私達自身の関連する実現類を追加する必要があります.構成は以下の通りです.
<struts>
	<bean class="com.icom.tech.struts2.IcomStrtuts2ActionFactory"
		name="default" type="com.opensymphony.xwork2.ActionProxyFactory" />
...
    </struts>
struts-actionがresultcodeに戻る例:
public String forTask() throws Exception {

		TaskService taskService = processEngine.getTaskService();
		task = taskService.getTask(taskId);
		if (null == task)
			throw new NullPointerException("id :" + taskId + "         ...");
		taskService.getVariableNames(taskId);
		Map<String, Object> variables = taskService.getVariables(taskId,
				taskService.getVariableNames(taskId));
		if (!(null == variables || variables.isEmpty())) {
			ValueStack stack = ActionContext.getContext().getValueStack();
			Iterator<String> it = variables.keySet().iterator();
			while (it.hasNext()) {
				String key = it.next();
				logger.info("       :" + key + "   :" + variables.get(key));
				Object value = variables.get(key);
				stack.set(key, value);
			}
		}
		if(flag){
			//           
			 return IcomStrutsActionInvocation.JBPM_PREFIX+retriveFormResource();
		}
		

		return IcomStrutsActionInvocation.JBPM_PREFIX
				+ task.getFormResourceName();
	}
	
	

	private String retriveFormResource() throws Exception {

		String formResourceName = task.getFormResourceName();

		String excutionId = task.getExecutionId();

		Execution e = processEngine.getExecutionService().findExecutionById(
				excutionId);

		ProcessDefinition pd = processEngine.getRepositoryService()
				.createProcessDefinitionQuery().processDefinitionId(
						e.getProcessDefinitionId()).uniqueResult();

		DeploymentImpl deployment = (DeploymentImpl) processEngine
				.getRepositoryService().createDeploymentQuery().deploymentId(
						pd.getDeploymentId()).uniqueResult();

		
		String path = deployment.getId() + "/" + pd.getId() + "/"
				+ formResourceName;
		File formFile = new File(formBaseDir, path);
		
		//           ,          
		if (!formFile.exists())
			
			synchronized (processEngine) {
				if(!formFile.getParentFile().exists()){
					formFile.getParentFile().mkdirs();
				}

				byte[] buf = deployment.getBytes(formResourceName);

				//          
				FileOutputStream fos = new FileOutputStream(formFile);
				fos.write(buf);
				fos.close();
			}

		return DEFAULT_FORM_BASE_DIR + path;
	}
以下はjpdlが作成したプロセス定義ファイルのセグメントです.
<task assignee="${user}" name="    " form="printSupplyMaterial.jsp">
		<on event="start">
			<event-listener factory="businessInstanceListener" method="getInstance" />
		</on>
		<on event="timeout">
			<timer duedate="${tc_supplyMaterial_timeout}" />
			<event-listener class="com.icom.cpb.workflow.listener.ChangeColorListener" auto-wire="true" >
				<property name="fontColor">
					<string value="${tc_supplyMaterial_timeout_color}"/>
				</property>
				<property name="businessInstanceService">
					<ref object="businessInstanceService"/>
				</property>
			</event-listener>
		</on>
		<transition name="   " to="   " >
			<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
				<property name="userInfoService">
					<ref object="userInfoService" />
				</property>
				<property name="docNumberService">
					<ref object="docNumberService" />
				</property>
				<property name="docnumberName">
					<string value="    " />
				</property>
				<property name="variableName">
					<string value="recode" />
				</property>
			</event-listener>
			<event-listener class="com.icom.cpb.workflow.listener.ResetCreateTimeListener">
		 		<property name="businessInstanceService">
		 			<ref object="businessInstanceService"/>
		 		</property>
		 	</event-listener>
		</transition>
		<!-- 
		<transition name="   " to="  " >
			<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
				<property name="userInfoService">
					<ref object="userInfoService" />
				</property>
				<property name="docNumberService">
					<ref object="docNumberService" />
				</property>
				<property name="docnumberName">
					<string value="  " />
				</property>
				<property name="variableName">
					<string value="accode" />
				</property>
			</event-listener>
		</transition>
		 -->
		 <transition name="   " to="  " >
	 		<event-listener class="com.icom.cpb.workflow.listener.ClearMaterialsListener" >
	 			<property name="businessInstanceService">
		 			<ref object="businessInstanceService"/>
		 		</property>
		 		<property name="receivedDocInfoService">
		 			<ref object="receivedDocInfoService"/>
		 		</property>
	 		</event-listener>
		 	<event-listener class="com.icom.cpb.workflow.listener.ResetCreateTimeListener">
		 		<property name="businessInstanceService">
		 			<ref object="businessInstanceService"/>
		 		</property>
		 	</event-listener>
		 	<event-listener class="com.icom.cpb.workflow.listener.IncreaseDocNumberListner" >
				<property name="userInfoService">
					<ref object="userInfoService" />
				</property>
				<property name="docNumberService">
					<ref object="docNumberService" />
				</property>
				<property name="docnumberName">
					<string value="  " />
				</property>
				<property name="variableName">
					<string value="accode" />
				</property>
			</event-listener>
		 </transition>
	</task>