4 Replies Latest reply on Dec 28, 2006 11:17 AM by gllambi

    selectItems+ajax4jsf

    gllambi

      I'm trying the new selectItems tag and had some problems with it when I tried to use it with ajax4jsf.

      I have two combos boxes. When the first is changed, the second one must refresh with new values. The problem is that when the first combo changes a Ilegal State Exception occurs.

      Here is the jsp

      <h:panelGrid id="panelGrid" columns="2">
       <h:outputText id="etiquetaUsuario" value="#{msg.socio}" />
       <s:decorate>
       <h:inputText id="inputUsuario" value="#{cliente.usuario}" size="30">
       <a4j:support id="soporteAjaxUsuario" event="onblur"
       reRender="errorUsuario" />
       </h:inputText>
       <a4j:outputPanel id="errorUsuario" styleClass="error">
       <s:message id="mensajeErrorUsuario" />
       </a4j:outputPanel>
       </s:decorate>
       <h:outputText id="etiquetaContraseña" value="#{msg.contraseña}" />
       <s:decorate>
       <h:inputText id="inputContraseña" value="#{cliente.pwd}" size="30">
       <a4j:support id="soporteAjaxContraseña" event="onblur"
       reRender="errorPassword" />
       </h:inputText>
       <a4j:outputPanel id="errorPassword" styleClass="error">
       <s:message id="mensajeErrorContraseña" />
       </a4j:outputPanel>
       </s:decorate>
       <h:outputText id="etiquetaPais" value="#{msg.pais}" />
       <h:selectOneMenu id="seleccionarPais"
       converter="#{registro.countryConverter}" required="true"
       value="#{cliente.country}">
       <si:selectItems value="#{paises}" var="pais"
       label="#{pais.countryCode}"
       noSelectionLabel="#{msg.selecionePais}" hideNoSelection="true"></si:selectItems>
       <a4j:support id="soporteAjaxPais" event="onchange"
       reRender="seleccionarEstado" />
       </h:selectOneMenu>
       <h:outputText id="etiquetaEstado" value="#{msg.estado}" />
       <h:selectOneMenu id="seleccionarEstado"
       converter="#{registro.stateConverter}" value="#{cliente.state}"
       required="true">
       <si:selectItems value="#{estados}" var="estado"
       label="#{estado.stateCode}"
       noSelectionLabel="#{msg.seleccioneEstado}" hideNoSelection="true"></si:selectItems>
       </h:selectOneMenu>
      </h:panelGrid>
      <a4j:commandButton id="botonAjax" value="Ajax #{msg.registrarse}"
       action="#{registro.registrarse}"
       reRender="formRegistro:mensajesErrorPanel"></a4j:commandButton>
      


      Here is the bean asociated with the page.

      /**
       *
       */
      package org.seam.ejemplo.validaciones.session;
      
      import java.util.List;
      
      import javax.ejb.Stateless;
      import javax.faces.convert.Converter;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.Factory;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Logger;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.core.FacesMessages;
      import org.jboss.seam.log.Log;
      import org.jboss.seam.selectitems.jsf.EntityConverter;
      import org.seam.ejemplo.validaciones.beans.Cliente;
      import org.seam.ejemplo.validaciones.beans.Country;
      import org.seam.ejemplo.validaciones.beans.State;
      
      /**
       * @author gllambi
       *
       */
      @Stateless
      @Name("registro")
      @Scope(ScopeType.EVENT)
      public class RegistroImpl implements Registro {
      
       @PersistenceContext
       private EntityManager em;
      
       @Logger
       private Log log;
      
       @In
       private Cliente cliente;
      
       public String registrarse() {
       log.info("Registrando al cliente...");
       List existing = em.createQuery(
       "select usuario from Cliente where usuario=:usuarioParam")
       .setParameter("usuarioParam", cliente.getUsuario())
       .getResultList();
      
       if (!existing.isEmpty()) {
       log.info("Ya existe!");
       FacesMessages.instance().add("El usuario ya existe: #{cliente.usuario}");
       return null;
      
       }else{
       em.persist(cliente);
       log.info("Se registró un cliente nuevo: #{cliente.usuario} #{cliente.pwd}");
       return "exito";
       }
       }
      
       @Factory("paises")
       public List obtenerPaises() {
       List paises = em.createQuery("from Country").getResultList();
       log.info("Hay "+paises.size()+" países.");
       return paises;
       }
      
       public void cambiarEstados(){
       log.info("Cambio los estados");
       }
      
       @Factory("estados")
       public List obtenerEstados() {
       List estados;
       if ((cliente!= null)&&(cliente.getCountry()!=null)){
       estados = em.createQuery("from State where country_id=:countryParam").
       setParameter("countryParam", cliente.getCountry().getCountryId()).getResultList();
       log.info("Hay "+estados.size()+" estados.");
       }
       else estados = em.createQuery("from State").getResultList();
       return estados;
       }
      
       public Converter getCountryConverter() {
       return new EntityConverter<Country>(){
       @Override
       protected Object getIdAsObject(String id, Class arg1) {
       return Integer.valueOf(id);
       }
      
       @Override
       protected String getIdAsString(Country entity) {
       return String.valueOf(entity.getCountryId());
       }
      
       };
       }
      
       public Converter getStateConverter() {
       return new EntityConverter<State>(){
       @Override
       protected Object getIdAsObject(String id, Class clazz) {
       return Integer.valueOf(id);
      
       }
      
       @Override
       protected String getIdAsString(State entity) {
       return String.valueOf(entity.getStateId());
       }
       };
       }
      
      }
      


      Here is the log

      2006-12-07 16:19:52,431 DEBUG [org.ajax4jsf.framework.renderer.AjaxContainerRenderer] Render Ajax Area component with ID :formRegistro:seleccionarEstado
      2006-12-07 16:19:52,431 DEBUG [org.jboss.seam.jsf.SeamVariableResolver] resolving name: registro
      2006-12-07 16:19:52,431 ERROR [org.apache.myfaces.lifecycle.PhaseListenerManager] Exception in PhaseListener RENDER_RESPONSE(6) afterPhase
      javax.faces.el.EvaluationException: Cannot get value for expression '#{registro.stateConverter}'
       at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:402)
       at javax.faces.component.UIOutput.getConverter(UIOutput.java:65)
       at org.jboss.seam.selectitems.ui.UISeamSelectItems.addConverters(UISeamSelectItems.java:297)
       at org.jboss.seam.selectitems.ui.UISeamSelectItems.getValue(UISeamSelectItems.java:192)
       at org.apache.myfaces.shared_impl.util.SelectItemsIterator.hasNext(SelectItemsIterator.java:102)
       at org.apache.myfaces.shared_impl.renderkit.RendererUtils.internalGetSelectItemList(RendererUtils.java:477)
       at org.apache.myfaces.shared_impl.renderkit.RendererUtils.getSelectItemList(RendererUtils.java:453)
       at org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils.internalRenderSelect(HtmlRendererUtils.java:277)
       at org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils.renderMenu(HtmlRendererUtils.java:251)
       at org.apache.myfaces.shared_impl.renderkit.html.HtmlMenuRendererBase.encodeEnd(HtmlMenuRendererBase.java:54)
       at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
       at org.ajax4jsf.framework.renderer.RendererBase.renderChild(RendererBase.java:249)
       at org.ajax4jsf.framework.renderer.AjaxContainerRenderer.encodeAjaxChild(AjaxContainerRenderer.java:197)
       at org.ajax4jsf.framework.renderer.AjaxContainerRenderer.encodeAjaxChild(AjaxContainerRenderer.java:190)
       at org.ajax4jsf.framework.renderer.AjaxContainerRenderer.encodeAjaxChild(AjaxContainerRenderer.java:190)
       at org.ajax4jsf.framework.renderer.AjaxContainerRenderer.encodeAjaxChild(AjaxContainerRenderer.java:190)
       at org.ajax4jsf.framework.renderer.AjaxContainerRenderer.encodeAjax(AjaxContainerRenderer.java:126)
       at org.ajax4jsf.framework.ajax.AjaxViewRoot.encodeAjax(AjaxViewRoot.java:570)
       at org.ajax4jsf.framework.ajax.AjaxContext.renderAjaxRegion(AjaxContext.java:260)
       at org.ajax4jsf.framework.renderer.AjaxPhaseListener.afterPhase(AjaxPhaseListener.java:96)
       at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersAfter(PhaseListenerManager.java:89)
       at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:391)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.servlet.SeamExceptionFilter.doFilter(SeamExceptionFilter.java:46)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.servlet.SeamRedirectFilter.doFilter(SeamRedirectFilter.java:32)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:67)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:223)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
       at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
       at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
       at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: java.lang.IllegalStateException: No application context active
       at org.jboss.seam.Component.forName(Component.java:1534)
       at org.jboss.seam.Component.getInstance(Component.java:1584)
       at org.jboss.seam.Component.getInstance(Component.java:1567)
       at org.jboss.seam.jsf.SeamVariableResolver.resolveVariable(SeamVariableResolver.java:45)
       at org.apache.myfaces.config.LastVariableResolverInChain.resolveVariable(LastVariableResolverInChain.java:42)
       at org.apache.myfaces.el.ValueBindingImpl$ELVariableResolver.resolveVariable(ValueBindingImpl.java:574)
       at org.apache.commons.el.NamedValue.evaluate(NamedValue.java:124)
       at org.apache.commons.el.ComplexValue.evaluate(ComplexValue.java:140)
       at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:383)
       ... 50 more
      2006-12-07 16:19:52,431 DEBUG [org.ajax4jsf.framework.DebugLifecycle] End phase RENDER_RESPONSE(6)
      2006-12-07 16:19:52,431 DEBUG [org.jboss.seam.util.Naming] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
      2006-12-07 16:19:52,431 DEBUG [org.jboss.seam.servlet.SeamExceptionFilter] ended request
      2006-12-07 16:19:52,431 DEBUG [org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter] Finished request processing total time 47ms for uri: /seam-validacion/view/registro.seam
      


      Thanks a lot

      Guzmán

        • 1. Re: selectItems+ajax4jsf
          pmuir

          Hmm. For some reason Seam/A4J aren't playing nicely when trying to access a converter via an EL expression - I don't think this is particularly related to SeamSelectItems. But it would be worth seeing whether you get a similar error if you just use f:selectItems (i.e. outject a

          List<SelectItem
          instead of si:selectitems.

          Also, if Country and State are Entities with numeric ids (and you are using annotations) (it looks to me as though they are) there is no need for you to implement the converter, the built in converter will do that for you.

          • 2. Re: selectItems+ajax4jsf
            gllambi

            I test it without the selectItem tag and the same exception is thrown

            I'm using seam1.1.0CR2, jboss 4.0.5 with the ejb profile and ajax4jsf-1.0.3 with jsp, not facelets. Also I'am usign my-faces-1.1.4

            Here I put the config files component.xml, faces-config.xml and web.xml

            <components>
            
             <component name="org.jboss.seam.core.init">
             <property name="debug">true</property>
             <property name="jndiPattern">seam-validacion/#{ejbName}/local</property>
             <property name="myFacesLifecycleBug">false</property>
             </component>
            
             <component class="org.jboss.seam.core.Microcontainer"
             installed="false" />
            
             <component name="em" class="org.jboss.seam.core.ManagedPersistenceContext">
             <property name="persistenceUnitJndiName">java:/selectItemsEntityManagerFactory</property>
             </component>
            
             <component class="org.jboss.seam.selectitems.SelectItemsConfig">
             <property name="persistenceUnitJndiName">java:/selectItemsEntityManagerFactory</property>
             </component>
            
            </components>
            


            <?xml version="1.0"?>
            <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
             "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
            <faces-config>
             <navigation-rule>
             <from-view-id>/view/registro_temp.jsp</from-view-id>
             <navigation-case>
             <from-outcome>exito</from-outcome>
             <to-view-id>/view/ok.jsp</to-view-id>
             </navigation-case>
             </navigation-rule>
             <lifecycle>
             <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
             </lifecycle>
            </faces-config>
            


            <?xml version="1.0" encoding="UTF-8"?>
            
            <web-app version="2.5"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
            
             <!-- Ajax4jsf (must come first!) -->
            
             <filter>
             <display-name>Ajax4jsf Filter</display-name>
             <filter-name>ajax4jsf</filter-name>
             <filter-class>org.ajax4jsf.Filter</filter-class>
             </filter>
            
             <filter-mapping>
             <filter-name>ajax4jsf</filter-name>
             <url-pattern>*.seam</url-pattern>
             </filter-mapping>
            
             <context-param>
             <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
             <param-value>org.jboss.seam.ui.facelet.SeamFaceletViewHandler</param-value>
             </context-param>
            
             <!-- Seam -->
            
             <listener>
             <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
             </listener>
            
             <!-- Propagate conversations across redirects -->
             <filter>
             <filter-name>Seam Redirect Filter</filter-name>
             <filter-class>org.jboss.seam.servlet.SeamRedirectFilter</filter-class>
             </filter>
            
             <filter-mapping>
             <filter-name>Seam Redirect Filter</filter-name>
             <url-pattern>*.seam</url-pattern>
             </filter-mapping>
            
             <filter>
             <filter-name>Seam Exception Filter</filter-name>
             <filter-class>org.jboss.seam.servlet.SeamExceptionFilter</filter-class>
             </filter>
            
             <filter-mapping>
             <filter-name>Seam Exception Filter</filter-name>
             <url-pattern>*.seam</url-pattern>
             </filter-mapping>
            
             <!-- JSF -->
            
             <context-param>
             <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
             <param-value>client</param-value>
             </context-param>
            
             <servlet>
             <servlet-name>Faces Servlet</servlet-name>
             <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
             <load-on-startup>1</load-on-startup>
             </servlet>
            
             <!-- Faces Servlet Mapping -->
             <servlet-mapping>
             <servlet-name>Faces Servlet</servlet-name>
             <url-pattern>*.seam</url-pattern>
             </servlet-mapping>
            
             <!-- MyFaces -->
             <listener>
             <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
             </listener>
            
             <!-- JSF RI -->
             <!--
             <listener>
             <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
             </listener>
             -->
            </web-app>
            


            Thanks,

            Guzmán

            • 3. Re: selectItems+ajax4jsf

              Are there any news here? I experienced this issue now twice, with ajax4jsf and icefaces... :(

              • 4. Re: selectItems+ajax4jsf
                gllambi

                 

                "atzbert" wrote:
                Are there any news here? I experienced this issue now twice, with ajax4jsf and icefaces... :(


                After some work, I found a solution to the problem. It isn't from the selectItem tag. It is a problem of using ajax4jsf with jsf and seam together.

                To make it work you must use the region and page ajax4jsf's tags.

                The tag page must go after the jsf view tag. This is due a problem of ajax4jsf and myfaces. More explanation of this is found in the ajax4jsf page.

                Then put the combo between the region tag. If you want to refresh something outside of the region, you have to set the option renderRegionOnly to false

                Here is the code that worked for me.

                <f:view>
                <a4j:page>
                 <h:outputText id="titulo" value="#{msg.titulo_registro}" />
                 <h:form id="formRegistro">
                 <a4j:outputPanel id="mensajesErrorPanel" styleClass="error">
                 <div><h:messages id="mensajesError" /></div>
                 </a4j:outputPanel>
                 <s:validateAll>
                 <h:panelGrid id="panelGrid" columns="2">
                 <h:outputText id="etiquetaUsuario" value="#{msg.socio}" />
                 <a4j:region id="regionUsuario">
                 <s:decorate>
                 <h:inputText id="inputUsuario" value="#{cliente.usuario}"
                 size="30" required="true">
                 <a4j:support id="soporteAjaxUsuario" event="onblur"
                 reRender="errorUsuario" />
                 </h:inputText>
                 <a4j:outputPanel id="errorUsuario" styleClass="error">
                 <s:message id="mensajeErrorUsuario" />
                 </a4j:outputPanel>
                 </s:decorate>
                 </a4j:region>
                 <h:outputText id="etiquetaContraseña" value="#{msg.contraseña}" />
                 <a4j:region id="regionContraseña">
                 <s:decorate>
                 <h:inputText id="inputContraseña" value="#{cliente.pwd}"
                 size="30" required="true">
                 <a4j:support id="soporteAjaxContraseña" event="onblur"
                 reRender="errorPassword" />
                 </h:inputText>
                 <a4j:outputPanel id="errorPassword" styleClass="error">
                 <s:message id="mensajeErrorContraseña" />
                 </a4j:outputPanel>
                 </s:decorate>
                 </a4j:region>
                 <h:outputText id="etiquetaPais" value="#{msg.pais}" />
                 <a4j:region id="regionPaises" renderRegionOnly="false">
                 <s:decorate>
                 <h:selectOneMenu id="seleccionarPais"
                 converter="#{registro.countryConverter}" required="true"
                 value="#{cliente.country}">
                 <si:selectItems value="#{paises}" var="pais"
                 label="#{pais.countryCode}"
                 noSelectionLabel="#{msg.selecionePais}" hideNoSelection="true"></si:selectItems>
                 <a4j:outputPanel id="errorPais" styleClass="error">
                 <s:message id="mensajeErrorPais" />
                 </a4j:outputPanel>
                 <a4j:support id="soporteAjaxPais" event="onchange"
                 reRender="seleccionarEstado, mensajeErrorPais"
                 action="#{registro.cambiarEstados}" />
                 </h:selectOneMenu>
                 </s:decorate>
                 </a4j:region>
                 <h:outputText id="etiquetaEstado" value="#{msg.estado}" />
                 <a4j:region id="regionEstados">
                 <h:selectOneMenu id="seleccionarEstado"
                 converter="#{registro.stateConverter}" value="#{cliente.state}">
                 <si:selectItems value="#{estados}" var="estado"
                 label="#{estado.stateCode}"
                 noSelectionLabel="#{msg.seleccioneEstado}"
                 hideNoSelection="true"></si:selectItems>
                 </h:selectOneMenu>
                 </a4j:region>
                 </h:panelGrid>
                 <a4j:commandButton id="botonAjax" value="Ajax #{msg.registrarse}"
                 action="#{registro.registrarse}"
                 reRender="formRegistro:mensajesErrorPanel"></a4j:commandButton>
                 </s:validateAll>
                 </h:form>
                 </a4j:page>
                </f:view>