Search code examples
droolsjbpmkie

Cannot Serialize KieSession with multiple streaming rules to byte[]


I'm running into an unimplemented case when serializing my KieSession into a byte[]. I keep my rules in a database in byte[] format.

Here's the piece of code I use to create my KieSession:

KieServices kServices = KieServices.Factory.get();

KieFileSystem kFileSystem = kServices.newKieFileSystem();

for(byte[] arr : myRules) {
    String fileName = "/src/main/resources/" + generateRandomRuleName();
    kFileSystem.write(fileName , new ByteArrayResource(arr ));
}

kServices.newKieBuilder(kFileSystem).buildAll();

I have ~1K permanent facts, and upon an HTTP request to my Spring Boot application, I need to copy my KieSession bytes, deserialize it to a KieSession insert ~1K temporary events, fireAllRules and dispose. This way, I can reuse my KieSession without inserting my 1K permanent facts on every HTTP request or without removing my 1K temporary facts after every HTTP request. Here's the code I use to serialize my KieSession:

KieBaseConfiguration configuration = KieServices.Factory.get().newKieBaseConfiguration();
configuration.setOption(MultithreadEvaluationOption.YES);
configuration.setOption(EqualityBehaviorOption.EQUALITY);
configuration.setOption(EventProcessingOption.STREAM);

KieBase kBase = kServices
        .newKieContainer(kServices.getRepository().getDefaultReleaseId())
        .getKieContainer()
        .newKieBase(configuration);

final KieSession kSession = kBase.newKieSession();

// myListOfPermanentFacts is an array of serializable Java objects, but not declared with @role ( fact )
kSession.execute((Command<?>) CommandFactory.newInsertElements(myListOfPermanentFacts));

final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MarshallerFactory.newMarshaller(kBase).marshall(outputStream, kSession);
outputStream.close();
byte[] kSessionBytes = outputStream.toByteArray();

When I have a single rule with from collect as follows:

rule "Rule_1"
    dialect "java"
    no-loop true
    when
        obj : MyObj( field1: field1 )
        List( size >= 3 ) from collect ( MyObj( field1 == field1, this before obj ) )
    then
        obj.someMethod( "string1" );
end

the above described use case works as expected. However, when I have a second rule (very similar):

rule "Rule_2"
    dialect "java"
    no-loop true
    when
        obj : MyObj( field2: field2 )
        List( size >= 3 ) from collect ( MyObj( field2 == field2, this before obj ) )
    then
        obj.someMethod( "string2" );
end

I receive the following exception in method marshall:

java.lang.UnsupportedOperationException: org.drools.core.common.CompositeDefaultAgenda.getActivations -> TODO
    at org.drools.core.common.CompositeDefaultAgenda.getActivations(CompositeDefaultAgenda.java:386) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]
    at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.evaluateRuleActivations(ProtobufOutputMarshaller.java:268) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]
    at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.serializeSession(ProtobufOutputMarshaller.java:135) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]
    at org.drools.core.marshalling.impl.ProtobufOutputMarshaller.writeSession(ProtobufOutputMarshaller.java:115) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]
    at org.drools.core.marshalling.impl.ProtobufMarshaller.marshall(ProtobufMarshaller.java:120) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]
    at org.drools.core.marshalling.impl.ProtobufMarshaller.marshall(ProtobufMarshaller.java:104) ~[drools-core-7.28.0.Final.jar:7.28.0.Final]

What use case am I running into that's not yet supported? Thank you.


Solution

  • It's simply not implemented for CompositeDefaultAgenda and CompositeDefaultAgenda is used by MultithreadEvaluationOption.YES. So setting it to MultithreadEvaluationOption.NO resolves the issue.

    What's interesting is that deserialization from a byte[] into a KieSession with my permanent facts (that I do not wish to re-insert every time) is a lot slower than caching the KieBase, generating a new KieSession and inserting those permanent facts every time.