hk2166 opened a new pull request, #16687:
URL: https://github.com/apache/grails-core/pull/16687

   ## Description
   
   ### Cause
   `META-INF/spring.schemas` maps 
`http://grails.org/schema/context/grails-context.xsd` to 
`org/grails/spring/context/annotation/grails-context.xsd`, but the file was 
under `grails-core/src/main/groovy`, which the build does not package. It was 
missing from the `grails-core` jar, so a schema-validated parse of 
`<grails:component-scan>` could not resolve the schema from the classpath and 
fell back to fetching it from grails.org.
   
   Packaging it is not enough on its own. The XSD declared 
`targetNamespace="http://www.grails.org/schema/context"`, while 
`spring.handlers`, `spring.schemas` and `CoreGrailsPlugin` all use 
`http://grails.org/schema/context`. With the file packaged, a validated parse 
fails with:
   
   ```
   TargetNamespace.1: Expecting namespace 'http://grails.org/schema/context', 
but the target namespace of the schema document is 
'http://www.grails.org/schema/context'.
   ```
   
   ### Fix
   - The XSD moves from `src/main/groovy` to `src/main/resources`, under the 
same package path, so `spring.schemas` is unchanged. It was the only non-source 
file under any `src/main/groovy` in the repository, so this needs no 
build-script change. A `processResources` include, as suggested in the issue, 
would work too if you prefer it.
   - The XSD's `targetNamespace` (and its default `xmlns`) is now 
`http://grails.org/schema/context`. No working document can have used the `www` 
URI, because Spring has no namespace handler registered for it. 
`CoreGrailsPlugin` declares `component-scan` through BeanBuilder, which does 
not validate, so it is unaffected. A spec below covers that path.
   
   Once this is merged forward, the spec in #16586 that parses 
`<grails:component-scan>` with validation off could validate against the schema 
again.
   
   ### Branch
   This targets `7.0.x`, the oldest maintained branch with the problem. 7.1.x 
through 9.0.x are the same. I asked on #16635 which branch you'd prefer, given 
that 7.0.x reaches end of support on Oct 31, and I'm happy to retarget this to 
7.2.x or 8.0.x.
   
   ### Coverage
   New `GrailsContextSchemaSpec` in `grails-core`:
   - The schema location resolves through `META-INF/spring.schemas` from the 
classpath.
   - The schema declares the namespace that `GrailsContextNamespaceHandler` is 
registered for, resolved through `DefaultNamespaceHandlerResolver`.
   - An XSD-validated `XmlBeanDefinitionReader` parse of 
`<grails:component-scan>` succeeds. The spec's entity resolver only resolves 
from the classpath, so a schema that isn't packaged fails the spec instead of 
being fetched over the network. The Grails scanner only scans the project's 
classes directory (`BuildSettings.CLASSES_DIR`), so the spec checks for the 
annotation config processors that parsing the element registers, not for 
scanned beans.
   - The BeanBuilder DSL that `CoreGrailsPlugin` uses can still declare 
`grailsContext.'component-scan'`. `CoreGrailsPluginTests.testComponentScan` 
would cover this, but it never runs (#16671).
   
   | Spec feature | Original code | XSD moved only | Moved + namespace fixed |
   |---|---|---|---|
   | Schema resolves from the classpath | fails | passes | passes |
   | Schema declares the handler's namespace | fails | fails | passes |
   | Validated parse of `<grails:component-scan>` | fails | fails | passes |
   | BeanBuilder `component-scan` | passes | passes | passes |
   
   Run locally (JDK 17):
   - `./gradlew :grails-core:test`: 512 tests, 0 failures.
   - `./gradlew codeStyle`: no violations.
   - The built `grails-core` jar contains 
`org/grails/spring/context/annotation/grails-context.xsd` with the corrected 
namespace.
   - Not run: `./gradlew build --rerun-tasks` for the whole repository.
   
   No documentation change. The guide does not mention this namespace.
   
   Fixes #16635
   
   **Use of generative AI:** the change, the spec and this description were 
prepared with [Claude Code](https://claude.com/claude-code) (Claude Opus 5.5), 
and the commit carries a `Co-Authored-By` trailer for it, per the ASF policy on 
generative tooling.
   
   ## Contributor Checklist
   
   Please review the following checklist before submitting your pull request. 
Pull requests that do not meet these requirements may be closed without review.
   
   ### Issue and Scope
   
   - [x] This PR is linked to an existing issue that has been **acknowledged or 
approved** by the project team. If no approved issue exists, please give 
background on why this change is necessary.  Tickets are preferred for release 
change log history.
   - [x] This PR addresses the **complete scope** of the linked issue. Partial 
implementations or unfinished work should not be submitted for review.
   - [x] This PR contains a **single, focused change**. Unrelated changes 
should be submitted as separate pull requests.
   - [x] This PR targets the **correct branch** for the type of change:
       - **Patch release branches** (e.g., `7.0.x`): Bug fixes only. No new 
features or API changes.
       - **Minor release branches** (e.g., `7.1.x`): New features are welcome, 
but breaking existing APIs must be avoided.
       - **Major release branches** (e.g., `8.0.x`): Reserved for major 
changes. Breaking API changes are permitted.
   
   ### Code Quality
   
   - [x] I have **added or updated tests** that cover the changes introduced in 
this PR. All code contributions are expected to include appropriate test 
coverage.
   - [ ] I have verified that all existing tests pass by running `./gradlew 
build --rerun-tasks`. *(Ran the full `grails-core` suite instead; see 
Coverage.)*
   - [x] My code follows the project's **code style** guidelines. I have run 
`./gradlew codeStyle` and resolved any violations. See [Code 
Style](../CONTRIBUTING.md#code-style) for details.
   - [x] This PR does **not** include mass reformatting, style-only changes, or 
large-scale refactoring unless it was **explicitly approved** in the linked 
issue. Unsolicited reformatting will not be accepted.
   - [x] If generative AI tooling was used in preparing this contribution, a 
quality model was used to ensure contributions are **consistent with the 
project's quality standards**.
   
   ### Licensing and Attribution
   
   - [x] All contributed code is provided under the [Apache License 
2.0](https://www.apache.org/licenses/LICENSE-2.0), and new source files include 
the appropriate **Apache license header**.
   - [ ] I have the necessary rights to submit this contribution and confirm it 
is my own original work (see [Legal 
Notice](../CONTRIBUTING.md#i-want-to-contribute)).
   - [x] If generative AI tooling was used in preparing this contribution, I 
have followed the [Apache Software Foundation's policy on generative 
tooling](https://www.apache.org/legal/generative-tooling.html) and have 
properly attributed its use.
   
   ### Documentation
   
   - [x] If this PR introduces user-facing changes, I have included or updated 
the relevant documentation.
   - [x] If this PR adds a new feature, I have updated the **What's New** 
section of the Grails Guide.
   - [x] If this PR introduces breaking changes or changes that require user 
action during an upgrade, I have updated the **Upgrade Notes** for the 
corresponding version in the Grails Guide.
   - [x] The PR description clearly explains **what** was changed and **why**.
   
   ---
   
   > **First-time contributors:** Please read our [Contributing 
Guide](../CONTRIBUTING.md) before submitting.
   > Pull requests that appear to be auto-generated, incomplete, or unrelated 
to an approved issue may be
   > closed to help maintainers focus on reviewed and planned work. We 
appreciate your understanding.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
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]

Reply via email to