jdaugherty commented on PR #15841:
URL: https://github.com/apache/grails-core/pull/15841#issuecomment-4910950125
Removing the yakworks library completely revealed a change that's probably
significant. Here's what AI said:
I found the root cause. ProfileServiceSpec isn't the real failure — it's
collateral damage from a genuine behavioral regression in the PR.
The failure chain
1. RegisterSpec.testRegisterAndForgotPassword fails first (the real
failure). It registers a user, creates a profile, then calls
ProfileListPage.editProfile(un), which looks up the edit link with the Geb
selector $('a', text: "User(username:$username)") — matching on the rendered
toString of the user.
2. Because RegisterSpec dies at that step, its own cleanup (delete profile,
delete user at the end of the same feature) never runs, leaving a committed
extra User and Profile.
3. That leftover row is exactly why ProfileServiceSpec > test count sees 5
instead of 4, and why UserSpec > testFindAll (user search results) fails too.
The regression
The profile list GSP renders the association directly: ${entry.user}
(grails-app/views/profile/index.gsp:52), where profile.user is a lazy Hibernate
proxy. The User domain has @ToString(includes='username', includeNames=true,
includePackage=false), so the page used to render User(username:test_user_...).
This PR's new GroovyProxyInterceptorLogic.handleUninitialized()
(grails-data-hibernate5/.../GroovyProxyInterceptorLogic.java:68-70)
short-circuits toString() on an uninitialized proxy and returns entityName +
":" + id — e.g. test.User:5 — without initializing the proxy or calling the
entity's real toString(). And since HibernateMappingContextConfiguration now
auto-registers the Groovy-aware proxy factory for every hibernate5 app, the
spring-security extended app silently switched behavior: the page now renders
test.User:5, the selector matches nothing, and the spec fails
deterministically. The behavior is even pinned by the PR's own test
(GroovyProxyInterceptorLogicSpec asserts "Book:1").
My recommendation
Remove (or rethink) the toString() short-circuit. Rendering
${someEntity.association} in a GSP is an extremely common pattern in real
Grails apps, and stock Hibernate semantics — initialize the proxy and delegate
to the entity's real toString() — is what every existing app depends on. The
lazy-toString behavior was inherited from yakworks' design, but yakworks was
opt-in; this factory is now the global default. The id/metaClass/ident()
interceptions are the valuable part of the fix and don't have this
compatibility problem.
The concrete change: drop the TO_STRING branch from handleUninitialized in
the h5 GroovyProxyInterceptorLogic (and the equivalent in h7 if it does the
same — worth checking GrailsBytecodeProvider/interceptor there), update
GroovyProxyInterceptorLogicSpec, and add an assertion that toString()
initializes and returns the real value.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]