Resource name with a query string is forbidden by the identifier grammar and required by the TCK
- Dominant language
- Java
- Stars
- 127
- Forks
- 59
- Avg merge
- 23h
- Merged PRs (30d)
- 7
Description
Discovered while analyzing eclipse-ee4j/mojarra#5969.
A resource name carrying a query string, as in ``, is forbidden by the resource identifier grammar, contradicted by the renderer algorithm, and simultaneously required by the TCK. All three cannot be right.
### What the specification says
Section 2.6.1.3 "Resource Identifiers" defines `[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]` and states that the valid characters for every segment, `resourceName` included, are XML NameChar excluding the path separator and `:`, with `resourceName` additionally allowed to contain the path separator. Neither `?` nor `=` is an XML NameChar. The same section requires that an identifier which does not follow these rules "must not be considered valid and must be ignored silently".
The Standard HTML RenderKit documentation, "Common Algorithm for Obtaining A Resource to Render", requires the resource renderers to look up the `name` attribute, look up the `library` attribute, and "create the resource by calling `Application.getResourceHandler.createResource(name, library)`" — that is, with the attribute value verbatim.
The only place the specification contemplates a query string at all is on the other end: the Script renderer's encode behavior (`changed_modified_2_1`, and the same clause on the Stylesheet renderer since `changed_modified_5_0`) says "Call `resource.getRequestPath()`. If the result contains a query string, take care to handle it correctly." That is about the `?ln=…&loc=…&con=…` which `getRequestPath()` itself produces, not about a query string in the name.
### What the TCK requires
`ee.jakarta.tck.faces.faces22.render_kit.Issue2172IT`, over fixture `issue2172.xhtml` containing ``, asserts that the rendered resource URL contains `ln=alibrary`, `v=1` and an escaped ampersand. An implementation that treats the name as an invalid resource identifier and ignores it silently, as 2.6.1.3 requires, fails this test.
`ee.jakarta.tck.faces.faces22.ajax_lifecycle.Issue4345IT` likewise drives `` and asserts the query string reaches the DOM unescaped. Its fixture carries the comment "h:outputStylesheet does not support params in the URL, so generate a similar link manually", with the stylesheet variant commented out — the TCK's own record that the behavior was never consistent.
### What implementations do
Both implementations support the extension, in implementation-specific places, and neither documents it in the VDL docs, where the `name` attribute of `h:outputScript`, `h:outputStylesheet` and `h:graphicImage` is described only as "The resourceName for this resource".
Mojarra splits the name at `?` in one place, `ScriptStyleBaseRenderer`, and re-appends the query to the request path. Every other consumer of the name sees it verbatim, which is what eclipse-ee4j/mojarra#5969 is about.
MyFaces splits at `?` in four places: `HtmlScriptRenderer`, `HtmlStylesheetRenderer`, `PartialViewContextImpl` and `FaceletsViewDeclarationLanguageUtils`.
Consequently `h:outputScript` and `h:outputStylesheet` accept a query string in the name on both implementations, while `h:graphicImage` and `#{resource['lib:name?v=1']}` do not, on either.
### Why users write this in the first place
The only versioning mechanism the specification offers is the `resourceVersion` segment, which requires a directory per resource with the version as the leaf file name (`resources/css/theme.css/1_0.css`). That cannot express a build-generated content hash without restructuring the output of every asset pipeline, so users reach for `?v=` instead. Whatever is decided below, a supported per-resource cache busting mechanism would remove the motivation for the extension entirely.
### Proposal
Decide one way and make all three artifacts agree.
Bless it: state in 2.6.1.3 that a `resourceName` may carry a trailing query string introduced by `?`, that the query string is not part of the resource identifier and is removed before the resource is resolved, that it is appended to the value returned by `Resource#getRequestPath()`, and that the resource name used as key for `ResourceHandler#markResourceRendered` and `#isResourceRendered` is the name without the query string. Amend "Common Algorithm for Obtaining A Resource to Render" accordingly, and state whether the extension applies to every tag taking a `name` attribute or only to the script and stylesheet renderers — today it is the latter, in both implementations, which is the more surprising of the two options.
Or drop it: remove `Issue2172IT` and the query string part of `Issue4345IT`, and let implementations return `RES_NOT_FOUND` for such a name as 2.6.1.3 already requires, but this will break existing apps which relied on impl-specific behavior.
🤖 Generated with Claude Opus 5
Contributor guide
Research direction
Start by reviewing the Resource Identifiers section, the Common Algorithm for Obtaining A Resource to Render, and TCK tests Issue2172IT and Issue4345IT. Compare the named Mojarra and MyFaces renderer behavior, then determine the agreed direction. Done requires the specification, TCK coverage, and implementation behavior to consistently support or reject query strings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend-api-design, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100