Drools:使用 Query 获取无状态会话结果

Posted

技术标签:

【中文标题】Drools:使用 Query 获取无状态会话结果【英文标题】:Drools: Get stateless session results using Query 【发布时间】:2020-01-05 05:36:16 【问题描述】:

由于它来自官方Droolsdocumentation,因此可以使用Query从无状态会话中获取结果。

// Set up a list of commands
List cmds = new ArrayList();
cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) );
cmds.add( CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) );
cmds.add( CommandFactory.newQuery( "Get People" "getPeople" );

// Execute the list
ExecutionResults results =
  ksession.execute( CommandFactory.newBatchExecution( cmds ) );

// Retrieve the ArrayList
results.getValue( "list1" );
// Retrieve the inserted Person fact
results.getValue( "person" );
// Retrieve the query as a QueryResults instance.
results.getValue( "Get People" );

在下面的示例中,Get People 是一个流口水 Query,它基本上返回一个对象或对象列表,形成一个无状态 (!) 会话。

在我的项目中我需要获取一个在无状态Kie session中创建的对象,所以我创建了一个Query

query "getCustomerProfileResponse"
    $result: CustomerProfileResponse()
end

CustomerProfileResponse 对象正在RHS 中构造和创建:

insert(customerProfileResponse);

我编写了以下代码以批处理模式执行命令并查询结果CustomerProfileResponse

// Creating a batch list
List<Command<?>> commands = new ArrayList<Command<?>>(10);
commands.add(CommandFactory.newInsert(customerProfile));
commands.add(CommandFactory.newQuery(GET_CUSTOMER_PROFILE_RESPONSE, 
GET_CUSTOMER_PROFILE_RESPONSE));

// GO!
ExecutionResults results = kSession.execute(CommandFactory.newBatchExecution(commands));

FlatQueryResults queryResults = (FlatQueryResults) results.getValue(GET_CUSTOMER_PROFILE_RESPONSE); // size() is 0!

但是queryResults 返回一个空列表。

我在 Stack Overflow 上搜索类似的问题,发现无法使用批处理模式对 Drools 中的无状态会话运行查询,因为会话在调用 execute() 方法后立即关闭,解决方案是注入一个空的CustomerProfileResponse 对象以及请求中的CustomerProfile

有人能解释一下这个问题吗?

【问题讨论】:

经过一些研究后,我还发现如果在实际规则执行之前将“虚拟”或“普通”查询对象作为批处理命令插入会话中,该查询可以正确运行。实际上不确定它是否是一个好的解决方案。 【参考方案1】:

在 newInsert 之后和 NewQuery 之前添加 CommandFactory.newFireAllRules() 应该可以解决问题。见http://drools-moved.46999.n3.nabble.com/rules-users-Query-in-stateless-knowledge-session-returns-no-results-td3210735.html

在执行所有命令之前,您的规则不会触发。即隐式 fireAllRules() 是在所有命令都执行后。这意味着将在您的规则触发以插入对象之前调用查询。 您需要在执行查询之前添加 FireAllRules 命令。

【讨论】:

以上是关于Drools:使用 Query 获取无状态会话结果的主要内容,如果未能解决你的问题,请参考以下文章

每个请求的 Drools 有状态会话

Drools文档 用户手册

为啥要池化无状态会话 bean?

何时在无状态会话 bean 上使用有状态会话 bean?

无状态会话 Bean 与单例会话 Bean

如何理解“RESTful API 是无状态的”?