#hybris
Вопрос:
Мне нужно создать действие в своем пользовательском бизнес-процессе, которое должно выполняться каждые 10 минут до тех пор, пока не будет возвращено определенное действие. Есть ли способ настроить интервал опроса действия в бизнес-процессе hybris order? Я знаю, что вы можете настроить тайм-аут, но не интервал опроса:
<wait id='waitForOrderConfirmation' then='checkOrder' prependProcessCode='true'>
<event>confirm</event>
<timeout delay='PT12H' then='asmCancelOrder'/>
Комментарии:
1. вы могли бы завершить это действие в состоянии ожидания и создать cronjob, который запускается каждые 10 минут для проверки/перезапуска процесса на определенном шаге
Ответ №1:
Для этого нужна пользовательская реализация, и необходимо использовать модель BusinessProcessParameterModel.
Ниже приведены шаги, чтобы повторить попытку на основе Dealy.
Создайте повторяющееся действие.
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 amp;amp; thresholdSet)
{
final int counter = counterOptional.get();
final int threshold = thresholdOptional.get();
thresholdExceeded = counter > threshold;
}
return counterSet amp;amp; thresholdSet amp;amp; 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 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>
ПРИМЕЧАНИЕ: Пожалуйста, установите dealy в соответствии с требованиями, начиная с новых 12 часов, кажется, слишком много