Reputation: 613
When I fire the rules I got a strange error.
The error details are
java.lang.RuntimeException: Unexpected global [validateResult]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1209)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:190)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:204)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.signUp(SignUpProjectServiceImpl.java:102)
at com.hikedu.backend.controller.ProjectApplicationRecordController.signUp(ProjectApplicationRecordController.java:94)
at com.hikedu.backend.controller.ProjectApplicationRecordController$$FastClassBySpringCGLIB$$dc339407.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
Here is my code to fire the rules
KieSession session = sessionBuilder.build(theDsl);
ProjectVersion latestVersion = projectVersionService.getLatestVersionIfNotExistsThenThrowException(projectId);
User user = userService.getUserIfNotExistsThenThrowException(userId);
ApplicationInfo info = getTheInsertObj(userId, projectId);
ProjectSignUpValidateResultDTO resultDTO = new ProjectSignUpValidateResultDTO();
resultDTO.setPass(true);
session.setGlobal("validateResult", resultDTO);
session.insert(latestVersion);
session.insert(info);
session.insert(user);
session.fireAllRules(1);
session.dispose();
return resultDTO;
I searched a lot about this error. The answers all talking the same thing--The dsl file must declar the global and the declar name and path must be euqal to the code given But I confirmd again and again my dsl and my code there is not found any mistaken.
I tried to change the global name to nother one but still get that error.
So please help me.
Here is my dsl
import com.hikedu.backend.model.User;
import com.hikedu.backend.model.ProjectVersion;
import java.util.Map;
import com.hikedu.backend.dto.signupproject.ApplicationInfo
import java.util.Date
import java.sql.Timestamp
global com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO validateResult
rule "department not match"
no-loop
when
$p : ProjectVersion()
$u : User($p.applicationRequirements.departmentId not contains departmentOfJoined.id)
then
validateResult.setPass(false);
validateResult.setTheReasonOfUnPass("some reason");
end
And I did the debug to check the globals of the session. Here is the debug result
The drools version I am using is
Here is the KieSessionBuilder.build method
@Override
public KieSession build(String dsl) {
if (dsl == null) {
throw new RuntimeException("Dsl cannot be null");
}
KieHelper helper = new KieHelper();
helper.setClassLoader(getClass().getClassLoader());
helper.addContent(dsl, ResourceType.DSL);
KieBase base = helper.build();
return base.newKieSession();
}
Thanks you all. My english dost not good well please forgive me.
Upvotes: 0
Views: 2969
Reputation: 1591
Coming late to the party, but I had the same error, but for a different reason. I was changing a system using Drools 7.0.12 from using a stateless session to a stateful session. It would appear that in a stateful session Drools is checking that the global is actually defined in at least one .drl file. If there is no "global" definition in a .drl file then the unexpected Global error is thrown. In a stateless session, no such check is made.
Upvotes: 2
Reputation: 613
I resovled the error by myself. Here is the solution:
Change the way of build drl.
@Override
public KieSession build(String drl) {
if (drl == null) {
throw new RuntimeException("Drl cannot be null");
}
kieFileSystem.write("src/main/resources/" + drl.hashCode() + ".drl", kieServices.getResources().newReaderResource(new StringReader(drl)));
KieBuilder builder = kieServices.newKieBuilder(kieFileSystem).buildAll();
Results results = builder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
throw new IllegalStateException("##errors : " + results.getMessages());
}
KieContainer container = kieServices.newKieContainer(builder.getKieModule().getReleaseId());
return container.newKieSession();
}
After I changed the way of build drl got another error :
java.lang.RuntimeException: Illegal class for global. Expected [com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO], found [com.hikedu.backend.dto.project.ProjectSignUpValidateResultDTO].
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1211)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:190)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.validate(SignUpProjectServiceImpl.java:204)
at com.hikedu.backend.service.impl.signupproject.SignUpProjectServiceImpl.signUp(SignUpProjectServiceImpl.java:102)
at com.hikedu.backend.controller.ProjectApplicationRecordController.signUp(ProjectApplicationRecordController.java:94)
at com.hikedu.backend.controller.ProjectApplicationRecordController$$FastClassBySpringCGLIB$$dc339407.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
I searched a lot about this new error. And finally got the solution. This error because I am using the devtools in my project. And the devtools will use itself classloader to load all class. But the drools load the class by another classloader.
Here is the debug info :
How to resolve this ? Just add the META-INF/spring-devtools.properties file. The content is
restart.include.drools=/drools-[\\s\\S]+\.jar
restart.include.kie=/kie-[\\s\\S]+\.jar
This will make sure the drools and kie load by devtools itself class loader. And then the error fixed.
Here is some document
https://github.com/spring-projects/spring-boot/issues/3316
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html
Upvotes: 1