Using grails-micronaut will not let you run java --jar build/libs/app.jar
Expected Behavior
That I can start a vanilla app with the org.apache.grails:grails-micronaut plugin.
It will run using
./gradlew bootRun
Actual Behaviour
When I create a vanilla Grails app in forge, and try to run it, I get the following exception:
io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.micronaut.context.event.ApplicationEventPublisher<io.micronaut.context.event.StartupEvent>] exists.
at io.micronaut.context.DefaultBeanContext.newNoSuchBeanException(DefaultBeanContext.java:2804)
at io.micronaut.context.DefaultApplicationContext.newNoSuchBeanException(DefaultApplicationContext.java:338)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:2767)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1781)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:855)
at io.micronaut.context.BeanLocator.getBean(BeanLocator.java:97)
at io.micronaut.context.DefaultBeanContext.publishEvent(DefaultBeanContext.java:1867)
at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:368)
at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:225)
at io.micronaut.spring.boot.starter.MicronautImportRegistrar.registerBeanDefinitions(MicronautImportRegistrar.java:128)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromRegistrars$1(ConfigurationClassBeanDefinitionReader.java:409)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
Steps To Reproduce
grails-forge-cli create-app --servlet=tomcat --jdk=17 --gorm=hibernate --test=spock --features=grails-micronaut com.example.app.grails-micronaut-app
cd grails-micronaut-app
./gradlew assemble
java -jar build/libs/grails-micronaut-app-0.1.war
Environment Information
- OS: Ubuntu 24.04
- JDK 17.0.15-librca
Example Application
https://github.com/sbglasius/grails-micronaut-app
Version
7.0.1
Same here: groovy: 2.2.2, spock: 0.7-groovy-2.0
I need it to be working in the same way, as I'm mocking collaborators and with GroovyMock
they evaluate to false, and throw exceptions. For now I'll use regular mocks.
Reported by janusz.slota on 2014-04-28 17:22:35
Example test http://meetspock.appspot.com/script/5700735861784576
Reported by janusz.slota on 2014-04-28 17:28:47
Why is your test depending on the truthiness of a mock object? What's the use case?
Reported by pniederw on 2014-04-28 17:31:12
This will do the trick:
def groovyMock = GroovyMock(Map) { asBoolean() >> true }
Perhaps this should be the default. Not sure.
Reported by pniederw on 2014-04-28 17:33:29
void initialize() {
if( ! config) {
throw new RuntimeException('configuration has not been injected')
}
// ... initialize logic
}
I'm not saying it's good design to have initialize method, but it'll work for now.
However GroovyMock config object injected via constructor evaluates to false. Using
Mock, it's OK.
Reported by janusz.slota on 2014-04-28 17:35:22
I see. Thanks for the explanation.
By the way, GroovyMock() should only be used where Mock() isn't good enough.
Reported by pniederw on 2014-04-28 17:37:27
>> def groovyMock = GroovyMock(Map) { asBoolean() >> true }
Great - thanks for reply. Works perfectly :-)
Reported by janusz.slota on 2014-04-28 17:39:11
I see I used the elvis operator so that's probably the specific case I ran into at the
time. I suspect I was doing some kind of lookup and found a GroovyMock instance but
instead I got the value on the right side of the operator.
I don't like having to explicitly define this kind of behavior or the explicit Object
type on the groovy mock or be forced to use null checking instead of the elvis operator.
As for preferring GroovyMock instead of Mock. I understand why you may feel that way
but I do prefer the dynamic aspect of GroovyMock in some cases. Much like how Brian
Marick uses dynamic mocks in his Robozzle kata. (http://vimeo.com/19404746)
Does it not make more sense for Mock and GroovyMock to behave the same way?
Reported by [email protected] on 2014-04-28 18:28:07
Should this issue still be open?
Well, the behavior at least is still the same. It's just the question whether this should be changed or not.
I personally tend to say the behavior is fine, that's just the difference between Java and Groovy objects. The Java object does not respond to asBoolean so truthy means non-null, the Groovy object responds to asBoolean, so it is used and as mock object answers with false by default.
Yes, 10 years is a long time to live with the behaviour if it's so bad. I imagine that it violates the principle of least surprise, though. Would there be a way to fix it? i.e. is it possible to detect Java objects and use a Groovy wrapper or something to respond in the same way as a Groovy object?
Any behavior different of the current one would for me violate the principle of least surprise to be honest.
Yes, at this point, I suppose it would. This leads me to the conclusion that this issue is a will-not-fix.