Hybris 业务流程轮询

问题描述

我需要在我的自定义业务流程中创建一个动作,该动作必须每 10 分钟执行一次,直到返回特定动作,有没有办法在 hybris 订单业务流程中自定义某个动作的轮询间隔?我知道您可以配置超时但不能配置轮询间隔:

<wait id='waitForOrderConfirmation' then='checkOrder' prependProcessCode='true'>
<event>confirm</event>
<timeout delay='PT12H' then='asmCancelOrder'/>

解决方法

需要自定义实现来实现这一点,并且需要使用 BusinessProcessParameterModel。

以下是基于Dealy进行Retry的步骤。

创建可重复操作。

import de.hybris.platform.processengine.model.BusinessProcessModel;
import de.hybris.platform.processengine.model.BusinessProcessParameterModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.warehousing.process.BusinessProcessException;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;


public interface RepeatableAction<T extends BusinessProcessModel>
{
    int COUNTER_STARTER = 1;

    ModelService getModelService();

    Optional<Integer> extractThreshold(T process);

    String getParamName();

    default void increaseRetriesCounter(final T process)
    {
        final Collection<BusinessProcessParameterModel> contextParameters = process.getContextParameters();

        final Optional<BusinessProcessParameterModel> paramOptional = extractCounter(contextParameters);

        paramOptional.ifPresent(this::incrementParameter);

        if (!paramOptional.isPresent())
        {
            final Collection<BusinessProcessParameterModel> newContextParameters = new ArrayList<>(contextParameters);

            final BusinessProcessParameterModel counter = getModelService().create(BusinessProcessParameterModel.class);
            counter.setName(getParamName());
            counter.setValue(COUNTER_STARTER);
            counter.setProcess(process);

            newContextParameters.add(counter);

            process.setContextParameters(newContextParameters);
            getModelService().save(process);
        }
    }

    default Optional<BusinessProcessParameterModel> extractCounter(
            final Collection<BusinessProcessParameterModel> contextParameters)
    {
        //@formatter:off
        return contextParameters.stream().filter(p -> getParamName().equals(p.getName())).findFirst();
        //@formatter:on
    }

    default void incrementParameter(final BusinessProcessParameterModel parameter)
    {
        final Object value = parameter.getValue();
        if (value instanceof Integer)
        {
            parameter.setValue((Integer) value + 1);

            getModelService().save(parameter);
        }
        else
        {
            //@formatter:off
            final String message = MessageFormat.format("Wrong process parameter '{}' type. {} expected,{} actual.",getParamName(),Integer.class.getSimpleName(),value.getClass().getSimpleName());
            //@formatter:on

            throw new BusinessProcessException(message);
        }
    }

    default boolean retriesCountThresholdExceeded(final T process)
    {
        //@formatter:off
        final Optional<Integer> counterOptional = extractCounter(process.getContextParameters())
                .map(BusinessProcessParameterModel::getValue).filter(Integer.class::isInstance).map(Integer.class::cast);
        //@formatter:on

        final Optional<Integer> thresholdOptional = extractThreshold(process);

        final boolean counterSet = counterOptional.isPresent();
        final boolean thresholdSet = thresholdOptional.isPresent();

        boolean thresholdExceeded = false;

        if (counterSet && thresholdSet)
        {
            final int counter = counterOptional.get();
            final int threshold = thresholdOptional.get();
            thresholdExceeded = counter > threshold;
        }

        return counterSet && thresholdSet && thresholdExceeded;
    }
}

然后转到自定义操作并实现此接口并根据某些条件使自定义转换为重试,类似这样。

public class CustomAction extends AbstractAction<OrderProcessModel>
        implements RepeatableAction<OrderProcessModel>
        {
        
        private static final int MAX_RETRIES = 3;//make it configurable it's your choice
        @Override
    public Transition prepare(OrderModel order,OrderProcessModel process)
    {
        if (!retriesCountThresholdExceeded(process))
        {
            if (custom condition)
            {
                return Transition.OK;
            }
            getModelService().refresh(order);
            increaseRetriesCounter(process);
            return Transition.RETRY;
        }
        return Transition.NOK;
    }
        
        }
        
        @Override
    public Optional<Integer> extractThreshold(OrderProcessModel process)
    {
        return Optional.of(MAX_RETRIES);
    }

那么在 process.xml Action 条目应该是这样的。

<action id="customAction" bean="customAction">
        <transition name="OK" to="nextStep"/>
        <transition name="RETRY" to="waitForOrderConfirmation"/>
        <transition name="NOK" to="cancelOrderAction"/>
    </action>

<wait id='waitForOrderConfirmation' then='checkOrder' prependProcessCode='true'>
<event>confirm</event>
<timeout delay='PT12H' then='asmCancelOrder'/>
<wait>

注意:请按照要求设置交易,因为新的 12 小时似乎太多了