jakartaee / faces

Jakarta Faces
Other
109 stars 55 forks source link

Missing Generics in Faces Standard Converters #1822

Closed pizzi80 closed 3 months ago

pizzi80 commented 1 year ago

The Faces API interface for converters is Converter<T> since JSF 2.3 (2015/2017)

After 8 years from these commits and 20 years from the introduction of generics in Java I think that it's more a bug than a feature to develop without Generics

https://arjan-tijms.omnifaces.org/p/jsf-23.html#1355

Both the Converter and Validator interfaces in JSF take an Object as their input value. Implementations then typically demand that this Object is of a specific type and that otherwise an exception should be thrown.

This contract predates generics and instead of demanding such type constraint via JavaDoc one can far better express this via a generic parameter. In JSF 2.3 both interfaces have now been parameterized and implementations can concisely define the exact input type, and in case of the Converter interface additionally the exact return type.

This updated interfaces are shown below:

public interface Converter<T> {
  T getAsObject(FacesContext context, UIComponent component, String value);
  String getAsString(FacesContext context, UIComponent component, T value);
}
public interface Validator<T> {
  void validate(FacesContext context, UIComponent component, T value);
}

Note that the myriad of existing Converter and Validator implementations in JSF have not been parameterized and are raw types. The reason for this is backwards compatibility.

E.g. in some obscure but possible cases code could actually depend on passing an Object to some Converter implementation. Even when such Object could only be of say type Foo, then actually typing the constructor as accepting only Foo will not compile anymore. A variety of other even more obscure but theoretical possible incompatibilities were discovered as well. One could ask how generics can ever have been introduced in the JDK itself for existing types, but even there some compromises were made (like the infamous Map#get taking an Object as input instead of the generic parameter for the key).

New converters and validators can of course take advantage of the new generic parameters, but existing ones in JSF have been frozen in time and can never change.

Commits for this feature have been done between 30/jul/15 and 18/aug/15.

pizzi80 commented 1 year ago

https://github.com/eclipse-ee4j/mojarra/pull/5259

tandraschko commented 1 year ago

+1

@BalusC / @arjantijms 4.1?

BalusC commented 1 year ago

+1

BalusC commented 1 year ago

Breaking change, make it 5.0.

tandraschko commented 4 months ago

i appled those changes to myfaces now i just didnt change the EnumConverter constructor for now as there are multiple ways of doing it: 1) like OmniFaces, getting the Enum Class in getAsString and remember 2) extracting from the value expression

which one is better and less error prone? I will create a new issue for it: #1938

tandraschko commented 4 months ago

https://github.com/apache/myfaces/commit/15cc2cf62824203a70460e8a2279b1df5a06bc05