Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jackson Errors in /env actuator if Closures defined in application.groovy #10279

Open
robertoschwald opened this issue Oct 27, 2016 · 7 comments

Comments

@robertoschwald
Copy link

robertoschwald commented Oct 27, 2016

When you define a closure in application.groovy, Jackson fails in the /env endpoint.

Steps to reproduce

Create a standard Grails 3.1.13 project, which only has the following things changed:

  • enable the endpoints in application.yml
  • define the grails.gorm.default.mapping closure
  • access /env in the application.

Stacktrace

Caused by: com.fasterxml.jackson.databind.JsonMappingException: 
No serializer found for class groovy.lang.GroovyClassLoader$1 and no properties discovered to
 create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) 
(through reference chain: java.util.LinkedHashMap["applicationConfig: 
[classpath:/application.groovy]"]->java.util.LinkedHashMap["grails.gorm.default.mapping"]-
>_run_closure1["delegate"]->script14775830011902070609279["binding"]-
>groovy.util.ConfigBinding["callable"]->groovy.util._parse_closure6["delegate"]-
>groovy.util.ConfigSlurper["classLoader"]->groovy.lang.GroovyClassLoader["resourceLoader"])
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69)
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:561)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:469)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:29)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:561)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:469)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:29)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
    at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1387)
    at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:889)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:269)
    ... 19 common frames omitted

Expected Behaviour

  • Jackson does not fail on application.groovy when using the env activator endpoint

Actual Behaviour

  • Exception occurs (see above)

Environment Information

  • Operating System: OSX 10.12.1
  • Grails Version: 3.1.13 (also tested with 3.0.10, same problem)
  • JDK Version: 1.8.0_91 ORACLE
  • Container Version (If Applicable): embedded, default.

Example Application

https://github.com/robertoschwald/grails3-actuator-jackson-error

Just run it and access /env

@graemerocher
Copy link
Member

Not sure if there is anything we can do about this really. The endpoint is part of Boot and the issue may need to be reported there.

@robertoschwald
Copy link
Author

Is it possible to either workaround that in Grails somehow, or provide the required serializer (or a NOOP error serializer) for this issue?

@graemerocher
Copy link
Member

Will see what we can do

@wilkinsona
Copy link

wilkinsona commented Oct 28, 2016

Not sure if there is anything we can do about this really. The endpoint is part of Boot and the issue may need to be reported there.

On the other hand, the logic that's "polluting" the Environment with a Groovy closure is part of Grails so it could be argued that Grails should ensure that things are sanitised such that Jackson can serialise them, or that it has customised the Actuator's ObjectMapper such that it can serialise the closure. If Boot is lacking the hook points to let you do that then we can see if we can add them.

@graemerocher
Copy link
Member

@wilkinsona Yes that could be argued. However, Grails for years has allowed richer configuration with closures to for example configure the default constraints and mapping in GORM http://gorm.grails.org/latest/hibernate/manual/index.html#_the_default_mapping_constraints

This issue would also impact use of GORM standalone outside of Grails if you were to use it in Spring Boot as is now possible http://gorm.grails.org/latest/hibernate/manual/index.html#springBoot

However, yes we can of course fix it only for Grails if the hook is available to do this. Configuration of GORM when using it standalone with Spring Boot would continue to be an issue.

@graemerocher
Copy link
Member

@wilkinsona currently we have dependency on Grails to Actuator itself. Is there a way to fix this problem without introducing a dependency on Actuator?

@wilkinsona
Copy link

Is there a way to fix this problem without introducing a dependency on Actuator?

I don't know, as I don't know what's required to fix the problem. I'm guessing a Jackson module might work but a bit of Googling hasn't turned up anything. If we can figure out how to fix the problem then hopefully it'll become obvious where that fix should go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants