简体   繁体   中英

Drools KModule persistence configuration

I am trying to set up a kmodule with persistence. I am using guice internally so the spring example isn't very helpful to me.

My current setup looks like that:

  • I have a core project that manages my sessions
  • I have multiple other projects that contribute sessions through META-INF/kmodule.xml files

This works fine, however I have only done this programatically (setting the environment's EntityManager and TransactionManager). Now I want to have this configuration in the kmodule so the modules themselves can define if they'd like to be persisted or not.

The issue is, that I don't know how to create the session for that, or how to configure the module. For example the easiest code snippets that I could find would look something like that:

<kmodule
        xmlns="http://jboss.org/kie/6.0.0/kmodule">

    <kbase name="kbase1">
        <ksession name="ksession1"/>
    </kbase>

</kmodule>

At which point the session is created like this:

    KieServices ks = KieServices.Factory.get();
    KieContainer kContainer = ks.getKieClasspathContainer();
    KieSession kSession = kContainer.newKieSession(name);

However, how does one configure persistence in the module, or if that is not possible, how does one pass the correct session name in a programatical setup. What I have is:

        // Guice inject Entitymanager and TransactionManager and setup the Environment variable env
        KieSessionConfiguration ksconf = ks.newKieSessionConfiguration();
        ksconf.setOption(ClockTypeOption.get("realtime"));
        JPAKnowledgeService.newStatefulKnowledgeSession(kbase, ksconf, env);

I was thinking that maybe there is a way to pass the session name to the JPAKnowledgeService class through the KieSessionConfiguraton but I can't seem to find any way.

Alternatively it would be even cooler to configure that in the kmodule itself. I could use the spring approach, but I somewhat doubt that injection will work like that. As far as I know, the Postprocessor in spring would do the persistence injections. I don't think guice can do that even if I provide them?

Thanks

So I looked into it and dug into a lot of drools code to try and work this out.

All the KieContainer#newSession does is to query the model and then ask the base for a new session with the session's configuration:

public KieSession newKieSession(String kSessionName, Environment environment, KieSessionConfiguration conf) {
    KieSessionModelImpl kSessionModel = (KieSessionModelImpl) getKieSessionModel(kSessionName);
    if ( kSessionModel == null ) {
        log.error("Unknown KieSession name: " + kSessionName);
        return null;
    }
    if (kSessionModel.getType() == KieSessionModel.KieSessionType.STATELESS) {
        throw new RuntimeException("Trying to create a stateful KieSession from a stateless KieSessionModel: " + kSessionName);
    }
    KieBase kBase = getKieBase( kSessionModel.getKieBaseModel().getName() );
    if ( kBase == null ) {
        log.error("Unknown KieBase name: " + kSessionModel.getKieBaseModel().getName());
        return null;
    }

    KieSession kSession = kBase.newKieSession( conf != null ? conf : getKnowledgeSessionConfiguration(kSessionModel), environment );
    wireListnersAndWIHs(kSessionModel, kSession);
    registerLoggers(kSessionModel, kSession);
    kSessions.put(kSessionName, kSession);
    return kSession;
}

At the same time, this is exactly what the StoreService implementation does as well, with some advanced harry potter code to make things persistent. It however ignores the configuration of the session, which I would almost say is a bug.. (might raise one after this)

The configuration created by the KieContainer however only takes 2 options into account anyway:

private KieSessionConfiguration getKnowledgeSessionConfiguration(KieSessionModelImpl kSessionModel) {
    KieSessionConfiguration ksConf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
    ksConf.setOption( kSessionModel.getClockType() );
    ksConf.setOption( kSessionModel.getBeliefSystem() );
    return ksConf;
}

This means, that I would have 2 options to solve this:

either write my own KieContainerImpl that does the right thing (why bother...) or simulate the session configuration. I decided to do the second.

public KieSession createJPASession(final String kieBaseId, Optional<String> clockType, Optional<String> beliefSystem) {
    log.info(String.format("Creating JPA Session for kieBase %s, clockType %s, beliefSystem %s", kieBaseId, clockType, beliefSystem));
    KieBase kieBase = kContainer.getKieBase(kieBaseId);
    KieSessionConfiguration ksConf = ks.newKieSessionConfiguration();

    // Set this thing up manually. Looking at the impl/docs these are the only two options available to set.
    // The Storage service will remove those options from a default session for whatever reason, however we can set this manually
    // This means we can use the base configuration and have things run in a normal way

    if (clockType.isPresent()) {
        ksConf.setOption(ClockTypeOption.get(clockType.get()));
    }
    if (beliefSystem.isPresent()) {
        ksConf.setOption(BeliefSystemTypeOption.get(beliefSystem.get()));
    }

    KieSession jpaSession = ks.getStoreServices().newKieSession(kieBase, ksConf, env);
    sessions.put(jpaSession.getIdentifier(), jpaSession);
    return jpaSession;
}

This last code snippet will create the configured session while making it persistent as well.

Alternatively, by casting KieContainer to KieContainerImpl one gets access to the public method needed to query the KieSession object in the KieModule. (man that's a lot of Kie's) That way one could use the same methods and access the XML configuration. My approach is a mix of that (use xml config for KieBase/Module while programatically set the beliefesystem and the clocktype). Reason being that I do not want to depend on the internal implementation and I didn't want to bother implementing my own KieContainer and wiring it in.

I hope this helps someone out. If someone else knows the "correct" way to do that, please post it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM