简体   繁体   中英

JSF Validation Error h:selectOneMenu but for only one item

I saw a million topics talking about this issue, but none of them was matching my problem, and here it is:

My query brings the following results to the list:

  1. Caixa Economica Federal
  2. ASSOCIAÇÃO DOS FRANQUEADOS DA REDE DE LANCHOLETES GIRAFFAS

When trying to seach by the first item in h:selectOneMenu , everything works fine. But when I try to search by the second item in list, I got the following error:

j_idt49:advertiserName: Validation Error: Value is not valid

This is really weird and, at least for me, all of the previous answers that I saw just don't make any sense at all, if you consider that with some values search works fine.

Here are my codes:

commercialRecognized.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:body>
        <ui:composition template="jsf/template/template.xhtml">
            <ui:define name="conteudo">
                <h:outputScript target="body" library="js" name="commercialRecognized.js"/>
                <div id="wrapper">
                    <div id="body_site">
                        <div id="content">
                            <div class="success urlpie hide">#{bundle.OperacaoSucesso}</div>
                            <div class="error"></div>
                            <span class="clearfix_2">&nbsp;</span>
                            <h2><h:outputText value="#{bundle.ComerciaisReconhecidos}"></h:outputText></h2>
                            <p class="subtitle"><h:outputText value="#{bundle.ConsulteOsComerciais}"></h:outputText></p>
                            <div class="box">
                                <p class="w_100 txt_bold al_left"><h:outputText value="#{bundle.PesquisarPor}"></h:outputText>
                                </p>
                                <h:form><p:growl id="messages" showDetail="true"/></h:form>
                                <h:form>
                                    <ul class="form_list_left al_right w_800">
                                        <li>
                                            <h:outputLabel for="advertiserName" value="#{bundle.Anunciante_Title}"/>
                                            <h:selectOneMenu value="#{matchesController.selected.advertiserName}" id="advertiserName" class="w_220" title="#{bundle.Anunciante_Title}">
                                                <f:selectItem itemLabel="Selecione..." itemValue=""/>
                                                <f:selectItems value="#{matchesController.advertiserNames}"/>
                                            </h:selectOneMenu>
                                        </li>
                                        <li>
                                            <h:outputLabel for="agencyName" value="#{bundle.Agencia_Title}"/>
                                            <h:selectOneMenu value="#{matchesController.selected.agencyName}" id="agencyName" class="w_220" title="#{bundle.Agencia_Title}">
                                                <f:selectItem itemLabel="Selecione..." itemValue=""/>
                                                <f:selectItems value="#{matchesController.agencyNames}"/>
                                            </h:selectOneMenu>
                                        </li>
                                        <li>
                                            <h:outputLabel for="productName" value="#{bundle.Produto_Title}"/>
                                            <h:selectOneMenu value="#{matchesController.selected.productName}" id="productName" class="w_220" title="#{bundle.Produto_Title}">
                                                <f:selectItem itemLabel="Selecione..." itemValue=""/>
                                                <f:selectItems value="#{matchesController.productNames}"/>
                                            </h:selectOneMenu>
                                        </li>
                                        <li>
                                            <h:outputLabel for="iniDate" value="#{bundle.DataInicial_Title}"/>
                                            <h:inputText value="#{matchesController.selected.iniDate}" class="w_80 data" id="iniDate" required="false" validatorMessage="#{bundle.DataInicial_Title} inválida."/>
                                        </li>
                                        <li>
                                            <h:outputLabel for="finalDate" value="#{bundle.DataFinal_Title}"/>
                                            <h:inputText value="#{matchesController.selected.finalDate}" class="w_80 data" id="finalDate" required="false" validatorMessage="#{bundle.DataFinal_Title} inválida."/>
                                        </li>
                                        <li>
                                            <h:outputLabel for="iniTime" value="#{bundle.HoraInicial_Title}"/>
                                            <h:inputText value="#{matchesController.selected.iniTime}" class="w_80 hora" id="iniTime" required="false" validatorMessage="#{bundle.HoraInicial_Title} inválida."/>
                                        </li>
                                        <li>
                                            <h:outputLabel for="finalTime" value="#{bundle.HoraFinal_Title}"/>
                                            <h:inputText value="#{matchesController.selected.finalTime}" class="w_80 hora" id="finalTime" required="false" validatorMessage="#{bundle.HoraFinal_Title} inválida."/>
                                        </li>
                                        <li>
                                            <h:outputLabel for="equipmentName" value="#{bundle.NomeEquipamento_Title}"/>
                                            <h:inputText value="#{matchesController.selected.equipmentName}" class="w_130 equipment" id="equipmentName" required="false" validatorMessage="#{bundle.NomeEquipamento_Title} inválido."/>
                                        </li>
                                        <li>
                                            <h:outputLabel for="channelCode" value="#{bundle.CodigoCanal_Title}"/>
                                            <h:inputText value="#{matchesController.selected.channelCode}" class="w_80 channelCode" id="channelCode" required="false" validatorMessage="#{bundle.CodigoCanal_Title} inválido."/>
                                        </li>
                                        <li><h:commandLink action="#{matchesController.clear}" class="bt_limpar button29" style="margin-top:13px;"><span class="screen_reader_text">Limpar</span></h:commandLink></li>
                                        <li><h:commandLink action="#{matchesController.search}" class="bt_pesquisar button29" style="margin-top:13px;"><span class="screen_reader_text">Pesquisar</span></h:commandLink></li>
                                    </ul>
                                </h:form>

                                <span class="clearfix_2">&nbsp;</span>
                            </div>
                            <div class="resultado">
                                <c:if test="#{matchesController.tableRs.size() > 0}">
                                    <h:dataTable id="tableResultados" value="#{matchesController.tableRs}" var="item">
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.DuracaoComercialCadastrado}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.durationCommercialRegistered}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.DuracaoComercialReconhecido}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.durationCommercialRecognized}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.Versao}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.version}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.ID}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.ID}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.Confiabilidade}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.confiability}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.Distorcao}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.distortion}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.DataEHoraExibicao}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.dateShow}"/>&nbsp;
                                            <h:outputText value="#{item.timeShow}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.SegundosDoComercial}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.commercialSeconds}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.Status}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.status}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.TituloMaterial}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.materialTitle}"/>
                                        </h:column>
                                        <h:column>
                                            <f:facet name="header">
                                                <h:outputText value="#{bundle.AnuncianteTable}"/>
                                            </f:facet>
                                            <h:outputText value="#{item.announcer}"/>
                                        </h:column>
                                    </h:dataTable>
                                </c:if>
                            </div>
                            <span class="clearfix_2">&nbsp;</span>
                        </div>
                        <!--#content--> 
                    </div>
                    <!--#body_site--> 
                </div>
                <!--#wrapper-->
            </ui:define>
        </ui:composition>
    </h:body>
</html>

MatchesController.java

package net.checkmidia.auditoria.managedbean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import net.checkmidia.auditoria.entity.Matches;
import net.checkmidia.auditoria.managedbean.converter.SearchCommercialsDTO;
import net.checkmidia.auditoria.managedbean.converter.TableResultSearchCommercialsDTO;
import net.checkmidia.auditoria.managedbean.helper.JsfHelper;
import net.checkmidia.auditoria.session.MatchesSession;
import net.checkmidia.auditoria.util.DateTimeUtil;
import net.checkmidia.auditoria.util.ObjectUtil;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;

@ManagedBean(name = "matchesController")
@SessionScoped
public class MatchesController implements Serializable {

    /* Instância de SearchCommercialsDTO com todos os dados digitados na pesquisa */
    private SearchCommercialsDTO current;

    /* Lista com todos os resultados obtidos na query de pesquisa */
    private List<TableResultSearchCommercialsDTO> tableRs = new ArrayList<TableResultSearchCommercialsDTO>();

    @EJB
    private MatchesSession ejbFacade;

    private int selectedItemIndex;

    /**
     * Combos
     */
    private String advertiserName;
    private String agencyName;
    private String productName;
    private Map<String, String> advertiserNames = new HashMap<String, String>();
    private Map<String, String> agencyNames = new HashMap<String, String>();
    private Map<String, String> productNames = new HashMap<String, String>();

    /**
     * Construtor default
     */
    public MatchesController() {}

    /**
     * Obtém todos os inputs marcados com "selected"
     * @return o formulario de pesquisa
     */
    public SearchCommercialsDTO getSelected() {
        if (current == null) {
            current = new SearchCommercialsDTO();
            selectedItemIndex = -1;
        }
        return current;
    }

    /**
     * Obtém a facade
     * @return facade
     */
    public MatchesSession getFacade() {
        return ejbFacade;
    }

    /**
     *  Popula o combo de anunciantes com todos os anunciantes gravados no banco
     */
    public void getAdvertisers() {
        try {
            List<String> advertiserList = ejbFacade.getAdvertiser();
            for (String advertiser : advertiserList) {
                advertiserNames.put(advertiser, advertiser);
            }
        } catch (Exception ex) {
            Logger.getLogger(MatchesController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     *  Popula o combo de agências com todos os agências gravados no banco
     */
    public void getAgencys() {
        try {
            List<String> agencyList = ejbFacade.getAgencys();
            for (String agency : agencyList) {
                agencyNames.put(agency, agency);
            }
        } catch (Exception ex) {
            Logger.getLogger(MatchesController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     *   Popula o combo de produtos com todos os produtos gravados no banco
     */
    public void getProducts() {
        try {
            List<String> productList = ejbFacade.getProducts();
            for (String product : productList) {
                productNames.put(product, product);
            }
        } catch (Exception ex) {
            Logger.getLogger(MatchesController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Inicializa os métodos para popular os combos assim que a página
     * for carregada
     */
    @PostConstruct
    public void combo(){
        getAdvertisers();
        getAgencys();
        getProducts();
    }

    /**
     * Limpa todos os dados do formulário de pesquisa e da tabela
     */
    public void clear() {
        tableRs.clear();
    }

    /**
     * Método de pesquisa
     * Esse método executa a facade e então obtém os resultados da pesquisa de acordo
     * com o formulario de pesquisa populando, então, a tabela
     * @return null
     */
    public String search() {
        try {
            List<Matches> execute = getFacade().searchMatches(current);
            if (!ObjectUtil.isEmpty(execute)) {
                tableRs.clear();
                for (int i = 0; i < execute.size(); i++) {
                    tableRs.add(
                            new TableResultSearchCommercialsDTO(
                            String.valueOf(execute.get(i).getMatchSearchedMaterialStartPosition()),
                            String.valueOf(execute.get(i).getMatchSourceMaterialStartPosition()),
                            String.valueOf(execute.get(i).getEngineVersion()),
                            String.valueOf(execute.get(i).getId()),
                            String.valueOf(execute.get(i).getMatchDistortion()),
                            String.valueOf(execute.get(i).getMatchMethod()),
                            DateTimeUtil.getDate(execute.get(i).getStartDate()),
                            DateTimeUtil.getTime(execute.get(i).getStartDate()),
                            String.valueOf(execute.get(i).getDuration()),
                            String.valueOf(execute.get(i).getStatus()),
                            String.valueOf(execute.get(i).getIdSourceMaterial().getTitle()),
                            String.valueOf(execute.get(i).getIdSourceMaterial().getAdvertiserName()),
                            String.valueOf(execute.get(i).getMatchConfidence())));
                }
                JsfHelper.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("SearchSuccessfull"));
            } else {
                tableRs.clear();
                JsfHelper.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("NoResults"));
            }
            return null;
        } catch (Exception e) {
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, e);
            JsfHelper.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

    /**
     * Getters e setters
     */
    public List<TableResultSearchCommercialsDTO> getTableRs() {
        return tableRs;
    }

    public String getAdvertiserName() {
        return advertiserName;
    }

    public void setCity(String advertiserName) {
        this.advertiserName = advertiserName;
    }

    public Map<String, String> getAdvertiserNames() {
        return advertiserNames;
    }

    public String getAgencyName() {
        return agencyName;
    }

    public String getProductName() {
        return productName;
    }

    public Map<String, String> getAgencyNames() {
        return agencyNames;
    }

    public Map<String, String> getProductNames() {
        return productNames;
    }

    public void setAdvertiserName(String advertiserName) {
        this.advertiserName = advertiserName;
    }

    public void setAgencyName(String agencyName) {
        this.agencyName = agencyName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public void setAdvertiserNames(Map<String, String> advertiserNames) {
        this.advertiserNames = advertiserNames;
    }

    public void setAgencyNames(Map<String, String> agencyNames) {
        this.agencyNames = agencyNames;
    }

    public void setProductNames(Map<String, String> productNames) {
        this.productNames = productNames;
    }

    public void setCities(Map<String, String> advertiserNames) {
        this.advertiserNames = advertiserNames;
    }

    public void setTableRs(List<TableResultSearchCommercialsDTO> tableRs) {
        this.tableRs = tableRs;
    }

}

MatchesControllerConverter.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.checkmidia.auditoria.managedbean.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import net.checkmidia.auditoria.entity.Matches;
import net.checkmidia.auditoria.managedbean.MatchesController;

/**
 * Conversor para a entidade Matches
 * @author gabrielbombardi
 */
@FacesConverter(forClass = Matches.class)
public class MatchesControllerConverter implements Converter {

    public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
        if (value == null || value.length() == 0) {
            return null;
        }
        MatchesController controller = (MatchesController) facesContext.getApplication().getELResolver().
                getValue(facesContext.getELContext(), null, "matchesController");
        return value;
    }

    java.lang.Integer getKey(String value) {
        java.lang.Integer key;
        key = Integer.valueOf(value);
        return key;
    }

    String getStringKey(java.lang.Integer value) {
        StringBuffer sb = new StringBuffer();
        sb.append(value);
        return sb.toString();
    }

    public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
        if (object == null) {
            return null;
        }
        if (object instanceof Matches) {
            Matches o = (Matches) object;
            return getStringKey(o.getId());
        } else {
            throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + Matches.class.getName());
        }
    }
}

Would you any of you help me? Thanks!

PS: sorry for my poor english :)

You forgot to implement the equals() and hashCode() in your Matches class according the contract . JSF is using it in order to match the selected item with the available items. Otherwise only exactly the item which was created by new operator would be considered equal with itself, but two separate instances created by new operator would never be considered equal even though they may be technically equal based on their internal properties.

Provided that your Matches class has an id field representing the technical DB identifier, then this should do:

@Override
public boolean equals(Object other) {
    return (id != null && other != null && getClass() == other.getClass())
         ? id.equals(((Matches) other).id)
         : (other == this);
}

@Override
public int hashCode() {
    return (id != null) 
         ? (getClass().hashCode() + id.hashCode()) 
         : super.hashCode();
}

See also:


Further, the getAsObject() method of your converter looks in its current form suspicious. It's totally ignoring the controller and directly returning the raw unconverted value . The method is supposed to convert the obtained string which represents the ID of the Matches instance into a concrete Matches instance.

It should look something like this instead:

public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
    if (value == null || value.length() == 0) {
        return null;
    }

    Integer id = getKey(value);
    Matches matches = getItSomehowBasedOn(id);
    return matches;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM