2017-05-02 11 views
1

チーム、spring webflowを1.xから2.4にアップグレードしています。spring webflow 2.x - 単一スナップショットを使用するためにalwaysGenerateNewNextKeyをfalseに設定する方法

SWF 1.xでは、セッション全体に対して1つのflowExecutionKeyを使用し、バックナビゲーションも無効にしました。 SWF 2.4で

は、我々は、我々は

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry"> 
    <webflow:flow-execution-repository max-executions="1" max-execution-snapshots="0"/> 
</webflow:flow-executor> 

しかしナビゲーションに、以下のように0に最大実行-スナップショットを設定することにより、スナップショットを無効にすることができました、同じ動作を持つように

を望んでいましたスナップショットIDは、

AbstractFlowExecutionRepository

がtrueの場合、すべてのナビゲーションのための新しいsnapshotIdを生成するのに役立ちます、フィールド、下にあり、我々はこれを調査する際に、問題の原因となっている (like e1s1, e1s2 ...)が増加し続けます

alwaysGenerateNewNextKeyデフォルトではtrueです。

SWF 1.xでは、RepositoryType.SINGLEKEYでfalseに設定するオプションがありましたが、SWF 2.4ではこの値をfalseに設定する方法はありませんでした。 、​​とFlowElementAttributeのあなた自身のコピーを作成し

をそれらMyFlowExecutorFactoryBeanMyFlowElementAttributeに名前を付ける:

"alwaysGenerateNewNextKey"

答えて

0

を上書きする方法があるかどうか、今、私は、これは醜いですが、ここで何ができるか知っている助けてください(MyFlowExecutorFactoryBeanFlowElementAttributeからMyFlowElementAttributeへの変更参照)。

public class MyFlowExecutorFactoryBean implements FactoryBean<FlowExecutor>, ApplicationContextAware, BeanClassLoaderAware, InitializingBean { 

    private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause"; 

    private static final String REDIRECT_IN_SAME_STATE = "redirectInSameState"; 

    private FlowDefinitionLocator flowDefinitionLocator; 

    private Integer maxFlowExecutions; 

    private Integer maxFlowExecutionSnapshots; 

    private Set<MyFlowElementAttribute> flowExecutionAttributes; 

    private FlowExecutionListenerLoader flowExecutionListenerLoader; 

    private ConversationManager conversationManager; 

    private ConversionService conversionService; 

    private FlowExecutor flowExecutor; 

    private MvcEnvironment environment; 

    private ClassLoader classLoader; 

    /** 
    * Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a 
    * {@link FlowDefinitionRegistry}. Required. 
    * @param flowDefinitionLocator the flow definition locator (registry) 
    */ 
    public void setFlowDefinitionLocator(FlowDefinitionLocator flowDefinitionLocator) { 
     this.flowDefinitionLocator = flowDefinitionLocator; 
    } 

    /** 
    * Set the maximum number of allowed flow executions allowed per user. 
    */ 
    public void setMaxFlowExecutions(int maxFlowExecutions) { 
     this.maxFlowExecutions = maxFlowExecutions; 
    } 

    /** 
    * Set the maximum number of history snapshots allowed per flow execution. 
    */ 
    public void setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) { 
     this.maxFlowExecutionSnapshots = maxFlowExecutionSnapshots; 
    } 

    /** 
    * Sets the system attributes that apply to flow executions launched by the executor created by this factory. 
    * Execution attributes may affect flow execution behavior. 
    * @param flowExecutionAttributes the flow execution system attributes 
    */ 
    public void setFlowExecutionAttributes(Set<MyFlowElementAttribute> flowExecutionAttributes) { 
     this.flowExecutionAttributes = flowExecutionAttributes; 
    } 

    /** 
    * Sets the strategy for loading the listeners that will observe executions of a flow definition. Allows full 
    * control over what listeners should apply to executions of a flow definition launched by the executor created by 
    * this factory. 
    */ 
    public void setFlowExecutionListenerLoader(FlowExecutionListenerLoader flowExecutionListenerLoader) { 
     this.flowExecutionListenerLoader = flowExecutionListenerLoader; 
    } 

    /** 
    * Sets the service type that manages conversations and effectively controls how state is stored physically when a 
    * flow execution is paused. 
    */ 
    public void setConversationManager(ConversationManager conversationManager) { 
     this.conversationManager = conversationManager; 
    } 

    // implementing ApplicationContextAware 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     environment = MvcEnvironment.environmentFor(applicationContext); 
    } 

    // implement BeanClassLoaderAware 

    @Override 
    public void setBeanClassLoader(ClassLoader classLoader) { 
     this.classLoader = classLoader; 
    } 

    // implementing InitializingBean 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     Assert.notNull(flowDefinitionLocator, "The flow definition locator property is required"); 
     if (conversionService == null) { 
      conversionService = new DefaultConversionService(); 
     } 
     MutableAttributeMap<Object> executionAttributes = createFlowExecutionAttributes(); 
     FlowExecutionImplFactory executionFactory = createFlowExecutionFactory(executionAttributes); 
     DefaultFlowExecutionRepository executionRepository = createFlowExecutionRepository(executionFactory); 
     executionRepository.setMaxSnapshots(0); 
     executionRepository.setAlwaysGenerateNewNextKey(false); 
     executionFactory.setExecutionKeyFactory(executionRepository); 
     flowExecutor = new FlowExecutorImpl(flowDefinitionLocator, executionFactory, executionRepository); 
    } 

    // implementing FactoryBean 

    @Override 
    public Class<?> getObjectType() { 
     return FlowExecutor.class; 
    } 

    @Override 
    public boolean isSingleton() { 
     return true; 
    } 

    @Override 
    public FlowExecutor getObject() throws Exception { 
     return flowExecutor; 
    } 

    private MutableAttributeMap<Object> createFlowExecutionAttributes() { 
     LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<Object>(); 
     if (flowExecutionAttributes != null) { 
      for (MyFlowElementAttribute attribute : flowExecutionAttributes) { 
       executionAttributes.put(attribute.getName(), getConvertedValue(attribute)); 
      } 
     } 
     putDefaultFlowExecutionAttributes(executionAttributes); 
     return executionAttributes; 
    } 

    private void putDefaultFlowExecutionAttributes(LocalAttributeMap<Object> executionAttributes) { 
     if (!executionAttributes.contains(ALWAYS_REDIRECT_ON_PAUSE)) { 
      Boolean redirect = environment != MvcEnvironment.PORTLET; 
      executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, redirect); 
     } 
     if (!executionAttributes.contains(REDIRECT_IN_SAME_STATE)) { 
      Boolean redirect = environment != MvcEnvironment.PORTLET; 
      executionAttributes.put(REDIRECT_IN_SAME_STATE, redirect); 
     } 
    } 

    private DefaultFlowExecutionRepository createFlowExecutionRepository(FlowExecutionFactory executionFactory) { 
     ConversationManager conversationManager = createConversationManager(); 
     FlowExecutionSnapshotFactory snapshotFactory = createFlowExecutionSnapshotFactory(executionFactory); 
     DefaultFlowExecutionRepository rep = new DefaultFlowExecutionRepository(conversationManager, snapshotFactory); 
     if (maxFlowExecutionSnapshots != null) { 
      rep.setMaxSnapshots(maxFlowExecutionSnapshots); 
     } 
     return rep; 
    } 

    private ConversationManager createConversationManager() { 
     if (conversationManager == null) { 
      conversationManager = new SessionBindingConversationManager(); 
      if (maxFlowExecutions != null) { 
       ((SessionBindingConversationManager) conversationManager).setMaxConversations(maxFlowExecutions); 
      } 
     } 
     return this.conversationManager; 
    } 

    private FlowExecutionSnapshotFactory createFlowExecutionSnapshotFactory(FlowExecutionFactory executionFactory) { 
     if (maxFlowExecutionSnapshots != null && maxFlowExecutionSnapshots == 0) { 
      maxFlowExecutionSnapshots = 1; 
      return new SimpleFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator); 
     } else { 
      return new SerializedFlowExecutionSnapshotFactory(executionFactory, flowDefinitionLocator); 
     } 
    } 

    private FlowExecutionImplFactory createFlowExecutionFactory(AttributeMap<Object> executionAttributes) { 
     FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory(); 
     executionFactory.setExecutionAttributes(executionAttributes); 
     if (flowExecutionListenerLoader != null) { 
      executionFactory.setExecutionListenerLoader(flowExecutionListenerLoader); 
     } 
     return executionFactory; 
    } 

    // utility methods 

    private Object getConvertedValue(MyFlowElementAttribute attribute) { 
     if (attribute.needsTypeConversion()) { 
      Class<?> targetType = fromStringToClass(attribute.getType()); 
      ConversionExecutor converter = conversionService.getConversionExecutor(String.class, targetType); 
      return converter.execute(attribute.getValue()); 
     } else { 
      return attribute.getValue(); 
     } 
    } 

    private Class<?> fromStringToClass(String name) { 
     Class<?> clazz = conversionService.getClassForAlias(name); 
     if (clazz != null) { 
      return clazz; 
     } else { 
      try { 
       return ClassUtils.forName(name, classLoader); 
      } catch (ClassNotFoundException e) { 
       throw new IllegalArgumentException("Unable to load class '" + name + "'"); 
      } 
     } 
    } 

    class MyFlowElementAttribute { 

     /** 
     * The name of the attribute. 
     */ 
     private String name; 

     /** 
     * The value of the attribute before type-conversion. 
     */ 
     private String value; 

     /** 
     * The attribute type, optional, but necessary for type conversion. 
     */ 
     private String type; 

     public MyFlowElementAttribute(String name, String value, String type) { 
      Assert.hasText(name, "The name is required"); 
      Assert.hasText(value, "The value is required"); 
      this.name = name; 
      this.value = value; 
      this.type = type; 
     } 

     public String getName() { 
      return name; 
     } 

     public String getValue() { 
      return value; 
     } 

     public String getType() { 
      return type; 
     } 

     public boolean needsTypeConversion() { 
      return type != null && type.length() > 0; 
     } 
    } 
} 

は今あなたのWebflowの設定でこれを使用します:

<bean id="flowExecutor" class="com.example.MyFlowExecutorFactoryBean "> 
    <property name="flowDefinitionLocator" ref="flowRegistry" /> 
    <property name="flowExecutionListenerLoader"> 
    <bean class="org.springframework.webflow.config.FlowExecutionListenerLoaderFactoryBean"> 
     <property name="listeners"> 
     <map> 
      <entry key-ref="yourFirstListener" value="*" /> 
      <entry key-ref="yourSecondListener" value="*" /> 
     </map> 
     </property> 
    </bean> 
    </property> 
</bean> 

Iの避難所」ここsetAlwaysGenerateNewNextKey(true)

は結果であるようにMyFlowExecutorFactoryBean

は、あなたがexecutionRepository上で必要なプロパティを設定します完全にテストしましたが、うまくいくはずです

+0

ありがとう、本当に役に立ちました。 – Vijay

0

おかげで、

<bean id="flowExecutionRepository" class="com.custom.module.SingleFlowExecutionRepository"> 
    <constructor-arg index="0" ref="conversationManager"/> 
    <constructor-arg index="1" ref="snapshotFactory"/> 
</bean> 

<bean id="flowExecutor" class="org.springframework.webflow.executor.FlowExecutorImpl"> 
    <constructor-arg index="0" ref="flowRegistry"/> 
    <constructor-arg index="1" ref="executionFactory" name="executionFactory"/> 
    <constructor-arg index="2" ref="flowExecutionRepository" name="executionRepository"/> 
</bean> 

そして

、可能性とそれが誰かを役に立てば幸いパブリッククラスSingleFlowExecutionRepositoryがDefaultFlowExecutionRepository {

を拡張する場合、私はまたDefaultFlowExecutionRepositoryを拡張して、それを修正しました

、この場合には確認してください

public SingleFlowExecutionRepository(ConversationManager conversationManager, 
     FlowExecutionSnapshotFactory snapshotFactory) { 
    super(conversationManager, snapshotFactory);   
    /** 
    * Set to maintain single snapshot for a session. 
    */ 
    super.setAlwaysGenerateNewNextKey(false); 
} 
関連する問題