Custom ClassLoader with Drools gives ClassCastException

65 views
Skip to first unread message

Hasan Can Saral

unread,
Jun 2, 2022, 4:58:04 AM6/2/22
to drools...@googlegroups.com

I'm trying to use a custom ClassLoader with Drools to add some methods to my facts using javassist in runtime. Here's the custom ClassLoader that extends Loader of javassist:

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {

        final Class<?> clazz = super.loadClass(name);

        if (clazz.getName().equals("my.package.MyClass") {

            final ClassPool classPool = ClassPool.getDefault();

            final CtClass javassistClass = classPool.get(clazz.getName());

            for (final MetaField field : fields) {

                final CtMethod method = CtNewMethod.make("public String sampleMethod() {\n" +
                                "   return \"Sample String\"; \n" +
                                "}");

                javassistClass.addMethod(method);

            return classPool.toClass(javassistClass, clazz.getClassLoader(), null);

        }

        return clazz;
    }

However, this leaves me with the exception:

java.lang.RuntimeException: Unable to load dialect 'org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration:java:org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration'
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.addDialect(KnowledgeBuilderConfigurationImpl.java:394)
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.buildDialectConfigurationMap(KnowledgeBuilderConfigurationImpl.java:380)
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.init(KnowledgeBuilderConfigurationImpl.java:235)
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.init(KnowledgeBuilderConfigurationImpl.java:187)
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.<init>(KnowledgeBuilderConfigurationImpl.java:155)
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.getBuilderConfiguration(AbstractKieProject.java:302)
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.createKnowledgeBuilder(AbstractKieProject.java:288)
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.buildKnowledgePackages(AbstractKieProject.java:213)
    at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:75)
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:271)
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:239)
    at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:188)
    at com.company.project.kie.util.KieRulePopulator.populateInternal(KieRulePopulator.java:112)
    at com.company.project.kie.util.KieRulePopulator.populate(KieRulePopulator.java:150)
    at com.company.project.kie.domain.rule.KieRuleContainer.initInternal(KieRuleContainer.java:121)
    at com.company.project.kie.domain.rule.KieRuleContainer.init(KieRuleContainer.java:105)
    at java.base/java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:441)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at com.company.project.kie.domain.rule.dao.JdbcCacheableKieRuleContainerDaoImpl.find(JdbcCacheableKieRuleContainerDaoImpl.java:105)
    at com.company.project.kie.domain.rule.dao.JdbcCacheableKieRuleContainerDaoImpl$$FastClassBySpringCGLIB$$9f93eb18.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:53)
    at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:365)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:420)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345)
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at com.company.project.kie.domain.rule.dao.JdbcCacheableKieRuleContainerDaoImpl$$EnhancerBySpringCGLIB$$414ae73c.find(<generated>)
    at com.company.client.core.configuration.ClientCachePopulatingApplicationListener$1.<init>(ClientCachePopulatingApplicationListener.java:102)
    at com.company.client.core.configuration.ClientCachePopulatingApplicationListener.onApplicationEvent(ClientCachePopulatingApplicationListener.java:101)
    at com.company.client.core.configuration.ClientCachePopulatingApplicationListener.onApplicationEvent(ClientCachePopulatingApplicationListener.java:42)
    at com.company.client.core.configuration.ClientCachePopulatingApplicationListener$$EnhancerBySpringCGLIB$$d87e98b8.onApplicationEvent(<generated>)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:403)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:360)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:897)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at com.company.client.core.NeroFraudGateApplication.main(NeroFraudGateApplication.java:28)
Caused by: java.lang.ClassCastException: class org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration cannot be cast to class org.drools.compiler.compiler.DialectConfiguration (org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration is in unnamed module of loader com.company.project.kie.util.MetaFieldAwareClassLoader @6dc98c02; org.drools.compiler.compiler.DialectConfiguration is in unnamed module of loader 'app')
    at org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl.addDialect(KnowledgeBuilderConfigurationImpl.java:389)
    ... 57 common frames omitted

Here's and excerpt from javassist tutorial:

If the program is running on some application server such as JBoss and
Tomcat, the context class loader used by toClass() might be
inappropriate. In this case, you would see an unexpected
ClassCastException. To avoid this exception, you must explicitly
give an appropriate class loader to toClass(). For example, if bean
is your session bean object, then the following code:

CtClass cc = ...; Class c = cc.toClass(bean.getClass().getClassLoader());

would work. You should give toClass() the class loader that has
loaded your program (in the above example, the class of the bean
object).

toClass() is provided for convenience. If you need more complex
functionality, you should write your own class loader.

What am I missing? Thanks.

Reply all
Reply to author
Forward
0 new messages