Drools KModule 持久性配置
Drools KModule persistence configuration
我正在尝试设置具有持久性的 kmodule。我在内部使用 guice,所以 spring 示例对我帮助不大。
我当前的设置如下所示:
- 我有一个管理我的会话的核心项目
- 我有多个其他项目通过 META-INF/kmodule.xml 文件贡献会话
这工作正常,但我只是以编程方式完成了这项工作(设置环境的 EntityManager 和 TransactionManager)。现在我想在 kmodule 中进行此配置,以便模块本身可以定义它们是否要持久化。
问题是,我不知道如何为此创建会话,或者如何配置模块。例如,我能找到的最简单的代码片段看起来像这样:
<kmodule
xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="kbase1">
<ksession name="ksession1"/>
</kbase>
</kmodule>
此时会话创建如下:
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession(name);
但是,如何在模块中配置持久性,或者如果不可能,如何在编程设置中传递正确的会话名称。我有的是:
// 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);
我在想,也许有一种方法可以通过 KieSessionConfiguraton 将会话名称传递给 JPAKnowledgeService class,但我似乎找不到任何方法。
或者,在 kmodule 本身中配置它会更酷。我可以使用 spring 方法,但我有点怀疑注入是否会像那样工作。据我所知,spring 中的后处理器会执行持久性注入。我不认为 guice 可以做到这一点,即使我提供它们?
谢谢
所以我调查了它并深入研究了很多 drools 代码来尝试解决这个问题。
KieContainer#newSession 所做的就是查询模型,然后使用会话配置向基础请求新会话:
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;
}
同时,这也正是 StoreService 实现所做的,使用一些高级哈利波特代码来使事情持久化。然而,它忽略了会话的配置,我几乎可以说这是一个错误..(在此之后可能会提出一个)
然而,KieContainer 创建的配置只考虑了 2 个选项:
private KieSessionConfiguration getKnowledgeSessionConfiguration(KieSessionModelImpl kSessionModel) {
KieSessionConfiguration ksConf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
ksConf.setOption( kSessionModel.getClockType() );
ksConf.setOption( kSessionModel.getBeliefSystem() );
return ksConf;
}
这意味着,我将有 2 个选项来解决这个问题:
要么编写我自己的 KieContainerImpl 来做正确的事情(为什么要麻烦...),要么模拟会话配置。我决定做第二个。
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;
}
最后一个代码片段将创建配置的会话,同时使其持久化。
或者,通过将 KieContainer 转换为 KieContainerImpl,可以访问查询 KieModule 中的 KieSession 对象所需的 public 方法。 (很多 Kie 的人)这样就可以使用相同的方法并访问 XML 配置。
我的方法是两者的结合(对 KieBase/Module 使用 xml 配置,同时以编程方式设置信念系统和时钟类型)。原因是我不想依赖内部实现,也不想费心去实现我自己的 KieContainer 并将其连接起来。
我希望这对某人有所帮助。如果其他人知道 "correct" 的方法,请 post 它。
我正在尝试设置具有持久性的 kmodule。我在内部使用 guice,所以 spring 示例对我帮助不大。
我当前的设置如下所示:
- 我有一个管理我的会话的核心项目
- 我有多个其他项目通过 META-INF/kmodule.xml 文件贡献会话
这工作正常,但我只是以编程方式完成了这项工作(设置环境的 EntityManager 和 TransactionManager)。现在我想在 kmodule 中进行此配置,以便模块本身可以定义它们是否要持久化。
问题是,我不知道如何为此创建会话,或者如何配置模块。例如,我能找到的最简单的代码片段看起来像这样:
<kmodule
xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="kbase1">
<ksession name="ksession1"/>
</kbase>
</kmodule>
此时会话创建如下:
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession(name);
但是,如何在模块中配置持久性,或者如果不可能,如何在编程设置中传递正确的会话名称。我有的是:
// 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);
我在想,也许有一种方法可以通过 KieSessionConfiguraton 将会话名称传递给 JPAKnowledgeService class,但我似乎找不到任何方法。
或者,在 kmodule 本身中配置它会更酷。我可以使用 spring 方法,但我有点怀疑注入是否会像那样工作。据我所知,spring 中的后处理器会执行持久性注入。我不认为 guice 可以做到这一点,即使我提供它们?
谢谢
所以我调查了它并深入研究了很多 drools 代码来尝试解决这个问题。
KieContainer#newSession 所做的就是查询模型,然后使用会话配置向基础请求新会话:
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;
}
同时,这也正是 StoreService 实现所做的,使用一些高级哈利波特代码来使事情持久化。然而,它忽略了会话的配置,我几乎可以说这是一个错误..(在此之后可能会提出一个)
然而,KieContainer 创建的配置只考虑了 2 个选项:
private KieSessionConfiguration getKnowledgeSessionConfiguration(KieSessionModelImpl kSessionModel) {
KieSessionConfiguration ksConf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
ksConf.setOption( kSessionModel.getClockType() );
ksConf.setOption( kSessionModel.getBeliefSystem() );
return ksConf;
}
这意味着,我将有 2 个选项来解决这个问题:
要么编写我自己的 KieContainerImpl 来做正确的事情(为什么要麻烦...),要么模拟会话配置。我决定做第二个。
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;
}
最后一个代码片段将创建配置的会话,同时使其持久化。
或者,通过将 KieContainer 转换为 KieContainerImpl,可以访问查询 KieModule 中的 KieSession 对象所需的 public 方法。 (很多 Kie 的人)这样就可以使用相同的方法并访问 XML 配置。 我的方法是两者的结合(对 KieBase/Module 使用 xml 配置,同时以编程方式设置信念系统和时钟类型)。原因是我不想依赖内部实现,也不想费心去实现我自己的 KieContainer 并将其连接起来。
我希望这对某人有所帮助。如果其他人知道 "correct" 的方法,请 post 它。