Skip to content

Conversation

@codeconsole
Copy link
Contributor

The Problem

Caused by: java.lang.IllegalStateException: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@48300ca8 has not been refreshed yet
        at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1262)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1280)
        at org.grails.web.context.ServletEnvironmentGrailsApplicationDiscoveryStrategy.findGrailsApplication(ServletEnvironmentGrailsApplicationDiscoveryStrategy.groovy:54)
        at grails.util.Holders.findApplication(Holders.java:126)
        at org.grails.plugins.web.controllers.api.ControllersDomainBindingApi.autowire(ControllersDomainBindingApi.java:90)
        at org.grails.plugins.web.controllers.api.ControllersDomainBindingApi.initialize(ControllersDomainBindingApi.java:50)
        at com.pixoto.community.CategoryParticipant.<init>(CategoryParticipant.groovy)
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
        ... 43 common frames omitted

This is only an issue during a Spring Dev Tools restart, but this fixes the issue.

  this.resource = resource.getDeclaredConstructor().newInstance() as GormAllOperations<T>

results in a domain object instantiation during the constructor, which:

  1. Triggers Grails GORM enhancements
  2. Calls ControllersDomainBindingApi.initialize()
  3. Tries to access Holders.findApplication()
  4. Fails during DevTools restart when ApplicationContext is being switched

The Fix

Lazy initialize the resource

@codeconsole codeconsole marked this pull request as draft November 1, 2025 20:34
@codeconsole codeconsole marked this pull request as ready for review November 1, 2025 22:12
@codeconsole
Copy link
Contributor Author

codeconsole commented Nov 1, 2025

@matrei if you recall, we did this this.resource = resource.getDeclaredConstructor().newInstance() as GormAllOperations<T> so we could @CompileStatic

but I think it is best to keep resource a Class<T> for 2 reasons:

  1. Simplify the DomainServiceLocator lookup
  2. Keep in line with

Also, I found it unnecessary to instantiate an instance if we separate GormAllOperations<T> and Class<T>

class GormService<T extends GormEntity<T>> {

GormAllOperations<T> resource
private GormAllOperations<T> gormStaticApi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field is now private, while it was public before. This is a breaking change for a non-major release ...

Copy link
Contributor Author

@codeconsole codeconsole Nov 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdaugherty this is something that is not documented that nobody uses, but I have no problem removing private. done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell, there was no gormStaticApi property before this change, so it should be private as it is lazily instantiated in the getter.

However, the resource property has changed type, which is breaking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we renamed the field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I think it is best to keep resource a Class for 2 reasons:

@matrei @jdaugherty I explained my rational for the name change in the comment above

class GormService<T extends GormEntity<T>> {

GormAllOperations<T> resource
private GormAllOperations<T> gormStaticApi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell, there was no gormStaticApi property before this change, so it should be private as it is lazily instantiated in the getter.

However, the resource property has changed type, which is breaking.

@jdaugherty jdaugherty modified the milestones: grails:7.0.2, grails:7.1.0 Nov 5, 2025
@codeconsole codeconsole changed the base branch from 7.0.x to 7.1.x November 6, 2025 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants