At first I tried with just the 'required' attribute, but as it never seems to be checked, I added an extremely simple validator which checks the length of the 'color' property... but nothing seems to work. In the same form I have other inputText required components which are correctly checked when I press the commandButton.
I have the following code:
<p:colorPicker id="color" value="#{backBean.color}" required="true" requiredMessage="Required!" validator="ColorValidator" validatorMessage="Required!"/>
<p:commandButton id="createOrUpdateButton"
actionListener="{backBean.createOrUpdate}"
process="#form"
update="#all"
value="Save"
style="width: 95%;" />
Validator:
#FacesValidator("ColorValidator")
public class ColorValidator implements Validator{
public ColorValidator(){
}
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (value==null || value.toString().trim().isEmpty()) {
FacesMessage msg = new FacesMessage("Color validation failed.","Please select a color.");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
The answer is: It was simply not supported!
Issue #5887 and issue #5892 addressing this and offer fixes which should be included in PrimeFaces version 9.0.
Related
I am having trouble to find my fault when recieving the Error "Validation Error: Value is not valid". After submitting a form, im getting this error, even though, when debugging, the selected Component is the right one. The converter seems to be working fine too thats why I am having a really tough time here. Here is what I have tried so far:
Change #RequestScoped to #ManagedBean and #ViewScoped - Made the SelectOneMenue beofore crash everytime because of a NullpointerException, this did never happen with #RequestScoped, so I am not sure what is happening there...
I double checked the Converter for this SelectedOneMenue, it seems to be working, I made a lot of debugging there, the Object that was converted to a String is, at least visible for me, the same that is later converted back from String to the Object.
The equals() Method: The equals Method seems OK to me, it literally just checks if the .id is the same, when checking this at the converter, it is always right. Maybe I'd rather search here for the error, even though I cant figure out what could be possibly wrong here.
Here are the parts of my code that I guess will be interesting for you, I have already made quite some research, I found quite good stuff though I couldn't get this to work but this must not mean anything since I just started programming with JavaEE and JSF ( + Primefaces).
Component equals() Method
#Override
public boolean equals(Object obj) {
if(obj == null){
//System.out.println("Component is NULL in equals() method");
}
if(this.id == ((Component) obj).id) {
return true;
}else {
return false;
}
}
Component Converter Class
#ManagedBean(name = "componentConverterBean")
#FacesConverter (value = "componentConverter")
public class ComponentConverter implements Converter{
#PersistenceContext(unitName="PU")
private EntityManager em;
#Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {
if (modelValue == null) {
return "";
}
return modelValue.toString();
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
System.out.println("ComponentConverter: submittedValue is null");
return null;
}
try {
System.out.println("ComponentConverter: Value to be found: " + submittedValue);
return em.find(Component.class, Integer.parseInt(submittedValue));
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(submittedValue + " is not a valid Component ID", e.getMessage()));
}
}
}
Part of the .xhtml file containing the SelectOneMenues
<p:outputLabel for="facility" value="Facility: " />
<p:selectOneMenu id="facility" value="#{visualization.facility}" converter="#{facilityConverterBean}" style="width:150px">
<p:ajax process="#this" partialSubmit="true" listener="#{visualization.onFacilityChange()}" update="component" />
<f:selectItem itemLabel="Select Facility" noSelectionOption="true" />
<f:selectItems value="#{visualization.facilities}" var="facility" itemLabel="#{facility.name}" itemValue="#{facility}" />
</p:selectOneMenu>
<p:outputLabel for="component" value="Components: " />
<p:selectOneMenu id="component" value="#{visualization.component}" converter="#{componentConverterBean}" style="width:150px">
<f:selectItem itemLabel="Select Component" noSelectionOption="true" />
<f:selectItems value="#{visualization.components}" var="comp" itemLabel="#{comp.name}" itemValue="#{comp}" />
</p:selectOneMenu>
"Components: Überprüfungsfehler: Wert ist ungültig."
This is the exact Error, which translates to:
"Components: Validation error: Value is not valid. "
I am very grateful for any help here. Thanks in advance.
Use a container object instead of an entity for value="#{visualization.component}".
e.g.
class ComponentDto {
private Component componentEntity;
private Component getComponentEntity() {
return this.componentEntity;
}
private void setComponentEntity(Component componentEntity) {
this.componentEntity = componentEntity;
}
}
See also: https://github.com/primefaces/primefaces/issues/2756
We now started to use JSF 2.3 on our existing JSF 2.2 project. On our custom converters we got warning Converter is a raw type. References to generic type Converter<T> should be parameterized.
Problem that we experiencing is when we tried to fix that warning using generics:
#FacesConverter(value = "myConverter", managed = true)
public class MyConverter implements Converter<MyCustomObject>{
#Override
public MyCustomObject getAsObject(FacesContext context, UIComponent component, String submittedValue){}
#Override
public String getAsString(FacesContext context, UIComponent component, MyCustomObject modelValue) {}
}
and when converter is used for example in
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:selectOneMenu id="#{componentId}" value="#{componentValue}">
<f:converter converterId="myConverter" />
<f:selectItem itemLabel="label"
itemValue="" />
<f:selectItems value="listOfValues"
var="singleValue"
itemValue="singleValue.value"
itemLabel="singleValue.label" />
</h:selectOneMenu>
then ClassCastException with message java.lang.String cannot be cast to MyCustomObjectis thrown. There is also one line in stacktrace that maybe can help com.sun.faces.cdi.CdiConverter.getAsString(CdiConverter.java:109).
But when converter generics definition changed from MyCustomObject to Object :
#FacesConverter(value = "myConverter", managed = true)
public class MyConverter implements Converter<Object>{
#Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue){}
#Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {}
}
then everything works as expected, but that obviously beats the purpose of Converter<T> interface.
I had same issue here and came up with following solution that actually not just compiles but also runs well:
some_page.xhtml (relevant excerpt):
<h:selectOneMenu styleClass="select" id="companyUserOwner" value="#{adminCompanyDataController.companyUserOwner}">
<f:converter converterId="UserConverter" />
<f:selectItem itemValue="#{null}" itemLabel="#{msg.NONE_SELECTED}" />
<f:selectItems value="#{userController.allUsers()}" var="companyUserOwner" itemValue="#{companyUserOwner}" itemLabel="#{companyUserOwner.userContact.contactFirstName} #{companyUserOwner.userContact.contactFamilyName} (#{companyUserOwner.userName})" />
</h:selectOneMenu>
Please note that the above JSF code is full of custom stuff and may not work on your end. And that my converter compiles without rawtype warning (JSF 2.3+, not 2.2!):
SomeUserConverter.java:
#FacesConverter (value = "UserConverter")
public class SomeUserConverter implements Converter<User> {
/**
* User EJB
*/
private static UserSessionBeanRemote USER_BEAN;
/**
* Default constructor
*/
public SomeUserConverter () {
}
#Override
public User getAsObject (final FacesContext context, final UIComponent component, final String submittedValue) {
// Is the value null or empty?
if ((null == submittedValue) || (submittedValue.trim().isEmpty())) {
// Return null
return null;
}
// Init instance
User user = null;
try {
// Try to parse the value as long
final Long userId = Long.valueOf(submittedValue);
// Try to get user instance from it
user = USER_BEAN.findUserById(userId);
} catch (final NumberFormatException ex) {
// Throw again
throw new ConverterException(ex);
} catch (final UserNotFoundException ex) {
// User was not found, return null
}
// Return it
return user;
}
#Override
public String getAsString (final FacesContext context, final UIComponent component, final User value) {
// Is the object null?
if ((null == value) || (String.valueOf(value).isEmpty())) {
// Is null
return ""; //NOI18N
}
// Return id number
return String.valueOf(value.getUserId());
}
}
This converter class has the JNDI lookup removed (I will rewrite that part later anyway) but it should be enough for demonstrating the important parts:
Converter<User> (by User is a custom POJI) preventing raw-type warning
value="UserConverter" that is the actual name you use in your JSF page
And most important, which actually fixed the ClassCastException:
<f:selectItem itemValue="#{null}" itemLabel="#{msg.NONE_SELECTED}" />
By omitting #{null} an empty string instead of null is being handled over to your getAsString method!
This last one actually fixed the said exception and my application is working again with much lesser warnings and much better type-hinting.
Need to remove forClass as value is there: FacesConverter is using both value andforClass, only value will be applied.
The raw-type warning will come (since Java SE 5) because you use an interface which has a generic (mostly stated as <T> after the interface name) which you need to satisfy so the compiler stop throwing that warning at you.
I had two issues with the FacesConverter.
First one, when I didn't use forClass = MyCustomObject.class I got the exact same error message as you had. Putting the forClass attribute in the #FacesConverter annotation solved the issue. It should solve it also for you...
Secondly, I suppose this is happening in the getAsString method? I had another issue with String casting and I had to do: return myCustomObject.getId().toString() where id is of type Long. After that I adapted my getAsObject to fetch the MyCustomObject based on the id. Maybe it is not directly related to your problem, but I thought it was important to mention as it is something I often bump into when writing converters.
I work with Primefaces 4-SNAPSHOT and I have some DataTables with <h:graphicImage> in them which I would like to export into different documents.
The fix that is desribed in p:dataExporter does not recognize p:cellEditor
which is supplied by BalusC works fine for the ExcelExporter, but does not work in the same way fot the CSVExporter.
I get NPE when I try to create the document.
I tried to remove the first lines of Code from the Extend-Class, because I have no CellEditor-Elements. This sort of works. It has no NPEs bus this gives me a document with the toString() of the graphicImage and the alt value.
The Extended-Class is this:
public class ExtendedCSVExporter extends CSVExporter
{
#Override
protected String exportValue(FacesContext context, UIComponent component)
{
if (component instanceof HtmlGraphicImage)
{
return (String) component.getAttributes().get("alt");
}
else
{
return super.exportValue(context, component);
}
}
}
And I call it like described in the referenced topic
public void exportPDF(DataTable table, String filename) throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
Exporter exporter = new ExtendedCSVExporter();
exporter.export(context, table, filename, false, false, "UTF-8", null, null);
context.responseComplete();
}
The column of the Table looks like this:
<p:column sortBy="state">
<f:facet name="header">
<h:outputText value="State">
</f:facet>
<h:graphicImage id="stateImg" name="state.png" library="icons" value="#{bean.state} />
<p:tooltip for="stateImg" value="Allowed" showEffect="fade" hideEffect="fade" />
</p:column>
For the Excel export this works fine, and the value which is taken for the image is the value of the tooltip because the graphic image has no alt-value.
But this does not work for CSV files
What I get in my document for pageOnly is:
"javax.faces.component.html.HtmlGraphicImage#23e645d8AltText"
For the whole Table I get a NPE
Any suggestions how to fix this?
Okay I know have found a solution to my problem.
I just override the HtmlGraphicImage.
I modified the Extended-Class so the GraphicImage always returns an empty String and I fetch the value of the tooltip.
So the Extende-Class looks like this:
public class ExtendedCSVExporter extends CSVExporter
{
#Override
protected String exportValue(FacesContext context, UIComponent component)
{
if (component instanceof HtmlGraphicImage)
{
return "";
}
else
{
return super.exportValue(context, component);
}
}
}
The following code:
<h:selectOneMenu id="discountCode" value="#{customerMBean.details.discountcode}"
title="DiscountCode" required="true" requiredMessage="The DiscountCode field is required."
converter="#{customerMBean.discountCodeConverter}">
<f:selectItems value="#{customerMBean.allDiscountCodes}"/>
</h:selectOneMenu>
<h:commandButton id="back" value="Back" action="#{customerMBean.list}"/>
<h:commandButton id="update" value="Update" action="#{customerMBean.update}"/>
Shows the following error, regardless of the clicked button:
j_idt6:discountCode : validation error .
public Converter getDiscountCodeConverter() {
return discountCodeConverter;
}
private Converter discountCodeConverter = new Converter() {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return new ConverterException("On verra la conversion String->Objet plus tard...");
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
DiscountCode dc = (DiscountCode) value;
return dc.getDiscountcode()+" : "+dc.getRate()+"%";
}
};
How is this caused and how can I solve it?
When using a custom converter in h:selectOneMenu, you should always override the equals() method of the object involved.
See also
JSF Validation Error While Using Custom Converter
Use <h:message/> tag it will show you validation error and update it on clicking of button or you can use auto update.
According to me :-
why your button is not working ?? because every time when you click on submit button it will show you validation error but you are not using that's why it is not visible on your screen.
And on back button use immediate=true it will skip the validation phase.
I am using seam 2.2.2.Final on JBoss AS 5. I am working on a multi-page wizard.On my first page, user will be able to enter several business names separated by a new line on a textarea.
<s:decorate id="businessNameTextAreaField" template="layout/edit.xhtml">
<ui:define name="label">Business Names</ui:define>
<h:inputTextarea id="businessNameTextArea"
cols="80"
rows="3"
required="true"
value="#{businessNameHome.instance.businessNameTextArea}"/>
</s:decorate>
Upon submission of the page, the system parses the inputed value and splits it into a list of strings
public String checkBusinessNames(){
String businessNameTextArea = this.getInstance().getbusinessNameTextArea();
String[] businessNameTextAreaArray = businessNameTextArea.split("\\n");
List<SelectItem> businessNameChoices = new ArrayList<SelectItem>();
for(String businessNameText: businessNameTextAreaArray){
businessNameChoices.add(new SelectItem(businessNameText));
}
this.getInstance().setBusinessNameChoices(businessNameChoices);
return "valid";
}
The user is then asked to select from the list of valid business names to register
<s:decorate id="businessNameRegisterListField" template="layout/edit.xhtml">
<ui:define name="label">Business Name</ui:define>
<h:selectManyCheckbox value="#{businessNameHome.instance.selectedbusinessName}" layout="pageDirection" immediate="true" >
<s:selectItems value="#{businessNameHome.instance.businessNameChoices}" var="bn" label="#{bn.label}" /> </h:selectManyCheckbox>
</s:decorate>
selectedbusinessName is of type String while businessNameChoices is of List
Upon submission of the page, what is submitted as business names is something like this:
javax.faces.model.SelectItem#135aa7c
I have tried putting an itemValue on the s:selectItems but I get another error which is "Value is not valid"
Tried to use <s:convertEntity> but gets a NumberFormatException
I have also tried to create my own converter
public class BusinessNameBeanConverter implements javax.faces.convert.Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent cmp, String value) {
// TODO Auto-generated method stub
System.out.println("getAsObject "+value);
return value;
}
#Override
public String getAsString(FacesContext context, UIComponent cmp, Object value) {
// TODO Auto-generated method stub
System.out.println("getAsString "+((SelectItem)value).getValue());
return ((SelectItem)value).getValue();
}
}
but I still get the same "Value is not valid" error.
I don't know what to do anymore. Please help.
Thanks,
Nicholas
Change
<s:selectItems value="#{businessNameHome.instance.businessNameChoices}" var="bn" label="#{bn.label}" />
to
<f:selectItems value="#{businessNameHome.instance.businessNameChoices}" />
You've namely already a List<SelectItem>, not a List<SomeObject> for which <s:selectItems> is useful.
Don't forget to remove the converter, it makes no sense.