I have a class DroolsRuleLocator that fetches rules from the database, compiles and hands me back the RuleBase. At this time I have just one rule file with a bunch of rules in them. I do not experience any issues when I execute that in a single thread.
But when I load test my application and the client is passing in the request that requires lookup and compilation of the same rule source in my server concurrently but on different threads, it appears that my application is dead locked trying to compile the rules.
Relevant Rule compilation code:
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
try {
// Rule is a simple java bean containing the rule text.
for (Rule rule : rules) {
// ruleDefinition will contain the contents of the drl source.
String ruleDefinition = rule.getRuleText();
PackageBuilder builder = new PackageBuilder();
// Parse and compile in one step
builder.addPackageFromDrl(new StringReader(ruleDefinition));
if (builder.hasErrors()) {
throw new RuntimeException("Unable to compile rule definition: "+ rule.getName());
}
// Get the compiled package (which is serializable)
Package pkg = builder.getPackage();
// Add the package to the created rulebase (deploy the rule package).
ruleBase.addPackage(pkg);
}
}
Remote attaching to the tomcat server and suspending the hanging threads shows the following trace.
Daemon Thread [http-8080-58] (Suspended)
owns: PhaseInterceptorChain (id=315)
waiting for: StandardClassLoader (id=244)
owned by: Daemon Thread [http-8080-62] (Running)
StandardClassLoader(ClassLoader).loadClass(String, boolean) line: not available
StandardClassLoader(ClassLoader).loadClass(String) line: not available
WebappClassLoader.loadClass(String, boolean) line: 1349
WebappClassLoader.loadClass(String) line: 1208
ParserContext.checkForDynamicImport(String) line: 121
ParserContext.hasImport(String) line: 155
ExpressionCompiler(AbstractParser).createPropertyToken(int, int) line: 893
ExpressionCompiler(AbstractParser).nextToken() line: 836
ExpressionCompiler._compile() line: 80
ExpressionCompiler.compile(ParserContext) line: 44
MVELExprAnalyzer.analyzeExpression(RuleBuildContext, String, Set[], Map) line: 85
MVELDialect.analyzeExpression(RuleBuildContext, BaseDescr, Object, Map) line: 320
MVELDialect.analyzeExpression(RuleBuildContext, BaseDescr, Object) line: 308
MVELFromBuilder.build(RuleBuildContext, BaseDescr, Pattern) line: 71
MVELFromBuilder.build(RuleBuildContext, BaseDescr) line: 50
PatternBuilder.build(RuleBuildContext, BaseDescr, Pattern) line: 172
PatternBuilder.build(RuleBuildContext, BaseDescr) line: 87
GroupElementBuilder.build(RuleBuildContext, BaseDescr, Pattern) line: 69
RuleBuilder.build(RuleBuildContext) line: 53
PackageBuilder.addRule(RuleDescr) line: 446
PackageBuilder.addPackage(PackageDescr) line: 304
PackageBuilder.addPackageFromDrl(Reader) line: 167
DroolsRuleLocator.findRuleBase(long, String) line: 122
Can someone clarify if this dead lock scenario is a possibility. Currently I am sychronizing on the method that compiles and returns the RuleBase to avoid this situation.
Thanks.
- Krishna