0

Two questions today,

I have this peace of code:

catalog.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
    <h:head>
        <f:facet name="first">
            <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        </f:facet>
        <title>booXtore - Catalog</title>
        <h:outputStylesheet library="css" name="main.css"/>
        <h:outputStylesheet library="css" name="font-awesome.css"/>
        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
            <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
        <![endif]-->
    </h:head>
    <h:body>
        <ui:include src="/WEB-INF/includes/navbar.xhtml"/>
        <div id="wrap">

            <div id="main" class="container clear-top">

                <ol class="breadcrumb">
                    <li class="active">Catalogue</li>
                </ol>

                <h:form >
                    <div class="row">
                        <div class="col-md-6">
                            <p:inputText id="searchBar" type="search" styleClass="form-control" placeholder="Recherche" value="#{searchProviderBean.search}"/>
                        </div>

                        <div class="col-md-4">
                            <h:selectOneMenu styleClass="form-control" value="#{searchProviderBean.searchCategory}">
                                <f:selectItem itemValue="#{searchProviderBean.defaultCategorySearch}" 
                                              itemLabel="#{searchProviderBean.defaultCategorySearch.name}"/>
                                <c:forEach items="#{searchProviderBean.categories}" var="category">
                                    <f:selectItem itemValue="#{category}"
                                                  itemLabel="#{category.name}"/>
                                </c:forEach>
                            </h:selectOneMenu>
                        </div>

                        <div class="col-md-2">
                            <h:commandLink class="btn btn-info" value="Rechercher" action="#{searchProviderBean.launchSearch}"/>
                        </div>
                    </div>
                </h:form>
            </div>
        </div>
    </h:body>
</hthml

SearchProviderBean:

package com.booXtore;

import com.booXtore.domain.Books;
import com.booXtore.domain.Categories;
import com.booXtore.service.BooksFacadeLocal;
import com.booXtore.service.CategoriesFacadeLocal;
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

@ManagedBean
@ViewScoped
public class SearchProviderBean implements Serializable {

    @EJB
    private BooksFacadeLocal bFL;
    @EJB
    private CategoriesFacadeLocal cFL;

    private String search;
    private Categories searchCategory;

    /**
     * Creates a new instance of SearchProviderBean
     */
    public SearchProviderBean() {
    }

    public List<Categories> getCategories() {
        List<Categories> result = cFL.findAll();

        return result;
    }

    public Categories getSearchCategory() {
        FacesContext fc = FacesContext.getCurrentInstance();
        for(Categories cat : this.cFL.findAll())
        {
            if(cat.getName().equalsIgnoreCase(getParam(fc, "category")))
            {
                this.searchCategory = cat;
            }
        }
        return this.searchCategory;
    }

    public void setSearchCategory(Categories searchCategory) {
        this.searchCategory = searchCategory;
    }

    public String launchSearch() {
        String cat = "";
        if(!this.searchCategory.getName().equalsIgnoreCase("Toutes Catégories"))
        {
            cat = "category=" + this.searchCategory.getName();
        }
        return "/catalog.xhtml?faces-redirect=true&search=" + search + cat;

    }

    public String getSearch() {
        FacesContext fc = FacesContext.getCurrentInstance();
        String searchParam = getParam(fc , "search");
        if(searchParam != null)
        {
            this.search = searchParam;
        }

        return search;
    }

    public void setSearch(String search) {
        this.search = search;
    }

    public Categories getDefaultCategorySearch()
    {
        Categories def = new Categories();
        def.setName("Toutes Catégories");
        return def;
    }

    public List<Books> getSearchResults() {
        return null;
    }

    public List<Books> getAllBooks()
    {
        return this.bFL.findAll();
    }

    private String getParam(FacesContext fc, String paramName)
    {
        return fc.getExternalContext().getRequestParameterMap().get(paramName);
    }

}

Then the problems:

  • The methods setSearch(String search) and setSearchCategory(Categories searchCategory) are never called (checked via breakpoints)

  • The commandLink action method is never called (checked via a breakpoint on the return statement) and only reloads the page.

I've tried to change the commandLink to a commandButton : no effect besides a style change I've tried to change the @ViewScoped annotation to @SessionScoped but no effect

EDIT:

Due to the size of the complete page and 'cause i'm quite new to jsf i didn't see the error message displayed at the bottom of the page which told me that there was an error converting the value of com.booXtore.domain.Category[ id=X ] for null converter

Cœur
  • 37,241
  • 25
  • 195
  • 267
Irwene
  • 2,807
  • 23
  • 48
  • 1
    Looks like there are conversion problems. Add a `` to check any conversion or other error that happens before the processing phase. – Luiggi Mendoza Nov 09 '13 at 19:19
  • There is actually a conversion problem , i just didn't see the error, i'm quite new to JSF an don't have the habit of looking on my browser for errors. The error is in the edited post. Any ideas on how to correct that ? – Irwene Nov 09 '13 at 19:32

1 Answers1

0

Found the Answer.

I just needed a converter for my object. For now, my class offered a ToString() method which allowed only to display my custom object.

From what i understood, the problem was that for saving the state of the object. Je JSF component tried to save the textual representation of my object. UNfortunately, the set method of the attribute didn't took the type String in argument but the type Categories.

I had to create a Converter class which allowed me to automatically convert my lbject one way to another (text<->object).

Here is the code i used :

package com.booXtore.converters;

import com.booXtore.domain.Categories;
import com.booXtore.service.CategoriesFacadeLocal;
import javax.ejb.EJB;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

/*The converter class has to be annotated and identified*/
@FacesConverter("com.booXtore.converters.CategoriesConverter")
public class CategoriesConverter implements Converter{

    @EJB
    private CategoriesFacadeLocal cFL;

    /*The method who will return an object based on the string passed by the JSF component*/
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if((value != null) || (Integer.parseInt(value) == -1))
        {
            Integer id = Integer.parseInt(value);
            return cFL.find(id);
        }
        Categories cat = new Categories();
        cat.setName("Toutes Catégories");
        return cat;
    }

    /*THe method wich will return the String that will represent the object*/
    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        Categories cat = (Categories)value;
        if(cat.getName().equals("Toutes Catégories"))
        {
            return "-1";
        }
        else
        {
            return cat.getId().toString();
        }
    }

}

i also had to add <f:converter converteedId="com.booXtore.converters.CategoriesConverter"/> in the <h:selectOneMenu> component to register the converter.

For a maybe more clear tutorial and a complete example here is the site wich helped me a lot : Custom Converter in JSF

Irwene
  • 2,807
  • 23
  • 48