jakartaee / jakartaee/faces

Specify the runtime mechanism for obtaining the @FacesDataModel registry (currently implementation-invented)

Open
#2,184 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
127
Forks
59
Avg merge
23h
Merged PRs (30d)
7

Description

Background

Since Faces 2.3, @FacesDataModel lets applications register custom DataModel wrappers. The jakarta.faces.model.FacesDataModel javadoc specifies the behavior in detail — the runtime must maintain a collection of these DataModels, UIData (and other components) must query it for the most-specific wrapper of a value's type, and it defines the inheritance-based sorting/selection algorithm.

What the spec does not define is the mechanism: how a component actually obtains that collection (or a wrapper from it) at runtime.

Problem

Because the mechanism is unspecified, each implementation invented its own — and they're mutually incompatible, both in identifier and in shape:

  • Mojarra: jakarta.faces.component.UIData queries the CDI BeanManager for a bean by a well-known name (historically the internal string comSunFacesDataModelClassesMap, now an impl constant), which yields a Map<Class<?>, Class<? extends DataModel<?>>>; UIData itself performs the most-specific-match selection.
  • MyFaces: jakarta.faces.component.UIData reflectively loads the impl class org.apache.myfaces.cdi.model.FacesDataModelManager by FQN and invokes a static createDataModel(FacesContext, Class, Object); selection happens inside the impl manager.

Consequences:

  • The well-known identifier is an undocumented contract that each impl must invent, guess, and duplicate across its API-level component code and its provider — on both sides of the API/impl module boundary.
  • No portable way exists for components (or third-party libraries) to obtain the registry; code written against one impl's mechanism won't work on the other.
  • The behavior is interoperable but the mechanism is not, which undercuts the point of standardizing @FacesDataModel in the first place.
Proposal

Define the lookup as a CDI contract in the specification. CDI is already the extension mechanism for @FacesDataModel (CDI discovers the annotated beans, the registry is built by a CDI extension, and UIData already requires CDI.current() to resolve it), so CDI itself is the SPI here — no additional factory interface is warranted. MyFaces' reflective class-load is precisely a workaround for the missing spec-defined CDI name; standardizing the name removes the reason that workaround exists.

Specifically, specify:

  • a stable, spec-owned bean name (and/or qualifier) for the registry — e.g. a constant FacesDataModel.DATA_MODEL_CLASSES_MAP_NAME = "jakarta.faces.DATA_MODEL_CLASSES_MAP";
  • the bean type: Map<Class<?>, Class<? extends DataModel<?>>>;
  • the semantics: sorted by inheritance (subclasses before superclasses) exactly as already described in FacesDataModel, so a component iterating it finds the most-specific match.

The runtime produces this bean; components (and third-party libraries) obtain it via the standard BeanManager, with no impl-specific identifier and no reflective class-loading. Implementations reference the one spec-defined constant instead of duplicating a private literal across the API/impl boundary.

Notes
  • This formalizes existing, shipping behavior — it standardizes a contract both implementations already satisfy (differently), so the risk is low and it's largely additive.
  • Mojarra recently moved off its legacy com.sun.faces-flavored bean name and currently uses an internal jakarta.faces.DATA_MODEL_CLASSES_MAP constant with a TODO noting it should be spec-defined; this issue is the upstream follow-through.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the jakarta.faces.model.FacesDataModel javadoc and the UIData implementations in Mojarra and MyFaces, comparing their registry lookup mechanisms. Define the spec-owned CDI bean name, Map type, and inheritance-order semantics so components and third-party libraries can obtain the registry portably without implementation-specific identifiers or reflective class loading.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.