Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KIE-1492] Allow KieRuntimeBuilder to also create and provide StatelessKieSession #6103

Merged
merged 1 commit into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ public String getDefaultKieSessionName() {
return defaultKieSessionName;
}

public String getDefaultKieStatelessSessionName() {
return defaultKieStatelessSessionName;
}

public Map<String, BlockStmt> getkSessionConfs() {
return kSessionConfs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,31 +90,33 @@ private void writeInitKieBasesMethod(ClassOrInterfaceDeclaration clazz) {
}

private void writeGetDefaultKieBaseMethod(ClassOrInterfaceDeclaration clazz) {
MethodDeclaration getDefaultKieBaseMethod = clazz.findAll(MethodDeclaration.class).stream()
.filter(m -> m.getNameAsString().equals("getKieBase"))
.filter(m -> m.getParameters().isEmpty())
.findFirst()
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find getKieBase method"));

if (modelMethod.getDefaultKieBaseName() != null) {
getDefaultKieBaseMethod.findFirst(StringLiteralExpr.class)
findDefaultKieMethod(clazz, "getKieBase").findFirst(StringLiteralExpr.class)
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find string inside getKieBase method"))
.setString(modelMethod.getDefaultKieBaseName());
}
}

private void writeNewDefaultKieSessionMethod(ClassOrInterfaceDeclaration clazz) {
MethodDeclaration newDefaultKieSessionMethod = clazz.findAll(MethodDeclaration.class).stream()
.filter(m -> m.getNameAsString().equals("newKieSession"))
.filter(m -> m.getParameters().isEmpty())
.findFirst()
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find newKieSession method"));

if (modelMethod.getDefaultKieSessionName() != null) {
newDefaultKieSessionMethod.findFirst(StringLiteralExpr.class)
findDefaultKieMethod(clazz, "newKieSession").findFirst(StringLiteralExpr.class)
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find string inside newKieSession method"))
.setString(modelMethod.getDefaultKieSessionName());
}

if (modelMethod.getDefaultKieStatelessSessionName() != null) {
findDefaultKieMethod(clazz, "newStatelessKieSession").findFirst(StringLiteralExpr.class)
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find string inside newStatelessKieSession method"))
.setString(modelMethod.getDefaultKieStatelessSessionName());
}
}

private MethodDeclaration findDefaultKieMethod(ClassOrInterfaceDeclaration clazz, String methodName) {
return clazz.findAll(MethodDeclaration.class).stream()
.filter(m -> m.getNameAsString().equals(methodName))
.filter(m -> m.getParameters().isEmpty())
.findFirst()
.orElseThrow(() -> new InvalidTemplateException(generator, "Cannot find " + methodName + " method"));
}

private void writeGetKieBaseForSessionMethod(ClassOrInterfaceDeclaration clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieRuntimeBuilder;
import org.kie.api.runtime.StatelessKieSession;
import org.drools.modelcompiler.KieBaseBuilder;

public class ProjectRuntime implements KieRuntimeBuilder {
Expand Down Expand Up @@ -62,8 +63,21 @@ public KieSession newKieSession(String sessionName) {
if (kbase == null) {
throw new RuntimeException("Unknown KieSession with name '" + sessionName + "'");
}
KieSession ksession = kbase.newKieSession(getConfForSession(sessionName), null);
return ksession;
return kbase.newKieSession(getConfForSession(sessionName), null);
}

@Override
public StatelessKieSession newStatelessKieSession() {
return newStatelessKieSession("$defaultStatelessKieSession$");
}

@Override
public StatelessKieSession newStatelessKieSession(String sessionName) {
KieBase kbase = getKieBaseForSession(sessionName);
if (kbase == null) {
throw new RuntimeException("Unknown StatelessKieSession with name '" + sessionName + "'");
}
return kbase.newStatelessKieSession(getConfForSession(sessionName));
}

private KieBase getKieBaseForSession(String sessionName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieRuntimeBuilder;
import org.kie.api.runtime.StatelessKieSession;
import org.drools.modelcompiler.KieBaseBuilder;

@jakarta.enterprise.context.ApplicationScoped
Expand Down Expand Up @@ -63,8 +64,21 @@ public KieSession newKieSession(String sessionName) {
if (kbase == null) {
throw new RuntimeException("Unknown KieSession with name '" + sessionName + "'");
}
KieSession ksession = kbase.newKieSession(getConfForSession(sessionName), null);
return ksession;
return kbase.newKieSession(getConfForSession(sessionName), null);
}

@Override
public StatelessKieSession newStatelessKieSession() {
return newStatelessKieSession("$defaultStatelessKieSession$");
}

@Override
public StatelessKieSession newStatelessKieSession(String sessionName) {
KieBase kbase = getKieBaseForSession(sessionName);
if (kbase == null) {
throw new RuntimeException("Unknown StatelessKieSession with name '" + sessionName + "'");
}
return kbase.newStatelessKieSession(getConfForSession(sessionName));
}

private KieBase getKieBaseForSession(String sessionName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieRuntimeBuilder;
import org.kie.api.runtime.StatelessKieSession;
import org.drools.modelcompiler.KieBaseBuilder;

@org.springframework.stereotype.Component
Expand Down Expand Up @@ -63,8 +64,21 @@ public KieSession newKieSession(String sessionName) {
if (kbase == null) {
throw new RuntimeException("Unknown KieSession with name '" + sessionName + "'");
}
KieSession ksession = kbase.newKieSession(getConfForSession(sessionName), null);
return ksession;
return kbase.newKieSession(getConfForSession(sessionName), null);
}

@Override
public StatelessKieSession newStatelessKieSession() {
return newStatelessKieSession("$defaultStatelessKieSession$");
}

@Override
public StatelessKieSession newStatelessKieSession(String sessionName) {
KieBase kbase = getKieBaseForSession(sessionName);
if (kbase == null) {
throw new RuntimeException("Unknown StatelessKieSession with name '" + sessionName + "'");
}
return kbase.newStatelessKieSession(getConfForSession(sessionName));
}

private KieBase getKieBaseForSession(String sessionName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ private Map<String, KieBaseModel> readKieBaseModels() {
case "default":
kieSessionModel.setDefault( config.getValue(propertyName, Boolean.class) );
break;
case "stateless":
kieSessionModel.setType( config.getValue(propertyName, Boolean.class) ? KieSessionModel.KieSessionType.STATELESS : KieSessionModel.KieSessionType.STATEFUL );
break;
case "clockType":
kieSessionModel.setClockType( ClockTypeOption.get(config.getValue(propertyName, String.class) ) );
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
<groupId>org.drools</groupId>
<artifactId>drools-quarkus</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-commands</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ drools.prototypes=allowed

drools.kbase.canDrinkKB.packages=org.drools.drl
drools.kbase.canDrinkKB.ksession.canDrinkKS.default=true
drools.kbase.canDrinkKB.ksession.statelessCanDrinkKS.stateless=true
drools.kbase.canDrinkKB.ksession.statelessCanDrinkKS.default=true

drools.kbase.canDrinkKBDTable.packages=org.drools.dtable
drools.kbase.canDrinkKBDTable.ksession=canDrinkKSDTable
drools.kbase.canDrinkKBDTable.ksession.canDrinkKSDTable.stateless=false
drools.kbase.canDrinkKBDTable.ksession.statelessCanDrinkKSDTable.stateless=true

drools.kbase.canDrinkKBYaml.packages=org.drools.yaml
drools.kbase.canDrinkKBYaml.ksession=canDrinkKSYaml
drools.kbase.canDrinkKBYaml.ksession.statelessCanDrinkKSYaml.stateless=true

drools.kbase.canDrinkKBPrototype.packages=org.drools.prototype
drools.kbase.canDrinkKBPrototype.prototypes=allowed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.command.KieCommands;
import org.kie.api.definition.KiePackage;
import org.kie.api.internal.utils.KieService;
import org.kie.api.prototype.PrototypeFact;
import org.kie.api.prototype.PrototypeFactInstance;
import org.kie.api.runtime.KieRuntimeBuilder;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.RuntimeSession;
import org.kie.api.runtime.StatelessKieSession;

import static org.assertj.core.api.Assertions.assertThat;
import static org.kie.api.prototype.PrototypeBuilder.prototype;
Expand All @@ -42,30 +47,59 @@ public class RuntimeTest {
@Test
public void testDrlEvaluation() {
// canDrinkKS is the default session
testSimpleDrl(runtimeBuilder.newKieSession(), "org.drools.drl");
testSimpleDrl(runtimeBuilder.newKieSession(), "org.drools.drl", true);
}

@Test
public void testDTableEvaluation() {
testSimpleDrl(runtimeBuilder.newKieSession("canDrinkKSDTable"), "org.drools.dtable");
testSimpleDrl(runtimeBuilder.newKieSession("canDrinkKSDTable"), "org.drools.dtable", true);
}

@Test
public void testYamlEvaluation() {
testSimpleDrl(runtimeBuilder.newKieSession("canDrinkKSYaml"), "org.drools.yaml");
testSimpleDrl(runtimeBuilder.newKieSession("canDrinkKSYaml"), "org.drools.yaml", true);
}

private void testSimpleDrl(KieSession ksession, String assetPackage) {
List<String> pkgNames = ksession.getKieBase().getKiePackages().stream().map(KiePackage::getName).collect(Collectors.toList());
@Test
public void testStatelessDrlEvaluation() {
// statelessCanDrinkKS is the default stateless session
testSimpleDrl(runtimeBuilder.newStatelessKieSession(), "org.drools.drl", false);
}

@Test
public void testStatelessDTableEvaluation() {
testSimpleDrl(runtimeBuilder.newStatelessKieSession("statelessCanDrinkKSDTable"), "org.drools.dtable", false);
}

@Test
public void testStatelessYamlEvaluation() {
testSimpleDrl(runtimeBuilder.newStatelessKieSession("statelessCanDrinkKSYaml"), "org.drools.yaml", false);
}

private void testSimpleDrl(RuntimeSession session, String assetPackage, boolean stateful) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm using the new RuntimeSession interface to test both KieSession and StatelessKieSession with the same method.

if (stateful) {
assertThat(session).isInstanceOf(KieSession.class);
} else {
assertThat(session).isInstanceOf(StatelessKieSession.class);
}

List<String> pkgNames = session.getKieBase().getKiePackages().stream().map(KiePackage::getName).collect(Collectors.toList());

assertThat(pkgNames).hasSize(2).containsExactlyInAnyOrder("org.drools.quarkus.test", assetPackage);

KieCommands kieCommands = KieServices.get().getCommands();

Result result = new Result();
ksession.insert(result);
ksession.insert(new Person("Mark", 17));
ksession.fireAllRules();
session.execute( kieCommands.newBatchExecution(
kieCommands.newInsert(result),
kieCommands.newInsert(new Person("Mark", 17)),
kieCommands.newFireAllRules() ) );

assertThat(result.toString()).isEqualTo("Mark can NOT drink");

if (stateful) {
((KieSession) session).dispose();
}
}

@Test
Expand Down
6 changes: 6 additions & 0 deletions kie-api/src/main/java/org/kie/api/command/KieCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.kie.api.runtime.process.WorkItemHandler;
import org.kie.api.runtime.rule.FactHandle;

import static java.util.Arrays.asList;

/**
* KieCommands is a factory for Commands that can be used by classes that implement CommandExecutor. Typically more than one Command
* will want to be executed, where is where the BatchExecution comes in, which takes a List of commands, think of it as CompositeCommand.
Expand Down Expand Up @@ -115,6 +117,10 @@ Command newQuery(String identifier,
String name,
Object[] arguments);

default BatchExecutionCommand newBatchExecution(Command... commands) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HI @mariofusco
is this related to the overall task ? If so, could. you please explain why ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly related to this fix, it's just a convenience method that I added to create batch commands in a single line that I used in my test.

return newBatchExecution( asList(commands) );
}

BatchExecutionCommand newBatchExecution(List< ? extends Command> commands);

BatchExecutionCommand newBatchExecution(List< ? extends Command> commands, String lookup);
Expand Down
32 changes: 1 addition & 31 deletions kie-api/src/main/java/org/kie/api/runtime/KieRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,23 @@
*/
package org.kie.api.runtime;

import java.util.Map;

import org.kie.api.KieBase;
import org.kie.api.event.KieRuntimeEventManager;
import org.kie.api.runtime.KieSessionConfiguration;
import org.kie.api.runtime.process.ProcessRuntime;
import org.kie.api.runtime.rule.RuleRuntime;
import org.kie.api.time.SessionClock;

public interface KieRuntime
extends
RuleRuntime,
ProcessRuntime,
KieRuntimeEventManager {
public interface KieRuntime extends RuntimeSession, RuleRuntime, ProcessRuntime, KieRuntimeEventManager {

/**
* @return the session clock instance assigned to this session
*/
<T extends SessionClock> T getSessionClock();

/**
* Sets a global value in this session
* @param identifier the global identifier
* @param value the value assigned to the global identifier
*/
void setGlobal(String identifier,
Object value);

Object getGlobal(String identifier);

Globals getGlobals();

Calendars getCalendars();

Environment getEnvironment();

/**
* @return the KieBase reference from which this stateful session was created.
*/
KieBase getKieBase();

void registerChannel(String name,
Channel channel);

void unregisterChannel(String name);

Map< String, Channel> getChannels();

KieSessionConfiguration getSessionConfiguration();
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public interface KieRuntimeBuilder {
KieSession newKieSession();
KieSession newKieSession(String sessionName);

StatelessKieSession newStatelessKieSession();
StatelessKieSession newStatelessKieSession(String sessionName);

default KieSession newKieSession(KieSessionConfiguration conf) {
return getKieBase().newKieSession(conf, null);
}
Expand Down
Loading
Loading