grails-core icon indicating copy to clipboard operation
grails-core copied to clipboard

Grails 4.0.12 and 5.0.1: VERY strange behavior in controller action using enumeration

Open davidkron opened this issue 3 years ago • 0 comments

We did upgrade some production application of ours to Grails 4.0.12 from 3.3.x and some specific code suddenly stopped working. I managed to extract a minimal example application with similar code, which produces the exception. I also added some Spock tests which verify the problem. Additionally I also tried with the newest Grails version 5.0.1, but the problem is still present there.

grails-app/controllers/myapp/TestController.groovy

package myapp

import groovy.util.logging.Slf4j
import myapp.utils.UIState

@Slf4j // works if @Slf4j is removed
class TestController {

    // works if parameter name is changed from someState to something else
    def something(String someState) {
        render 'something'
    }

    private UIState getUIState() {
        // works if variable someState is changed to something else
        UIState.SomeState someState = UIState.SomeState.NORMAL
        return new UIState(state: someState)
    }
}

src/main/groovy/myapp/utils/UIState.groovy

package myapp.utils

import groovy.transform.Immutable

@Immutable
class UIState {

    enum SomeState { NORMAL, THING, THINGY }

    SomeState state = SomeState.NORMAL
}

This produces an java.lang.IllegalArgumentException: No enum constant myapp.utils.UIState.SomeState. when I open the URL http://localhost:8080/test/something?someState= inside the browser.

What is very strange in this code is the fact, that when I change only one of the marked lines above (see my comments in the code), the example suddenly starts working. Also I don't understand why in the non-working example some Enum.valueOf call seems to happen, but in my very simple controller code the action something doesn't utilize the parameter and it is not even an enumeration. Also the private utility method getUIState is not invoked at all and why the presence of the @Slf4j annotation changes the behavior is very unclear to me.

Task List

  • [x] Steps to reproduce provided
  • [x] Stacktrace (if present) provided
  • [x] Example that reproduces the problem uploaded to Github
  • [x] Full description of the issue provided (see below)

Steps to Reproduce

  1. clone example repository
  2. grails run-app
  3. curl http://localhost:8080/test/something?someState=
  4. or ./gradlew test

Expected Behaviour

I don't see why the given example should not work.

Actual Behaviour

Grails application running at http://localhost:8080 in environment: development
2021-11-22 21:43:37.729 ERROR --- [nio-8080-exec-3] o.g.web.errors.GrailsExceptionResolver   : IllegalArgumentException occurred when processing request: [GET] /test/something - parameters:
someState: 
No enum constant myapp.utils.UIState.SomeState.. 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:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	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.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalArgumentException: No enum constant myapp.utils.UIState.SomeState.
	at java.base/java.lang.Enum.valueOf(Enum.java:240)
	... 15 common frames omitted

Environment Information

  • Operating System: Windows 11 / Ubuntu 18.04 running in WSL
  • Grails Version: 4.0.12 / 5.0.1
  • JDK Version: 11

Example Application

https://github.com/davidkron/grails-strange-controller-action-problem

davidkron avatar Nov 22 '21 21:11 davidkron