1 Reply Latest reply on Jul 4, 2013 9:25 AM by zschorn

    Problems with custom component in jsf 2

    rart3001_1

      Regards,

       

      I created a component to paint a menu, the component uses HtmlCommandLink to call navigation rules. The problem is that the component is displayed correctly, but when I click on a link does not redirect to the desired page.

       

      The code of the component is:

       

       

      import java.io.IOException;
      import java.text.Normalizer;
      import java.util.List;
      
      
      import javax.el.ExpressionFactory;
      import javax.el.MethodExpression;
      import javax.faces.application.Application;
      import javax.faces.component.FacesComponent;
      import javax.faces.component.StateHolder;
      import javax.faces.component.UIComponentBase;
      import javax.faces.component.html.HtmlCommandLink;
      import javax.faces.context.FacesContext;
      import javax.faces.context.ResponseWriter;
      
      
      import org.jboss.logging.Logger;
      
      
      import com.oficcomtechnology.model.Menu;
      
      
      /**
       * @author rrequena
       *
       */
      @FacesComponent(value = "HtmlMenu")
      public class HtmlMenu extends UIComponentBase implements StateHolder {
        
      
      
                private transient Logger LOG = Logger.getLogger(HtmlMenu.class);
      
      
          public static final String COMPONENT_TYPE = "oficcom.custom.component";
      
      
          public static final String COMPONENT_FAMILY = "oficcom.custom.component";
        
                private FacesContext context;
        
                private Application application;
        
                private ExpressionFactory expressionFactory;
      
      
                private String menuSeleccionado;
        
                public HtmlMenu() {
                          this.context = FacesContext.getCurrentInstance();
                          this.application = context.getApplication();
                          this.expressionFactory =  application.getExpressionFactory();
                          setParent(findComponent("formMenu"));
                          setRendererType(COMPONENT_TYPE);
                }
      
      
                /* (non-Javadoc)
                 * @see javax.faces.component.UIComponent#getFamily()
                 */
                @Override
                public String getFamily() {
                          return COMPONENT_FAMILY;
                }
        
                /* (non-Javadoc)
                 * @see javax.faces.component.UIComponentBase#getRendererType()
                 */
                @Override
          public String getRendererType() {
              return COMPONENT_TYPE; 
          }
        
      
        
                /* (non-Javadoc)
                 * @see javax.faces.component.UIComponent#encodeAll(javax.faces.context.FacesContext)
                 */
                @Override
          public void encodeAll(FacesContext context) throws IOException {
        
                          final ResponseWriter writer = context.getResponseWriter();
              
                          writer.startElement("ul", this);
              writer.writeAttribute("class", "big-menu", null);
              
              if (getValores() != null && getValores().size() > 0) {
        
                        for (Menu menu : getValores()) {
              
                                  if (menu.getMenuVisible()) {
                                            if (menu.getMenues() != null && menu.getMenues().size() > 0) {
                                                            encodeLiTagWithUl(menu, writer);
                                                  }else{
                                                            encodeLiTag(menu, writer);
                                                  }
                                              }
                                    }
              
                          }
              
              writer.endElement("ul");
          
          }
        
                /**
                 * Crea un elemento <li> para el menu hijo.
                 * 
                 * @param menu
                 * @param writer
                 */
                private void encodeLiTagWithUl(Menu menu, ResponseWriter writer){
        
          
                          try {
        
                                    //<li class="with-right-arrow">
                                    writer.startElement("li", this);
                                    writer.writeAttribute("class", "with-right-arrow", null);
        
                                              //<span><span class="list-count">5</span>Administracion</span>
                                              writer.startElement("span", this);
                                                        writer.startElement("span", this);
                                                        writer.writeAttribute("class", "list-count", null);
                                                                  writer.writeText(menu.getMenues().size(), null);
                                                        writer.endElement("span");
                                                        writer.writeText(menu.getNombre(), null);
                                              writer.endElement("span");
        
                                              //<ul class="big-menu">
                                              writer.startElement("ul", this);
                                  writer.writeAttribute("class", "big-menu", null);
        
                                           //Creamos los hijos
                                                        for (Menu menuHijo : menu.getMenues()) {
                                                                  if (menuHijo.getMenuVisible()) {
                                                                            if (menuHijo.getMenues() != null && menuHijo.getMenues().size() > 0) {
                                                                                      encodeLiTagWithUl(menuHijo, writer);
                                                                            }else{
                                                                                      encodeLiTag(menuHijo, writer);
                                                                            }
                                                                  }
                                                        }
      
      
                                              writer.endElement("ul");
                                    writer.endElement("li");
        
        
                          } catch (IOException e) {
                                    LOG.error(e);
                          }
      
      
                }
        
                /**
                 * Crea un elemento <li> para el menu hijo.
                 * 
                 * @param menu
                 * @param writer
                 */
                private void encodeLiTag(Menu menu, ResponseWriter writer){
        
                          //Creamos el id
                          String id = (removerAcentos(menu.getNombre()).replaceAll("\\s","")) + "Id";
                          MethodExpression me = expressionFactory.createMethodExpression(context.getELContext(), menu.getUrl(), String.class, new Class<?>[] {});
        
                          //<li><h:commandLink action="lista_configuraciones" >Configuraciones</h:commandLink></li>
        
                          try {
        
                                    writer.startElement("li", this);
        
                                              HtmlCommandLink link = (HtmlCommandLink) application.createComponent(HtmlCommandLink.COMPONENT_TYPE);
                                              link.setId(id); 
                                              link.setParent(this);
                                              link.setActionExpression(me);
                                              link.setValue(menu.getNombre());
                                              link.encodeAll(context);
        
                                    writer.endElement("li");
        
        
                          } catch (IOException e) {
                                    LOG.error(e);
                          }
      
      
                }
        
                /**
                 * Metodo encargado de remover acentos 
                 * @param s
                 * @return
                 */
                private String removerAcentos(String s) {
                    s = Normalizer.normalize(s, Normalizer.Form.NFD);
                    s = s.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
                    return s;
                }
      
      
                /**
                 * @return the valores
                 */
                @SuppressWarnings("unchecked")
                public List<Menu> getValores() { 
                          return (List<Menu>) getStateHelper().eval("valores");
                }
      
      
                /**
                 * @param valores the valores to set
                 */
                public void setValores(List<Menu> menus) {
                          getStateHelper().put("valores", menus);
                }
      
      
                /**
                 * @return the menuSeleccionado
                 */
                public String getMenuSeleccionado() {
                          return menuSeleccionado;
                }
      
      
                /**
                 * @param menuSeleccionado the menuSeleccionado to set
                 */
                public void setMenuSeleccionado(String menuSeleccionado) {
                          this.menuSeleccionado = menuSeleccionado;
                }
      

       

      I can observe on the console after clicking on a link is the following:

       

      16:27:04,584 INFO  [stdout] (http-localhost-127.0.0.1-7777-4) Unable to find state for component with clientId 'formMenu:ConfiguracionesId', not restoring it.
      

       

      if anyone can help me, thanks

        • 1. Re: Problems with custom component in jsf 2
          zschorn

          You are modifying the component tree in the wrong phase. This worked in jsf 1.2, but not in jsf 2 anymore. You really have to follow the spec, or you will get into a big mess. Do it with listenening to the prerenderevent. How to do it  is explained quite good here . This worked for me.