Skip to content

Grails 6.2.2: ClassCastException for inheritance in Commands #13945

@agre1981

Description

@agre1981

Expected Behavior

Grails throws exception ClassCastException when we have 2 endpoints with inherited commands. It worked fine on 6.1.2.

Looks like this is a critical issue.

class UrlMappings {
        "/my/$patientId/procedure"(controller: "my", action: "createLedgerProcedure", method: "POST")
        "/my/$patientId/procedure/insuranceEstimates"(controller: "my", action: "getInsuranceEstimates", method: "POST")
}

class MyBaseCommand implements Validateable {

    int testId
}

class MyCommand extends MyBaseCommand {

    int myId
}

class MyController {
    def getInsuranceEstimates(MyCommand command, long patientId) {
        log.info('test2 method')
        render([response: "test2 method"] as JSON)
    }

    def createLedgerProcedure(MyBaseCommand command, long patientId) {
        log.info('test1 method')
        render([response: "test1 method"] as JSON)
    }

}

Actual Behaviour

Exception:

2024-12-26 18:13:10.639 ERROR --- [nio-8080-exec-2] StackTrace                               : Full Stack Trace:

java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
	at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
	at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.ClassCastException: class com.example.MyBaseCommand cannot be cast to class com.example.MyCommand (com.example.MyBaseCommand and com.example.MyCommand are in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @8f4db8)
	... 13 common frames omitted

2024-12-26 18:13:10.690 ERROR --- [nio-8080-exec-2] o.g.web.errors.GrailsExceptionResolver   : ClassCastException occurred when processing request: [POST] /my/123/procedure
class com.example.MyBaseCommand cannot be cast to class com.example.MyCommand (com.example.MyBaseCommand and com.example.MyCommand are in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @8f4db8). Stacktrace follows:

java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
	at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
	at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.ClassCastException: class com.example.MyBaseCommand cannot be cast to class com.example.MyCommand (com.example.MyBaseCommand and com.example.MyCommand are in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @8f4db8)
	... 13 common frames omitted

Steps To Reproduce

Reproduces on Grails 6.2.2. It worked fine on 6.1.2.

grails_6_2_2.zip

An example of the application has been attached:

  • run the attached application: ./gradlew bootRun
  • Send the request:

curl --location --request POST 'http://localhost:8080/my/123/procedure' \
--header 'Content-Type: application/json' \
--data '{
    "testId": 321
}'

Environment Information

  • Windows 10
  • Java:
openjdk version "11.0.22" 2024-01-16
OpenJDK Runtime Environment Temurin-11.0.22+7 (build 11.0.22+7)
OpenJDK 64-Bit Server VM Temurin-11.0.22+7 (build 11.0.22+7, mixed mode)

Example Application

No response

Version

6.2.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions