5 Replies Latest reply on Nov 27, 2009 5:28 PM by judy guglielmin

    non ascii characters urlencoded by simple get

    Arturo Frappe Newbie
      Greetings!
      My configuration is Seam 2.2.0.GA with IceFaces 1.8.2 on JBoss 5.1

      I'm working with non ascii characters and with a ice:form
      When I submit data by a partialSubmit, the dates and fields with non ascii characters behaves ok.

      BUT when I use a submit button things goes wrong and I get a URLEncoded value in my form fields.

      i.e.: 
             | If I enter  -> I got
             ------------------------------
             | Muñoz  ->  Mu%C3%B1oz
             -------------------------------
             | 12/12/1980 ->   12%2F12%2F1980
             --------------------------------


      I believe that this issue has relation with:
      http://seamframework.org/Community/WhyEntitypagexmlParameter
      and
      http://seamframework.org/Community/DateFormatErrorInPagexmlParamsASeamIssue

      If I use a converter with the Dates and the non ascii characters all works fine.
      I'm fighting against seam page.xml or components.xml, or other configuration to find a seam-friendly solution to this issue.

      Thank you.

      My Form and my converters are below:
      ----------------------------------------

      <ice:form id="pacienteSearch" styleClass="edit"  partialSubmit="true">        
                     <ice:panelGroup id="searchGroup" styleClass="formBorderHighlight">
                          <table width="100%" border="0" cellspacing="0" cellpadding="0">
                               <tr>
                                    <td class="iceDatTblColHdr2"><ice:outputText
                                         id="listPacienteId" value="B&#250;squeda simple" /></td>
                               </tr>
                          </table>
                          <ice:panelGroup id="listPanelGroupPacienteId" styleClass="edit">
                          Debes capturar todos los campos:
                          <hr />
                               <s:decorate id="sexodecId" template="layout/display.xhtml">
                                    <ui:define name="label">#{messages.genero}</ui:define>
                                    <ice:selectOneRadio id="logic"
                                         value="#{pacienteList.paciente.sexo}" partialSubmit="false"
                                         style="width: 225px;height: 12px; vertical-align:middle; display:inline"
                                         required="true">
                                         <f:selectItem itemLabel="#{messages.genero_femenino}" itemValue="FEMENINO" />
                                         <f:selectItem itemLabel="#{messages.genero_masculino}" itemValue="MASCULINO" />
                                    </ice:selectOneRadio>
                               </s:decorate>
                               <s:decorate id="apPaternodecId" template="layout/display.xhtml">
                                    <ui:define name="label">#{messages.apPaterno}</ui:define>
                                    <ice:inputText id="apPaterno"
                                         value="#{pacienteList.paciente.apPaterno}" partialSubmit="false"
                                         required="true"/>
                               </s:decorate>
                               <s:decorate id="nacimientodecId" template="layout/display.xhtml">
                                    <ui:define name="label">#{messages.fechaNacimiento}</ui:define>
                                    <ice:selectInputDate id="nacimiento"
                                         value="#{pacienteList.paciente.nacimiento}" renderAsPopup="true"
                                         partialSubmit="false" renderMonthAsDropdown="true"
                                         renderYearAsDropdown="true" style="width: 225px; display:inline"
                                         required="true" /><ice:message style="color:red;" id="nacimientoError" for="nacimiento"/>
                               </s:decorate>                                             
                     </ice:panelGroup>
                          <s:decorate id="searchdecId" template="layout/display.xhtml">
                               <ice:commandButton id="search" value="#{messages.search}"
                                    action="/PacienteList.xhtml" partialSubmit="true" />
                               <ice:commandButton id="reset" value="#{messages.reset}"
                                    action="#{pacienteList.reset()}" partialSubmit="true" />
                          </s:decorate>
                     </ice:panelGroup>
                </ice:form>




      ------------------- Date converter -------------------------

      @Name("jbSeam4413Converter")
      @BypassInterceptors
      @Converter
      public class JbSeam4413 implements javax.faces.convert.Converter {

        @Logger
        private Log log;

        public Object getAsObject(FacesContext context, UIComponent component,
                String value) throws ConverterException {
            log.info("JbSeam4413.getAsObject called (" + value +")");
            if(value == null || value.trim().length() == 0)
                return null;
            Date date = null;
            try {
                 SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
                date = sdf.parse(URLDecoder.decode(value,"UTF-8"));
            } catch (ParseException e) {
                e.printStackTrace();
                FacesMessage message = new FacesMessage();
                message.setDetail("javax.faces.converter.DateTimeConverter.DATE");
                message.setSummary("javax.faces.converter.DateTimeConverter.DATE_detail");
                message.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ConverterException(message);
            } catch (UnsupportedEncodingException e) {
                 e.printStackTrace();
                FacesMessage message = new FacesMessage();
                message.setDetail("javax.faces.converter.DateTimeConverter.DATE");
                message.setSummary("javax.faces.converter.DateTimeConverter.DATE_detail");
                message.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ConverterException(message);
           }
            return date;
        }

        public String getAsString(FacesContext context, UIComponent component,
                Object value) throws ConverterException {
            log.info("JbSeam4413.getAsString called");
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
            return sdf.format(value);
        }
      }


      -------------------------- Non ascii field converter --------------------------


      @Name("trimInputFields")
      @BypassInterceptors
      @Converter
      public class TrimInputFields implements javax.faces.convert.Converter{

           public Object getAsObject(FacesContext context, UIComponent component, String value) {
                if(StringUtils.isEmpty(value)){
                     return null;
                } else {
                     try {
                          return URLDecoder.decode(value,"UTF-8");
                     } catch (UnsupportedEncodingException e) {
                           FacesMessage message = new FacesMessage();
                          message.setDetail("javax.faces.converter.STRING");                   
                          message.setSeverity(FacesMessage.SEVERITY_ERROR);
                          throw new ConverterException(message);
                     }
                }
           }

           public String getAsString(FacesContext context, UIComponent component, Object value) {
             if(value!=null){
                  try {
                     return URLDecoder.decode(value.toString().trim(),"UTF-8");
                } catch (UnsupportedEncodingException e) {
                       FacesMessage message = new FacesMessage();
                     message.setDetail("javax.faces.converter.STRING");
                     message.setSummary(e.getLocalizedMessage());
                     message.setSeverity(FacesMessage.SEVERITY_ERROR);
                     throw new ConverterException(message);
                }
             } else {
                  return null;
             }
           }
      }

        • 1. Re: non ascii characters urlencoded by simple get
          Arturo Frappe Newbie

          It seems a icefaces bug.
          I changed my configuration to:
          Seam 2.2.0.GA with RichFaces on JBoss 5.1, then I configured JBoss to accept UTF-8, and voilá!


          Is not a seam defect, surely is IceFaces.


          Case is not closed.

          • 2. Re: non ascii characters urlencoded by simple get
            judy guglielmin Novice

            ICEfaces should work with UTF-8, so if it doesn't please open a jira and attach a simple test case where this isn't working for you.  If you assign it to me, then I can take a look. Thanks, Judy.

            • 3. Re: non ascii characters urlencoded by simple get
              Arturo Frappe Newbie

              Judy: My suspect on ICEFaces is because I regenerated the same project using seam-gen with RichFaces, then and all runs as expected. Maybe ICEFaces is not the problem but the combination with seam could be.



              Today I tried something diffrent: I enabled all verbosity on log4j, and I hang a phase listener, my findings are intresting:


              Seam calls HibernateEntityQuery:getResultList 3 times, first without parameters, second with right characters, and third with a urlencoded chars.


              I don't know how to make a test case.


              Below is my log:



              17:15:51,864 DEBUG PhaseLog:20 - Inicio fase RESTORE_VIEW 1
              17:15:51,864 DEBUG PhaseLog:16 - Fin fase RESTORE_VIEW 1
              17:15:51,864 DEBUG SessionFactoryObjectFactory:92 - JNDI lookup: visoreseceSessionFactory
              ...
              
              17:15:51,880 DEBUG JTATransaction:92 - Began a new JTA transaction
              17:15:51,880 DEBUG JDBCContext:199 - successfully registered Synchronization
              17:15:51,880 TRACE JDBCContext:237 - after transaction begin
              
              17:15:51,880 *DEBUG PhaseLog:20 - Inicio fase APPLY REQUEST_VALUES 2
              17:15:51,880 TRACE QueryPlanCache:98 - located HQL query plan in cache (select paciente from Paciente paciente)
              ...
              17:16:00,817 DEBUG StatefulPersistenceContext:860 - initializing non-lazy collections
              17:16:00,817 DEBUG PhaseLog:16 - Fin fase APPLY REQUEST_VALUES 2
              17:16:00,817 DEBUG PhaseLog:20 - Inicio fase PROCESS_VALIDATIONS 3
              17:16:00,833 DEBUG PhaseLog:16 - Fin fase PROCESS_VALIDATIONS 3
              17:16:00,833 DEBUG PhaseLog:20 - Inicio fase UPDATE_MODEL_VALUES 4
              ...
              17:16:00,848 TRACE QueryPlanCache:98 - located HQL query plan in cache (select paciente from Paciente paciente where lower(paciente.apPaterno) like lower(concat(:el3,'%')) and lower(paciente.sexo) like lower(concat(:el6,'%')) and paciente.nacimiento = :el7)
              ...
              17:16:00,880 TRACE DefaultAutoFlushEventListener:76 - Dont need to execute flush
              17:16:00,880 TRACE HQLQueryPlan:174 - find: select paciente from Paciente paciente where lower(paciente.apPaterno) like lower(concat(:el3,'%')) and lower(paciente.sexo) like lower(concat(:el6,'%')) and paciente.nacimiento = :el7
              



              Here is my non ascii character as Hibernate parameter:


              17:16:00,880 TRACE QueryParameters:278 - named parameters: {el6=MASCULINO, el3=Zuñiga, el7=12 octubre 1983}
              ...
              17:16:01,520 DEBUG PhaseLog:16 - Fin fase UPDATE_MODEL_VALUES 4
              17:16:01,520 DEBUG PhaseLog:20 - Inicio fase INVOKE_APPLICATION 5
              17:16:01,520 DEBUG PhaseLog:16 - Fin fase INVOKE_APPLICATION 5
              17:16:01,536 TRACE CacheSynchronization:114 - transaction after completion callback, status: 4
              17:16:01,536 TRACE JDBCContext:242 - after transaction completion
              17:16:01,536 TRACE SessionImpl:450 - after transaction completion
              17:16:01,661 DEBUG PhaseLog:20 - Inicio fase RESTORE_VIEW 1
              17:16:01,661 DEBUG PhaseLog:16 - Fin fase RESTORE_VIEW 1
              


              After this point my non ascii characters get urlencoded and the field is requeried against Hibernate:


              17:16:01,755 DEBUG SQL:111 - select top 11 paciente0_.CV_CURP as CV1_2_, paciente0_.CV_AGREGADO_MED as CV2_2_, paciente0_.TX_AP_MATERNO as TX3_2_, paciente0_.TX_AP_PATERNO as TX4_2_, paciente0_.CV_CURP_RENAPO as CV5_2_, paciente0_.TM_NACIMIENTO as TM6_2_, paciente0_.TX_NOMBRE as TX7_2_, paciente0_.CV_NSS as CV8_2_, (SELECT c.tx_entidad_federativa FROM CAT_ENTIDAD_FEDERATIVA c WHERE c.id_pais = paciente0_.id_pais_nacimiento AND c.id_entidad_federativa = paciente0_.id_entidad_federativa_nac) as formula5_, (SELECT c.tx_escolaridad FROM CAT_ESCOLARIDAD c WHERE c.id_escolaridad = paciente0_.id_escolaridad) as formula6_, (SELECT c.tx_edo_civil FROM CAT_EDO_CIVIL c WHERE c.id_edo_civil = paciente0_.id_edo_civil) as formula7_, (SELECT c.tx_grupo_sanguineo FROM CAT_GRUPO_SANGUINEO c WHERE c.id_grupo_sanguineo = paciente0_.id_grupo_sanguineo) as formula8_, (SELECT c.TX_OCUPACION FROM CAT_OCUPACION c WHERE c.ID_OCUPACION=paciente0_.ID_OCUPACION) as formula9_, (SELECT c.tx_pais FROM CAT_PAIS c WHERE c.id_pais = paciente0_.id_pais_nacimiento) as formula10_, (SELECT TOP 1 c.CT_RESULTADO FROM  MEDICIONES_PACIENTE c WHERE c.ID_MEDICION =303 AND c.CV_CURP=paciente0_.CV_CURP ORDER BY c.TM_EVENTO DESC) as formula11_, (SELECT c.tx_sexo FROM CAT_SEXO c WHERE c.id_sexo = paciente0_.id_sexo) as formula12_, (SELECT TOP 1 c.CT_RESULTADO FROM  MEDICIONES_PACIENTE c WHERE c.ID_MEDICION =301 AND c.CV_CURP=paciente0_.CV_CURP ORDER BY c.TM_EVENTO DESC) as formula13_ from EC.dbo.PACIENTE paciente0_ where (lower(paciente0_.TX_AP_PATERNO) like lower((?+'%'))) and (lower((SELECT c.tx_sexo FROM CAT_SEXO c WHERE c.id_sexo = paciente0_.id_sexo)) like lower((?+'%'))) and paciente0_.TM_NACIMIENTO=?
              Hibernate: select top 11 paciente0_.CV_CURP as CV1_2_, paciente0_.CV_AGREGADO_MED as CV2_2_, paciente0_.TX_AP_MATERNO as TX3_2_, paciente0_.TX_AP_PATERNO as TX4_2_, paciente0_.CV_CURP_RENAPO as CV5_2_, paciente0_.TM_NACIMIENTO as TM6_2_, paciente0_.TX_NOMBRE as TX7_2_, paciente0_.CV_NSS as CV8_2_, (SELECT c.tx_entidad_federativa FROM CAT_ENTIDAD_FEDERATIVA c WHERE c.id_pais = paciente0_.id_pais_nacimiento AND c.id_entidad_federativa = paciente0_.id_entidad_federativa_nac) as formula5_, (SELECT c.tx_escolaridad FROM CAT_ESCOLARIDAD c WHERE c.id_escolaridad = paciente0_.id_escolaridad) as formula6_, (SELECT c.tx_edo_civil FROM CAT_EDO_CIVIL c WHERE c.id_edo_civil = paciente0_.id_edo_civil) as formula7_, (SELECT c.tx_grupo_sanguineo FROM CAT_GRUPO_SANGUINEO c WHERE c.id_grupo_sanguineo = paciente0_.id_grupo_sanguineo) as formula8_, (SELECT c.TX_OCUPACION FROM CAT_OCUPACION c WHERE c.ID_OCUPACION=paciente0_.ID_OCUPACION) as formula9_, (SELECT c.tx_pais FROM CAT_PAIS c WHERE c.id_pais = paciente0_.id_pais_nacimiento) as formula10_, (SELECT TOP 1 c.CT_RESULTADO FROM  MEDICIONES_PACIENTE c WHERE c.ID_MEDICION =303 AND c.CV_CURP=paciente0_.CV_CURP ORDER BY c.TM_EVENTO DESC) as formula11_, (SELECT c.tx_sexo FROM CAT_SEXO c WHERE c.id_sexo = paciente0_.id_sexo) as formula12_, (SELECT TOP 1 c.CT_RESULTADO FROM  MEDICIONES_PACIENTE c WHERE c.ID_MEDICION =301 AND c.CV_CURP=paciente0_.CV_CURP ORDER BY c.TM_EVENTO DESC) as formula13_ from EC.dbo.PACIENTE paciente0_ where (lower(paciente0_.TX_AP_PATERNO) like lower((?+'%'))) and (lower((SELECT c.tx_sexo FROM CAT_SEXO c WHERE c.id_sexo = paciente0_.id_sexo)) like lower((?+'%'))) and paciente0_.TM_NACIMIENTO=?
              17:16:01,755 TRACE AbstractBatcher:513 - preparing statement
              17:16:01,755 TRACE StringType:151 - binding 'Zu%C3%B1iga' to parameter: 1
              17:16:01,755 TRACE StringType:151 - binding 'MASCULINO' to parameter: 2
              17:16:01,755 TRACE DateType:151 - binding '12 octubre 1983' to parameter: 3
              17:16:02,208 DEBUG AbstractBatcher:426 - about to open ResultSet (open ResultSets: 0, globally: 0)
              17:16:02,208 TRACE Loader:717 - processing result set
              17:16:02,208 TRACE Loader:744 - done processing result set (0 rows)
              17:16:02,208 DEBUG AbstractBatcher:433 - about to close ResultSet (open ResultSets: 1, globally: 1)
              17:16:02,208 DEBUG AbstractBatcher:418 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
              17:16:02,208 TRACE AbstractBatcher:562 - closing statement
              17:16:02,208 DEBUG ConnectionManager:427 - aggressively releasing JDBC connection
              17:16:02,208 DEBUG ConnectionManager:464 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
              17:16:02,208 TRACE Loader:874 - total objects hydrated: 0
              17:16:02,208 DEBUG StatefulPersistenceContext:860 - initializing non-lazy collections
              17:16:02,224 DEBUG PhaseLog:16 - Fin fase RENDER_RESPONSE 6
              17:16:02,224 TRACE SessionImpl:1317 - setting flush mode to: AUTO
              17:16:02,224 TRACE SessionImpl:301 - closing session
              17:16:02,224 TRACE ConnectionManager:398 - connection already null in cleanup : no action
              17:16:02,224 TRACE CacheSynchronization:114 - transaction after completion callback, status: 4
              17:16:02,224 TRACE JDBCContext:242 - after transaction completion
              17:16:02,224 TRACE SessionImpl:450 - after transaction completion
              

              • 4. Re: non ascii characters urlencoded by simple get
                Arturo Frappe Newbie

                Finally I got the bug.
                It was not in Seam.


                After processing a request a redirect is thrown between seam and icefaces.
                Seam URLEncodes the resulting URI with parameters and redirects to IceFaces, then IceFaces urlencodes the urlencoded passed by Seam, this is not a problem with ascii characters, and with US-dateformat. But with non-ascii characters and with dates formated with /  this double encoding screws-up every parameter.



                My solution was to patch IceFaces source to avoid the double URLEncoding.


                Look at icefaces 1.8.2 source code on BridgeExternalContext at 412 line.
                     


                  redirector.redirect(encodeResourceURL(uri.toString()));
                




                I just changed this line to


                       


                redirector.redirect(encodeResourceURL(uriString));
                




                This is not an Icefaces forum, I know, but since I find this bug using Seam, the solution is posted here.


                • 5. Re: non ascii characters urlencoded by simple get
                  judy guglielmin Novice

                  This can be tracked at jira ICE-5172.


                  If you have a simple sample that you could attach for testing purposes, it would be appreciated.