apache / apache/grails-core

Consolidate the reflection utility classes into grails-common

Open
#16,326 0 comments 0 reactions 0 assignees View on GitHub
type: improvement
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

Follow-up to https://github.com/apache/grails-core/pull/16296, where @jdaugherty pointed out that the repo carries several `ReflectionUtils`-shaped classes and asked for one shared home rather than another copy.

That PR added `org.apache.grails.common.reflect.ReflectionUtils` in **grails-common** for the non-public bean access it needed, and deliberately stopped there. This issue covers the rest of the consolidation, which is a cross-module public-API change and was kept out of a bug fix on the 8.0.0 timeline.

## What exists today

| Class | Module | Notes |
|---|---|---|
| `org.grails.datastore.mapping.reflect.ReflectionUtils` | grails-datastore-core | **public, `@since 1.0`, published.** `makeAccessible(Field)`, `makeAccessible(Method)`, `isAssignableFrom`, `instantiate`, `getPropertiesOfType`, `isGetter`, `isSetter`, `forName`. 8 internal call sites |
| `org.grails.datastore.gorm.utils.ReflectionUtils` | grails-datamapping-core | one method: `isMethodOverriddenFromParent(Method)` |
| `grails.plugin.cache.util.ClassUtils` | grails-cache | `getPropertyOrFieldValue(Object, String)`, delegates to Spring |
| `grails.util.GrailsClassUtils` | grails-core | public `grails.*` API; carries the property/field accessor helpers |
| `org.apache.grails.common.reflect.ReflectionUtils` | grails-common | added by #16296 |

The 8 call sites of the grails-datastore-core one live in grails-datastore-core, grails-datamapping-core and grails-datamapping-rx. No test references it — every `ReflectionUtils` in `src/test` resolves to Spring's.

## Proposed

1. Move `org.grails.datastore.mapping.reflect.ReflectionUtils` into `org.apache.grails.common.reflect`, merging it with the class added by #16296.
2. Leave a deprecated delegating class at the old FQCN. It is published and public since 1.0, so external GORM plugins may well be compiling against it; removing it outright is a binary-compatibility break.
3. Repoint the 8 internal call sites.
4. Fold in the others where it makes sense: `org.grails.datastore.gorm.utils.ReflectionUtils`, `grails.plugin.cache.util.ClassUtils`, and the accessibility helpers on `grails.util.GrailsClassUtils` (that one is `grails.*` public API, so it needs the same deprecation treatment rather than a move).
5. Note that grails-common must not depend on grails-core (its build file says so), and exposes `spring-core` as `implementation` only — so anything moved there must not put a Spring type in a method signature.

## Also worth revisiting here

`grails-views-core` (`WritableScriptTemplate`) and `grails-views-gson` (`DefaultHalViewHelper`) do their own `setAccessible` widening. If the shared utility is the one home for this, those are candidates to repoint too.

## Removal of the workaround

Separately, `org.apache.grails.common.reflect.ReflectionUtils.warnOnNonPublicClass` exists so that the non-public-class handling added in #16296 is visible and can be withdrawn if Groovy stops compiling anonymous inner classes as non-public. Whoever picks this up should keep that seam intact rather than quietly absorbing it.

Contributor guide

Open the contributing guide

Research direction

Start with org.apache.grails.common.reflect.ReflectionUtils, the grails-common build file, and the listed ReflectionUtils and GrailsClassUtils classes across the affected modules. Trace the 8 grails-datastore-core call sites and review the views helpers, checking existing API and dependency constraints. Done means the shared utility covers the agreed cases, callers use it, and published old APIs remain compatible and deprecated.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, spring
Domain
tooling
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.