在Drools 6.5.0和Drools 7.0.0中序列化后,时间操作符失败

时间:2017-07-10 07:37:03

标签: java serialization drools drools-fusion

我正在尝试在drools中实现序列化。我的问题是drools融合运算符之后,之前,......都没有按预期序列化。

如果我不使用序列化和反序列化,我的规则正常工作。

我附上了一个复制品。谁能告诉我问题是什么。我希望规则只能开一次。它应该在03:06:00开火一次,但它会发射3次,一次发生在3:04:00,2次发射在3:06:00。

序列化的事件:

package com.reproducer;

import java.io.Serializable;
import java.util.Date;

import org.apache.commons.lang3.builder.ToStringBuilder;

public class EventA implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 8129243856721618942L;
private int value;
private Date timestamp;

public EventA(Date timestamp, int value) {
    this.value = value;
    this.timestamp = timestamp;
}

public Date getTimestamp() {
    return timestamp;
}

public int getValue() {
    return value;
}

@Override
public String toString() {
        return new ToStringBuilder(this)
                .append("value", this.value)
                .append("timestamp", this.getTimestamp()).toString();
    }
}

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class Reproducer {
    // date formatter for simulation data and tests
    private static DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Configuration
    static class ContextConfiguration {

    }

    private KieBase kieBase;
    private static KieSession ksession;
    private static SessionPseudoClock clock;
    private KieSessionConfiguration sessionConfig;

    public byte[] serializedSession;

    @Test
    public void ruleTest() {
        List<EventA> events = getSimulationEvents();
        startKnowledgeSession(events.get(0).getTimestamp(), false);
        runSimulation(events);
    }

    private static Date parseDate(String input) {
        Date d = null;
        try {
            d = dateFormatter.parse(input);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return d;
    }

    private void runSimulation(List<EventA> events) {

        for (EventA current : events) {

            KieSession ksession2 = kieBase.newKieSession(sessionConfig, null);

            Marshaller marshaller = KieServices.Factory.get().getMarshallers().newMarshaller(kieBase);

            try {
                ByteArrayInputStream bais = new ByteArrayInputStream(serializedSession);
                ksession2 = marshaller.unmarshall(bais, sessionConfig, null);
                clock = ksession2.getSessionClock();
                bais.close();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            long currTime = clock.getCurrentTime();
            long nextTime = current.getTimestamp().getTime();

            while (currTime <= (nextTime - 1000)) {
                clock.advanceTime(1000, TimeUnit.MILLISECONDS);
                ksession2.fireAllRules();
                currTime += 1000;
            }

            long diff = nextTime - currTime;
            if (diff > 0) {
                clock.advanceTime(diff, TimeUnit.MILLISECONDS);
            }

            ksession2.insert(current);
            ksession2.fireAllRules();

            // serialize knowledge session
            try {
                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                marshaller.marshall(baos, ksession2);
                serializedSession = baos.toByteArray();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
            ksession2.halt();
            ksession2.dispose();
        }
    }

    private List<EventA> getSimulationEvents() {
        List<EventA> events = new ArrayList<EventA>();

        events.add(new EventA(parseDate("2010-01-01 02:00:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:00:00"), 1));
        events.add(new EventA(parseDate("2010-01-01 03:01:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:02:00"), 1));
        events.add(new EventA(parseDate("2010-01-01 03:03:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:04:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:05:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:06:00"), 0));
        events.add(new EventA(parseDate("2010-01-01 03:07:00"), 0));

        return events;
    }

    private void startKnowledgeSession(Date startTime, boolean onHolidays) {
        // create configuration

        StringBuffer drlR1 = new StringBuffer();
        drlR1.append("package test\n");
        drlR1.append("dialect \"mvel\"\n");
        drlR1.append("import com.reproducer.EventA\n");
        drlR1.append("import java.util.Date\n");
        drlR1.append("declare EventA\n");
        drlR1.append("  @role(event)\n");
        drlR1.append("  @timestamp(timestamp)\n");
        drlR1.append("end\n");
        drlR1.append("rule test\n");
        drlR1.append(" when\n");
        drlR1.append("      $event : EventA(getValue() == 1)\n");
        drlR1.append("    not(EventA(getValue() == 1, this after [1ms,4m] $event))\n");
        drlR1.append(" then\n");
        drlR1.append(
                "       System.out.println(\"Fired \"+ new Date(drools.getWorkingMemory().getSessionClock().getCurrentTime()));\n");
        drlR1.append("end\n");

        kieBase = new KieHelper().addContent(drlR1.toString(), ResourceType.DRL).build(EventProcessingOption.STREAM);

        sessionConfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
        sessionConfig.setOption(ClockTypeOption.get(ClockType.PSEUDO_CLOCK.getId()));
        sessionConfig.setOption(TimedRuleExecutionOption.YES);
        sessionConfig.setOption(TimerJobFactoryOption.get("trackable"));
        sessionConfig.setOption(ClockTypeOption.get("pseudo"));

        ksession = kieBase.newKieSession(sessionConfig, null);

        // set clock reference
        clock = ksession.getSessionClock();
        clock.advanceTime(startTime.getTime(), TimeUnit.MILLISECONDS);

        sessionConfig = ksession.getSessionConfiguration();
        // serialize knowledge session
        try {
            Marshaller marshaller = KieServices.Factory.get().getMarshallers().newMarshaller(kieBase);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            marshaller.marshall(baos, ksession);

            serializedSession = baos.toByteArray();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我在JBOSS Developer Jira Bug Report打开了一个针对此问题的错误报告。这是drools核心引擎中的一个错误。它将使用版本7.2.0Final修复。