Comments (13)
I (sort of) see what you mean and we probably cannot give for granted that the Type
is always a Class
in that point, but at the moment I don't understand under which conditions it could be something else, and I really need a reproducer of this problem since I don't want to just develop a blind fix. Can you please just paste here the drl of a sample rule in your knowledge base that is causing this issue so I could try to create the isolated reproducer on my own?
from incubator-kie-drools.
I understand not wanting to fix blindly unless the scenario is clear.
The DRL is this:
package com.mycompany.myproject.engine.rules.model;
//generated from Decision Table
import com.mycompany.myproject.engine.rules.model.*;
global com.mycompany.myproject.engine.rules.model.ServerCodeRuntimeService serverCode;
dialect "mvel"
// rule values at B13, header at B8
rule "Tank Rules-SmartBIN_13"
salience 65535
when
$asset: Sbtanknew_1_0_6($asset.devices.tank_device.properties.tanklevel_status != "Nearing Empty", $asset.devices.tank_device.readings.tank_level < $asset.properties.empty_fill_level_threshold)
then
$asset.getDevices().getTank_device().getProperties().setTanklevel_status("Nearing Empty");
$asset.getDevices().getTank_device().getProperties().setTanklevel_color("Red");
$asset.getProperties().setTank_level_status("CRITICAL");
AlertMessage message = new AlertMessage("Nearing Empty");
message.withParam("value", $asset.devices.tank_device.readings.tank_level);
message.withParam("alias", "sb_device_tank_level");
message.withParam("field", "Tank Level");
message.withParam("is_required", "Required");
insert(message);
end
if I drop $asset.devices.tank_device.readings.tank_level < $asset.properties.empty_fill_level_threshold
, the above error goes away and a different one appears, but this one I need to investigate further. It also seems related to the fact that a generic class is involved. (I understand $asset
inside the condition is redundant).
the model classes (eg:Sbtanknew_1_0_6) are derived from base classes and are runtime generated with byte-buddy, overriding several generic parameters of the parent class. I think this is where the issue comes from, and why it's not easy to isolate. I will try.
from incubator-kie-drools.
I have the feeling this could be related: https://issues.redhat.com/browse/DROOLS-7197, which I reported long time ago and was assumed to become a known issue partially documented in https://docs.drools.org/latest/drools-docs/drools/migration-guide/index.html
from incubator-kie-drools.
This is my attempt at reproducing it but no luck so far:
https://github.com/flozano/drools-issues/blob/main/src/test/java/drools/issues/DynamicClassTest.java
Classes are generated here dynamically in a similar way as I generate the ones causing trouble, with byte-buddy:
https://github.com/flozano/drools-issues/blob/main/src/main/java/drools/issues/model/vehicles/GasolineModelGenerator.java
and this DRL works well over them:
https://github.com/flozano/drools-issues/blob/main/src/test/resources/drools/issues/DynamicClassTest.drl
from incubator-kie-drools.
if I drop
$asset.devices.tank_device.readings.tank_level < $asset.properties.empty_fill_level_threshold
, the above error goes away and a different one appears, but this one I need to investigate further. It also seems related to the fact that a generic class is involved. (I understand$asset
inside the condition is redundant).
Is there any reason why you're keeping that $asset
inside the condition? Does it change anything if you remove it (I don't expect so, but just in case).
the model classes (eg:Sbtanknew_1_0_6) are derived from base classes and are runtime generated with byte-buddy, overriding several generic parameters of the parent class. I think this is where the issue comes from, and why it's not easy to isolate. I will try.
If the executable model generator can access the runtime classes generated by byte-buddy and introspect them during the code generation phase I believe that there shouldn't be any problem. My wild guess is that the executable model generator is introspecting the original classes before byte-buddy instrumentation and if so of course that's wrong and the root cause of the problem. Another (in my opinion more remote) possibility is that byte-buddy is rewriting the bytecode of the domain model classes in a way that for some reason prevents the introspection necessary for the executable model generation, but if so we would also need a reproducer for that.
from incubator-kie-drools.
Thanks for answering!
Is there any reason why you're keeping that $asset inside the condition? Does it change anything if you remove it (I don't expect so, but just in case).
I'm keeping because the original DRL had it and I wanted to reproduce exactly - but no, it doesn't change anything. I mentioned in:
(I understand $asset inside the condition is redundant).
With regard to:
If the executable model generator can access the runtime classes generated by byte-buddy and introspect them during the code generation phase I believe that there shouldn't be any problem.
I believe so too. I use the correct strategy in byte-buddy (ClassLoadingStrategy.Default.CHILD_FIRST_PERSISTENT
) and expose the right class-loader to drools... so everything is there for drools to access.
update
I just reproduced it, you can find the failing version here: https://github.com/flozano/drools-issues/blob/main/src/test/java/drools/issues/DynamicClassTest.java
The changes to reproduce:
After properly subclassing in byte-buddy with the generic type descriptor instead of the raw Vehicle class,
and using the property getter defined in the parent item (motor
instead of engine
), I expected to find same issue as in #5932 (https://issues.redhat.com/browse/DROOLS-7197), but I didn't, I reproduced this.
full stack-trace
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.TypeVariableImpl and java.lang.Class are in module java.base of loader 'bootstrap')
java.lang.ClassCastException: class sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.TypeVariableImpl and java.lang.Class are in module java.base of loader 'bootstrap')
at org.drools.model.codegen.execmodel.generator.drlxparse.SpecialComparisonCase.typeNeedsCast(SpecialComparisonCase.java:71)
at org.drools.model.codegen.execmodel.generator.drlxparse.SpecialComparisonCase.specialComparisonFactory(SpecialComparisonCase.java:56)
at org.drools.model.codegen.execmodel.generator.drlxparse.ConstraintParser.handleSpecialComparisonCases(ConstraintParser.java:900)
at org.drools.model.codegen.execmodel.generator.drlxparse.ConstraintParser.parseBinaryExpr(ConstraintParser.java:712)
at org.drools.model.codegen.execmodel.generator.drlxparse.ConstraintParser.compileToJavaRecursive(ConstraintParser.java:317)
at org.drools.model.codegen.execmodel.generator.drlxparse.ConstraintParser.compileStart(ConstraintParser.java:269)
at org.drools.model.codegen.execmodel.generator.drlxparse.ConstraintParser.drlxParse(ConstraintParser.java:164)
at org.drools.model.codegen.execmodel.generator.visitor.pattern.ClassPatternDSL.findAllConstraint(ClassPatternDSL.java:188)
at org.drools.model.codegen.execmodel.generator.visitor.pattern.PatternDSL.buildPattern(PatternDSL.java:62)
at org.drools.model.codegen.execmodel.generator.visitor.ModelGeneratorVisitor.visit(ModelGeneratorVisitor.java:132)
at org.drools.drl.ast.descr.PatternDescr.accept(PatternDescr.java:278)
at org.drools.model.codegen.execmodel.generator.visitor.AndVisitor.visit(AndVisitor.java:52)
at org.drools.model.codegen.execmodel.generator.visitor.ModelGeneratorVisitor.visit(ModelGeneratorVisitor.java:70)
at org.drools.model.codegen.execmodel.generator.ModelGenerator.processRule(ModelGenerator.java:204)
at org.drools.model.codegen.execmodel.generator.ModelGenerator.processRuleDescr(ModelGenerator.java:185)
at org.drools.model.codegen.execmodel.generator.ModelGenerator.processRules(ModelGenerator.java:164)
at org.drools.model.codegen.execmodel.generator.ModelGenerator.generateModel(ModelGenerator.java:130)
at org.drools.model.codegen.execmodel.processors.ModelGeneratorPhase.process(ModelGeneratorPhase.java:48)
at org.drools.compiler.builder.impl.processors.IteratingPhase.process(IteratingPhase.java:53)
at org.drools.model.codegen.execmodel.processors.ModelMainCompilationPhase.process(ModelMainCompilationPhase.java:104)
at org.drools.model.codegen.execmodel.ModelBuilderImpl.doSecondBuildStep(ModelBuilderImpl.java:114)
at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.build(CompositeKnowledgeBuilderImpl.java:125)
at org.drools.compiler.builder.impl.CompositeKnowledgeBuilderImpl.build(CompositeKnowledgeBuilderImpl.java:109)
at org.drools.compiler.kie.builder.impl.AbstractKieProject.buildKnowledgePackages(AbstractKieProject.java:274)
at org.drools.compiler.kie.builder.impl.AbstractKieProject.buildKnowledgePackages(AbstractKieProject.java:220)
at org.drools.compiler.kie.builder.impl.AbstractKieProject.verify(AbstractKieProject.java:84)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildKieProject(KieBuilderImpl.java:285)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:251)
at org.drools.compiler.kie.builder.impl.KieBuilderImpl.buildAll(KieBuilderImpl.java:208)
at drools.issues.executor.DroolsInternalFactory.instanceKieContainer(DroolsInternalFactory.java:52)
at drools.issues.executor.AbstractDroolsExecutor.<init>(AbstractDroolsExecutor.java:56)
at drools.issues.executor.AbstractDroolsExecutor.<init>(AbstractDroolsExecutor.java:45)
at drools.issues.executor.SingleStatefulSessionExecutor.<init>(SingleStatefulSessionExecutor.java:15)
at drools.issues.AbstractTest.executor(AbstractTest.java:16)
at drools.issues.DynamicClassTest.test(DynamicClassTest.java:39)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestTemplateMethod(TimeoutExtension.java:92)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:226)
at org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor.execute(NodeTestTask.java:204)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:139)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.lambda$execute$2(TestTemplateTestDescriptor.java:107)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:107)
at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:42)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:119)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:94)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:89)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
from incubator-kie-drools.
I will try to give a look at that reproducer asap, but what I don't understand is why it is not possible to create the same reproducer in a more isolated way and without byte-buddy. I mean once you have done the byte-buddy instrumentation those generated classes should be indistinguishable from classes generated by a normal compilation. In essence what I'm suggesting is that it should be possible to also reproduce the same problem with a plain Java domain model that incorporates in its source the changes made at bytecode level by byte-buddy. Am I making sense? Do you think it would be possible to create such a reproducer?
from incubator-kie-drools.
I agree with you that it should be possible, but if you look at what my byte-buddy code does, it should be the same already...
Base
public abstract class Vehicle<TEngine extends Engine> {
public abstract TEngine getEngine();
public abstract class Engine {
// ...
"Diesel" model, 'normal' java compilation-generated classes
public class DieselCar extends Vehicle<DieselEngine> {
// ...
public DieselEngine getEngine() {
return engine;
}
// ...
public class DieselEngine extends Engine {
"Gasoline" model, byte-buddy generated classes
engineClass = new ByteBuddy()
.subclass(Engine.class).name("drools.issues.model.vehicles.GasolineEngine") //
.method(ElementMatchers.named("isZeroEmissions")) //
.intercept(FixedValue.value(false)) //
.defineProperty("highOctane", boolean.class) //
.defineProperty("maxTorque", int.class) //
.defineProperty("serialNumber", long.class) //
.make().load(classLoader, ClassLoadingStrategy.Default.CHILD_FIRST_PERSISTENT).getLoaded();
TypeDescription.Generic generic = TypeDescription.Generic.Builder.parameterizedType(Vehicle.class, engineClass).build();
vehicleClass = (Class<? extends Vehicle>) new ByteBuddy() //
// .subclass(Vehicle.class) //
.subclass(generic)
.name("drools.issues.model.vehicles.GasolineVehicle") //
.defineField("engine", engineClass, Visibility.PRIVATE) //
.defineConstructor(Visibility.PUBLIC) //
.withParameters(String.class, String.class, engineClass) //
.intercept(MethodCall.invoke(Vehicle.class.getDeclaredConstructor(String.class, String.class))
.withArgument(0, 1) //
.andThen(FieldAccessor.ofField("engine").setsArgumentAt(2)) //
) //
.defineMethod("getEngine", engineClass, Visibility.PUBLIC) //
.intercept(FieldAccessor.ofField("engine")) //
.defineProperty("frameMaxTorque", long.class) //
.make().load(classLoader, ClassLoadingStrategy.Default.CHILD_FIRST_PERSISTENT).getLoaded();
the byte-buddy generated class is legal JVM code that can be executed. I can dispatch invocations to parent class (Engine
) methods, subclass (DieselEngine
) methods... as per the JVM this should be legal code, I believe.
from incubator-kie-drools.
from byte-buddy, it very explicitly supports subclasses of generic parents:
/**
* <p>
* Creates a new builder for subclassing the provided type. If the provided type is an interface, a new class implementing
* this interface type is created.
* </p>
* <p>
* When extending a class, Byte Buddy imitates all visible constructors of the subclassed type and sets them to be {@code public}.
* Any constructor is implemented to only invoke its super type constructor of equal signature. Another behavior can be specified by
* supplying an explicit {@link ConstructorStrategy} by {@link ByteBuddy#subclass(TypeDefinition, ConstructorStrategy)}.
* </p>
* <p>
* <b>Note</b>: This methods implements the supplied types <i>as is</i>, i.e. any {@link TypeDescription} values are implemented
* as raw types if they declare type variables.
* </p>
* <p>
* <b>Note</b>: Byte Buddy does not cache previous subclasses but will attempt the generation of a new subclass. For caching
* types, a external cache or {@link TypeCache} should be used.
* </p>
*
* @param superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type
* variables that are referenced by the generic type must be declared by the generated subclass before creating
* the type.
* @return A type builder for creating a new class extending the provided class or interface.
*/
public DynamicType.Builder<?> subclass(TypeDefinition superType) {
return subclass(superType, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING);
}
superType The super class or interface type to extend. The type must be a raw type or parameterized type. All type variables that are referenced by the generic type must be declared by the generated subclass before creating the type.
from incubator-kie-drools.
(just pushed a small fix for another unrelated method which was declared package-private but public in the byte-buddy. it has no effect on this specific test and case).
from incubator-kie-drools.
@mariofusco after you pushed for checking this better, I verified I could also reproduce this with non-byte-buddy classes:
I copied the test and replicated it with DieselCar/Engine, which are normal java classes.
from incubator-kie-drools.
Fixed by 785ef86
from incubator-kie-drools.
Thanks a lot! I will verify once the SNAPSHOT is built.
The same test incidentally raised #5943, will check that one too.
from incubator-kie-drools.
Related Issues (20)
- Add explanation for "Generics return type resolution" in migration guide
- [new-parser] Anonymous classes not supported HOT 3
- [new-parser] `PackageDescr.resource` not set HOT 3
- [new-parser] `unit` without `package` should not be allowed HOT 1
- [new-parser] `||` and `&&` should be allowed as alternatives to infix `or` and `and` HOT 2
- [new-parser] Tests using wrong duration attribute format HOT 2
- [new-parser] Support ISO 8601 format for duration attribute's value HOT 2
- [new-parser] InternalResource's encoding is ignored HOT 1
- Difference when using redundant variable qualifier and not using it (with MVEL runtime, MVEL syntax) HOT 2
- [new-parser] Broken named consequences inside OR HOT 2
- [new-parser] Broken testIncompatibleListOnAccumulateFunction HOT 1
- [new-parser] ClassCastException in test2AccumulatesWithOr HOT 3
- [new-parser] IOOBE in visitLhsUnary if LHS is invalid HOT 1
- executable model fails to handle property reactive with null-safe-dereferencing HOT 1
- [new-parser] Unify error reporting of DRLParser and DRL6Expressions
- OOPath from bound Variable HOT 1
- DSL Constraints Don't Work With OOPath HOT 2
- [new-parser] Backward compatibility issues
- [new-parser] Improvement candidates HOT 1
- Possible deadlock with KieRepositoryImpl$KieModuleRepo and KieRepositoryScannerImpl
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from incubator-kie-drools.