I am also facing another marshalling issue when running with the latest snapshot, I am trying to fire the same temporal rule as the initial issue above but I am serializing the session to a file as per example here -
https://github.com/tkobayas/kiegroup-examples/tree/master/Ex-marshaller-8.41/src/test/java/com/sample but the rule never fires. I am using two separate tests one to serialize and one to deserialize as I wanted to ensure that the session could survive a JVM restart.
I can see that the fact is available after deserializing and the clock is correct but the rule fails to fire.
Here is the reproducer code
POJO
```
package com.sample;
import org.kie.api.definition.type.Role;
import java.io.Serializable;
@Role(Role.Type.EVENT)
public class Event implements Serializable {
private String eventId;
private String status;
private String reason;
public Event() {
super();
// TODO Auto-generated constructor stub
}
public Event(String eventId, String status, String reason) {
super();
this.eventId = eventId;
this.status = status;
this.reason = reason;
}
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
@Override
public String toString() {
return "Event [eventId=" + eventId + ", status=" + status + ", reason=" + reason + "]";
}
}
```
Channel
```
package com.sample;
import org.kie.api.runtime.Channel;
import java.util.HashMap;
import java.util.Map;
public class EventNotificationChannel implements Channel {
private Map<String, Event> eventMap = new HashMap<>();
@Override
public void send(Object object) {
System.out.println("send : " + object);
Event event = (Event)object;
eventMap.put(event.getEventId(), event);
}
public Event getClosedEvent(String eventId) {
Event event = eventMap.get(eventId);
if (event != null && event.getStatus().equals("closed")) {
return event;
} else {
return null;
}
}
}
```
kmodule
```
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="
http://jboss.org/kie/6.0.0/kmodule">
<kbase name="testing-marshaller" default="true" eventProcessingMode="stream" equalsBehavior="equality" packages="com.sample"/>
</kmodule>
```
Rule
```
package com.sample;
import com.sample.Event;
rule "Close event without status change x "
when
$eventCreated: Event($eventId: eventId, status=="created")
not(
Event(
this != $eventCreated,
eventId==$eventId,
status != "created",
status != "closed",
this after[0s, 1m] $eventCreated
)
)
then
System.out.println("No status change in 1 secs");
insert(new Event($eventCreated.getEventId(), "closed", "auto-closed"));
end
rule "Collect closed event"
when
$eventClosed: Event(status=="closed")
then
System.out.println("Sending " + $eventClosed + " to notification channel");
channels['notification-channel'].send($eventClosed);
end
```
Tests
```
@Test
public void testSerialize() {
// load up the knowledge base
KieServices ks = KieServices.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setOption(ClockTypeOption.PSEUDO);
KieSession kieSession = kContainer.getKieBase().newKieSession(config,null);
SessionPseudoClock clock = kieSession.getSessionClock();
EventNotificationChannel notificationChannel = new EventNotificationChannel();
kieSession.registerChannel("notification-channel", notificationChannel);
String eventId = "beb0af1a-97f2-42bb-9af9-94990e38f221";
Event eventCreated = new Event();
eventCreated.setEventId(eventId);
eventCreated.setStatus("created");
kieSession.insert(eventCreated);
System.out.println("Facts inserted - " + kieSession.getFactHandles());
long ruleFireCount = kieSession.fireAllRules();
System.out.println(ruleFireCount);
assertEquals(0, ruleFireCount);
System.out.println("advancing time");
clock.advanceTime(61, TimeUnit.SECONDS);
System.out.println("Session clock -> " + kieSession.getSessionClock());
System.out.println("Session clock -> " + new Date(kieSession.getSessionClock().getCurrentTime()));
// Serialize
try (FileOutputStream out = new FileOutputStream("./ksession.out")) {
ks.getMarshallers().newMarshaller(kieSession.getKieBase()).marshall(out, kieSession);
} catch (IOException e) {
e.printStackTrace();
}
kieSession.dispose();
System.out.println("=== finished");
}
@Test
public void testDeserialize() throws InterruptedException {
// load up the knowledge base
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieBase kBase = kContainer.getKieBase();
KieSession deserializeSession = null;
String eventId = "beb0af1a-97f2-42bb-9af9-94990e38f221";
// Deserialize
try (FileInputStream in = new FileInputStream("./ksession.out")) {
KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setOption(ClockTypeOption.PSEUDO);
deserializeSession = ks.getMarshallers().newMarshaller(kBase).unmarshall(in, config, null);
System.out.println("Session clock -> " + deserializeSession.getSessionClock());
System.out.println("Session clock -> " + new Date(deserializeSession.getSessionClock().getCurrentTime()));
EventNotificationChannel notificationChannel = new EventNotificationChannel();
deserializeSession.registerChannel("notification-channel", notificationChannel);
System.out.println("Facts available - " + deserializeSession.getFactHandles());
System.out.println("firing rules again");
int ruleFireCount = deserializeSession.fireAllRules();
System.out.println(ruleFireCount);
assertEquals(2, ruleFireCount);
Event event = notificationChannel.getClosedEvent(eventId);
assertEquals("closed", event.getStatus());
assertEquals("auto-closed", event.getReason());
deserializeSession.dispose();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
```
So what the above tests are doing is that it creates a session, inserts fact, advances the clock and serializes the session. Then the deserialize test unmarsalls the session and fires the rule.
Now one thing I have tried is to move advancing the clock to the deserialized test so this would mean the session is serialize at t=0 and deserialized at t=0 and then clock is then advanced so the rule is fired at t=61 I can see the rule is fired.
After this I have tried to use the realtime clock (run the serialize test, wait 1 min and then run the deserialize test) and what I found was the rule was not fired after deserializing. Again I can see the clock advancing, facts are available but the rule is failing to fire.
Is there something I am missing here?
Thanks
Thomas