I am trying to add a non-existing method to a Java bean, compile it and use the newly added method in Drools rules. Via a custom class loader.
I am using CompilerUtils to bind newly modified class to the custom ClassLoader
as follows:
ClassLoader loader = new ClassLoader(){}; String className = "com.example.Transaction"; String path = "file:D:/workspace/Transaction.class.tmp"; // a tmp file that contains source for Java bean try { URL transactionUrl = new URL(path); URLConnection connection = transactionUrl.openConnection(); InputStream input = connection.getInputStream(); String transactionClass = new String(StreamUtils.copyToByteArray(input), StandardCharsets.UTF_8); System.out.println(transactionClass); String javaCode = "npublic int test() {n" + " return 3;n" + " }n" + "}"; String updatedClassString = transactionClass.substring(0, transactionClass.length() - 1).concat(javaCode); Class<?> classB = CompilerUtils.CACHED_COMPILER.loadFromJava(loader, className, updatedClassString); // This is where the loader is made aware of the newly compiled class return loader; } catch (IOException | ClassNotFoundException exception) { e.printStackTrace(); } return null;
And this is where I give access to drools my classloader
final KieServices kServices = KieServices.Factory.get(); final KieFileSystem kFileSystem = kServices.newKieFileSystem(); final KieModuleModel kModuleModel = KieRulePopulator.kieModuleModel(); if (kModuleModel != null) kFileSystem.writeKModuleXML(kModuleModel.toXML()); kServices .newKieBuilder(kFileSystem, classLoader) .buildAll(); } KieContainer container = kServices.newKieContainer(kServices .getRepository() .getDefaultReleaseId(), classLoader);
This is how I fire rules
final KieBaseConfiguration configuration = KieServices.Factory.get().newKieBaseConfiguration(); final KieSession kSession = container .getKieContainer() .newKieBase(configuration) .newKieSession(); Transaction someTransaction = new Transaction(); kSession.insert(transaction); kSession.fireAllRules();
And this is my rule
rule "Rule_31F6DE769554404B89D4E3B7B5979CA1" dialect "java" no-loop true when tr : Transaction( test == 3 ) then System.out.println("deneme"); end
Advertisement
Answer
I have load Transaction class from containers classloader and it worked.
final KieSession kSession = container .getKieContainer() .newKieBase(configuration) .newKieSession(); Class<?> classA = container.getKieContainer().getClassLoader().loadClass("com.example.Transaction"); Object transaction = classA.getDeclaredConstructor().newInstance(); kSession.insert(transaction); kSession.fireAllRules();