0

I am using Spring Boot starter 2.3.1, Groovy-all 2.4.13. I have a mechanism which enables me to execute Groovy Scripts at runtime from within my Java program. Something like below:

GroovyShell groovyShell = new GroovyShell(this.getClass().getClassLoader());
Class<Script> pScriptClass = groovyShell.parse(pScriptString).getClass();
Script pScriptObject = pScriptClass.newInstance();
pScriptObject.setBinding(pBinding);
return pScriptObject.invokeMethod("process", null);

This is running fine as long as the script does not involve any casting. However, in one of my script, I've a class casting like below:

Object process(){
   RestServiceUtil resServ = (RestServiceUtil) applicationContext.getBean("restServiceUtil");
   .
   .
   .
}

In the case above I understand that the LHS refers to the class object from the GroovyClassLoader whereas the RHS is from the java class loader. However, from whatever I dug up, this should not create problem since the GroovyShell was created with java class loader as parent i.e. new GroovyShell(this.getClass().getClassLoader())

But when I try to run this script, I still see class cast exception. Since the Groovy class loader is using the Java class loader as parent I was thinking we shouldn't have two separately compiled instances.

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.bell.na.nt.bnsm.nets.consumer.utils.RestServiceUtil@1f239d3f' with class 'com.bell.na.nt.bnsm.nets.consumer.utils.RestServiceUtil$$EnhancerBySpringCGLIB$$88984819' to class 'com.bell.na.nt.bnsm.nets.consumer.utils.RestServiceUtil'
    at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405) ~[groovy-all-2.4.13.jar:2.4.13]
    at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319) ~[groovy-all-2.4.13.jar:2.4.13]
    at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:232) ~[groovy-all-2.4.13.jar:2.4.13]
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603) ~[groovy-all-2.4.13.jar:2.4.13]
    at Script33.process(Script33.groovy:16) ~[?:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_282]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_282]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_282]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_282]
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:803) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46) ~[groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.Script.invokeMethod(Script.java:80) ~[groovy-all-2.4.13.jar:2.4.13]
    at com.bell.na.nt.remedy.groovy.NetsUtilityGroovyUtils.execute(NetsUtilityGroovyUtils.java:62) ~[ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.json.utils.NetsUtilityJSONDatumUtils.getJsonValue(NetsUtilityJSONDatumUtils.java:260) [ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.json.utils.NetsUtilityJSONDatumUtils.createPlainJsonObjectFromJsonObject(NetsUtilityJSONDatumUtils.java:169) [ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.json.utils.NetsUtilityJSONDatumUtils$createPlainJsonObjectFromJsonObject.call(Unknown Source) [ms-nets-utility-library-1.0.jar:1.0]
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-all-2.4.13.jar:2.4.13]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-all-2.4.13.jar:2.4.13]
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-all-2.4.13.jar:2.4.13]
    at Script8.process(Script8.groovy:17) [shell:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_282]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_282]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_282]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_282]
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:803) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:46) [groovy-all-2.4.13.jar:2.4.13]
    at groovy.lang.Script.invokeMethod(Script.java:80) [groovy-all-2.4.13.jar:2.4.13]
    at com.bell.na.nt.remedy.groovy.NetsUtilityGroovyUtils.execute(NetsUtilityGroovyUtils.java:62) [ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.json.utils.NetsUtilityJSONDatumUtils.getJsonValue(NetsUtilityJSONDatumUtils.java:260) [ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.json.utils.NetsUtilityJSONDatumUtils.createPlainJsonObjectFromJsonObject(NetsUtilityJSONDatumUtils.java:169) [ms-nets-utility-library-1.0.jar:1.0]
    at com.bell.na.nt.bnsm.nets.consumer.service.BNSMNETSReaderService.transformJSONMsg(BNSMNETSReaderService.java:138) [classes/:?]
    at com.bell.na.nt.bnsm.nets.consumer.service.BNSMNETSReaderService.iterativelyTrnsfrmJSON(BNSMNETSReaderService.java:117) [classes/:?]
    at com.bell.na.nt.bnsm.nets.consumer.service.BNSMNETSReaderService.processEventMessage(BNSMNETSReaderService.java:76) [classes/:?]
    at com.bell.na.nt.bnsm.nets.consumer.processor.EventReaderMessageProcessor.processMessage(EventReaderMessageProcessor.java:42) [classes/:?]
    at com.bell.na.nt.kafka.consumer.KafkaConsumer.onMessage(KafkaConsumer.java:52) [spring-kafka-consumer-module-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_282]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_282]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_282]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_282]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) [spring-messaging-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) [spring-messaging-5.2.7.RELEASE.jar:5.2.7.RELEASE]
    at org.springframework.kafka.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:48) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:329) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:86) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:51) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:1878) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeOnMessage(KafkaMessageListenerContainer.java:1860) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:1797) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:1737) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:1634) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1364) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1080) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:988) [spring-kafka-2.5.4.RELEASE.jar:2.5.4.RELEASE]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_282]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_282]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_282]

Any help in this regard would be much appreciated.

2
  • Did you have look with -verbose, where RestServiceUtil is loaded from? Maybe twice? Commented Mar 30, 2021 at 16:50
  • Thanks @Turo. I will try this option to check for multiples ... Commented Mar 30, 2021 at 16:53

1 Answer 1

0

So apparently it was two different classloader hierarchy which was causing the problem. Java class loader and then there was this GroovyClassLoader which had separate instance of the same Object that it was trying to cast to i.e. something similar to what we see below.

enter image description here

Therefore the following way to initialize groovyclassloader using the java class loader as parent should work. GroovyShell groovyShell = new GroovyShell(this.getClass().getClassLoader());

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.