Reputation: 3
I am trying to do some "custom lightweight" JSF component binding. In my bean (controlling some JSF page) i'm declaring a HahsMap where keys ranging over my h:inputText
ids (appearing in the page) map these ids to custom HInputText<T>
objects (T
in the example given below is Long). Then i am using HInputText<T>
objects to hold a subset of corresponding h:inputText attributes : value
supposed to be of type T
, rendered
, required
, etc. In this direction fields from the HInputText<T>
objects give values to the h:inputText
attributes.
My problem is that when using such an h:inputText
inside a h:form
, JSF validation does not take place : i can type alphanumeric chars in the h:inputText
(supposed to hold a Long value) and my form submits without showing any errors. Note that required
and rendered
attributes are managed correctly (since required
is set to true, i have an error when i leave the h:inputText
field empty) and that when i try to display back the value of the h:inputText
in the page using some h:outputText
the alphanumeric chars are displayed.
Is there some trick to make JSF validation work without having to explicitly define a custom Validator for each h:inputText
?
HInputText.class:
public class HInputText<T>
{
private String id;
private boolean rendered;
private boolean required;
private T value;
private Class<T> myClass;
// getters and setters for all fields
public HInputText(Class<T> myClass, String id)
{
this.myClass = myClass;
this.id = id;
this.rendered = true;
this.required = true;
}
}
Code snippet from my Managed Bean :
@ManagedBean(name="saisieController")
@SessionScoped
public class SaisieController
{
...
private HashMap<String,HInputText<Long>> htagLongInputTexts;
public HashMap<String, HInputText<Long>> getHtagLongInputTexts()
{
return htagLongInputTexts;
}
public void setHtagLongInputTexts(HashMap<String, HInputText<Long>> hLongInputTexts)
{
this.htagLongInputTexts = hLongInputTexts;
}
public void addHtagLongInputText(HInputText<Long> hLongInputText)
{
getHtagLongInputTexts().put(hLongInputText.getId(), hLongInputText);
}
public HInputText<Long> getHtagLongInputText(String hLongInputTextId)
{
return(getHtagLongInputTexts().get(hLongInputTextId));
}
@PostConstruct
public void init()
{
setHtagLongInputTexts(new HashMap<String, HInputText<Long>>());
addHtagLongInputText(new HInputText<Long>(Long.class, "HIT_LongTestHIT"));
}
public String doNothing()
{
return null;
}
}
and finally a snippet from my jsf page:
<h:form>
<h:inputText
id = "HIT_LongTestHIT"
value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}"
rendered = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].rendered}"
required = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].required}"
/>
<h:message for = "HIT_LongTestHIT" styleClass = "error-text" />
<h:commandButton value = "submit" action = "#{saisieController.doNothing()}" />
<h:outputText value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}" />
</h:form>
Upvotes: 0
Views: 791
Reputation: 1108642
Is there some trick to make JSF validation work without having to explicitly define a custom Validator for each h:inputText?
No, that's not possible. Due to type erasure the generic type information is not available during runtime. JSF/EL has no idea that T
is actually a Long
, let alone that there's actually some T
. You really need to explicitly specify a converter which is in this particular example the LongConverter
with a converter ID of javax.faces.Long
.
<h:inputText ... converter="javax.faces.Long">
or, dynamically so you want
<h:inputText ...>
<f:converter converterId="#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].converterId}" />
</h:inputText>
You can find an overview of all available standard JSF converters in the javax.faces.convert
package summary. You can find out their converter IDs by navigating to the Constant field values link on the public constant CONVERTER_ID
.
Upvotes: 0