0

good morning.

I am trying to create a simple page that lists in a dropdown all countries and then, after I choose a country the autocomplete for State shows up and after 3 chars typed it performs the autocomplete. It seems to be a simple issue.

So, this is my State model

package br.com.danielfc.model;

// Generated 27/08/2015 23:59:43 by Hibernate Tools 4.3.1

import static javax.persistence.GenerationType.IDENTITY;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * State generated by hbm2java
 */
@Entity
@Table(name = "State", catalog = "daniel")
@NamedQuery(name = "State.findStateByName", query = "select s from State s where s.country.iso = :iso and s.name like :name ")
public class State implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 4498876370214791673L;
    private Integer id;
    private Country country;
    private String name;
    /*Stands for Federative Unit*/
    private String fu;
    private Set<City> cities = new HashSet<City>(0);

    public State() {
    }

    public State(Country country, String name, String fu) {
        this.country = country;
        this.name = name;
        this.fu = fu;
    }

    public State(Country country, String name, String fu, Set<City> cities) {
        this.country = country;
        this.name = name;
        this.fu = fu;
        this.cities = cities;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "countryIso", nullable = false, referencedColumnName = "iso")
    public Country getCountry() {
        return this.country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }

    @Column(name = "name", nullable = false, length = 45)
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "fu", nullable = false, length = 2)
    public String getFu() {
        return this.fu;
    }

    public void setFu(String fu) {
        this.fu = fu;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "state")
    public Set<City> getCities() {
        return this.cities;
    }

    public void setCities(Set<City> cities) {
        this.cities = cities;
    }
}

This is my StateBean

package br.com.danielfc.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import br.com.danielfc.model.State;
import br.com.danielfc.model.City;
import br.com.danielfc.model.Country;

import java.util.Iterator;

/**
 * Backing bean for State entities.
 * <p/>
 * This class provides CRUD functionality for all State entities. It focuses
 * purely on Java EE 6 standards (e.g. <tt>&#64;ConversationScoped</tt> for
 * state management, <tt>PersistenceContext</tt> for persistence,
 * <tt>CriteriaBuilder</tt> for searches) rather than introducing a CRUD
 * framework or custom base class.
 */

@Named
@Stateful
@ConversationScoped
public class StateBean implements Serializable {

    private static final long serialVersionUID = 1L;

    /*
     * Support creating and retrieving State entities
     */

    private Integer id;

    private State state;

    @Inject
    private Conversation conversation;

    @PersistenceContext(unitName = "RentACar-persistence-unit", type = PersistenceContextType.EXTENDED)
    private EntityManager entityManager;

    private int page;

    private long count;

    private List<State> pageItems;

    private State example = new State();

    @Resource
    private SessionContext sessionContext;

    private State add = new State();

    public String create() {

        this.conversation.begin();
        this.conversation.setTimeout(1800000L);
        return "create?faces-redirect=true";
    }

    /*
     * Support updating and deleting State entities
     */

    public String delete() {
        this.conversation.end();

        try {
            State deletableEntity = findById(getId());
            Country country = deletableEntity.getCountry();
            country.getStates().remove(deletableEntity);
            deletableEntity.setCountry(null);
            this.entityManager.merge(country);
            Iterator<City> iterCities = deletableEntity.getCities().iterator();
            for (; iterCities.hasNext();) {
                City nextInCities = iterCities.next();
                nextInCities.setState(null);
                iterCities.remove();
                this.entityManager.merge(nextInCities);
            }
            this.entityManager.remove(deletableEntity);
            this.entityManager.flush();
            return "search?faces-redirect=true";
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(e.getMessage()));
            return null;
        }
    }

    public State findById(Integer id) {

        return this.entityManager.find(State.class, id);
    }

    /*
     * Support searching State entities with pagination
     */

    public State getAdd() {
        return this.add;
    }
    public State getAdded() {
        State added = this.add;
        this.add = new State();
        return added;
    }
    public List<State> getAll() {

        CriteriaQuery<State> criteria = this.entityManager.getCriteriaBuilder()
                .createQuery(State.class);
        return this.entityManager.createQuery(
                criteria.select(criteria.from(State.class))).getResultList();
    }

    /*
     * AutoComplete input box for state
     */
    public List<State> getAllByCountry(Country country, String name) {
        CriteriaQuery<State> criteria = this.entityManager.getCriteriaBuilder()
                .createQuery(State.class);
        TypedQuery<State> query = entityManager.createQuery(criteria.select(criteria.from(State.class)));
        query.setParameter("iso", country.getIso());
        query.setParameter("name", "%"+name);
        List<State> retorno = query.getResultList();
        return retorno;
    }

    public Converter getConverter() {

        final StateBean ejbProxy = this.sessionContext
                .getBusinessObject(StateBean.class);

        return new Converter() {

            @Override
            public Object getAsObject(FacesContext context,
                    UIComponent component, String value) {

                return ejbProxy.findById(Integer.valueOf(value));
            }

            @Override
            public String getAsString(FacesContext context,
                    UIComponent component, Object value) {

                if (value == null) {
                    return "";
                }

                return String.valueOf(((State) value).getId());
            }
        };
    }

    public long getCount() {
        return this.count;
    }

    public State getExample() {
        return this.example;
    }

    public Integer getId() {
        return this.id;
    }

    public int getPage() {
        return this.page;
    }

    public List<State> getPageItems() {
        return this.pageItems;
    }

    public int getPageSize() {
        return 10;
    }

    private Predicate[] getSearchPredicates(Root<State> root) {

        CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
        List<Predicate> predicatesList = new ArrayList<Predicate>();

        Country country = this.example.getCountry();
        if (country != null) {
            predicatesList.add(builder.equal(root.get("country"), country));
        }
        String name = this.example.getName();
        if (name != null && !"".equals(name)) {
            predicatesList.add(builder.like(
                    builder.lower(root.<String> get("name")),
                    '%' + name.toLowerCase() + '%'));
        }
        String fu = this.example.getFu();
        if (fu != null && !"".equals(fu)) {
            predicatesList.add(builder.like(
                    builder.lower(root.<String> get("fu")),
                    '%' + fu.toLowerCase() + '%'));
        }

        return predicatesList.toArray(new Predicate[predicatesList.size()]);
    }

    public State getState() {
        return this.state;
    }

    public void paginate() {

        CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

        // Populate this.count

        CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
        Root<State> root = countCriteria.from(State.class);
        countCriteria = countCriteria.select(builder.count(root)).where(
                getSearchPredicates(root));
        this.count = this.entityManager.createQuery(countCriteria)
                .getSingleResult();

        // Populate this.pageItems

        CriteriaQuery<State> criteria = builder.createQuery(State.class);
        root = criteria.from(State.class);
        TypedQuery<State> query = this.entityManager.createQuery(criteria
                .select(root).where(getSearchPredicates(root)));
        query.setFirstResult(this.page * getPageSize()).setMaxResults(
                getPageSize());
        this.pageItems = query.getResultList();
    }

    /*
     * Support listing and POSTing back State entities (e.g. from inside an
     * HtmlSelectOneMenu)
     */

    public void retrieve() {

        if (FacesContext.getCurrentInstance().isPostback()) {
            return;
        }

        if (this.conversation.isTransient()) {
            this.conversation.begin();
            this.conversation.setTimeout(1800000L);
        }

        if (this.id == null) {
            this.state = this.example;
        } else {
            this.state = findById(getId());
        }
    }

    public String search() {
        this.page = 0;
        return null;
    }

    public void setExample(State example) {
        this.example = example;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    /*
     * Support adding children to bidirectional, one-to-many tables
     */

    public void setPage(int page) {
        this.page = page;
    }

    public void setState(State state) {
        this.state = state;
    }

    public String update() {
        this.conversation.end();

        try {
            if (this.id == null) {
                this.entityManager.persist(this.state);
                return "search?faces-redirect=true";
            } else {
                this.entityManager.merge(this.state);
                return "view?faces-redirect=true&id=" + this.state.getId();
            }
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(e.getMessage()));
            return null;
        }
    }
}

And this is my Address model

package br.com.danielfc.model;

// Generated 27/08/2015 23:59:43 by Hibernate Tools 4.3.1

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * Address generated by hbm2java
 */
@Entity
@Table(name = "Address", catalog = "daniel")
public class Address implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -7374915404433933232L;
    private Integer id;
    private AddressType addressType;
    private int typeSite;
    private String streetName;
    private String city;
    private String country;
    private String zipcode;

    public Address() {
    }

    public Address(int typeSite) {
        this.typeSite = typeSite;
    }

    public Address(AddressType addressType, int typeSite, String streetName,
            String city, String country, String zipcode) {
        this.addressType = addressType;
        this.typeSite = typeSite;
        this.streetName = streetName;
        this.city = city;
        this.country = country;
        this.zipcode = zipcode;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "addressType")
    public AddressType getAddressType() {
        return this.addressType;
    }

    public void setAddressType(AddressType addressType) {
        this.addressType = addressType;
    }

    @Column(name = "typeSite", nullable = false)
    public int getTypeSite() {
        return this.typeSite;
    }

    public void setTypeSite(int typeSite) {
        this.typeSite = typeSite;
    }

    @Column(name = "streetName", length = 45)
    public String getStreetName() {
        return this.streetName;
    }

    public void setStreetName(String streetName) {
        this.streetName = streetName;
    }

    @Column(name = "city", length = 45)
    public String getCity() {
        return this.city;
    }

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

    @Column(name = "country", length = 45)
    public String getCountry() {
        return this.country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Column(name = "zipcode", length = 45)
    public String getZipcode() {
        return this.zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

}

And this is a part of my jsf page that I would like to have the behaviour explained before.

                    <h:outputLabel for="addressBeanExampleCountry" value="Country:" />
                    <h:panelGroup>
                        <!-- <h:inputText id="addressBeanExampleCountry" maxLength="45" value="#{addressBean.example.country}"/> -->
                        <h:selectOneMenu id="addressBeanExampleCountry" value="#{addressBean.example.country}">
                            <f:selectItem />
                            <f:selectItems itemLabel="#{forgeview:display(_item.name)}" itemValue="#{_item}" value="#{countryBean.all}" var="_item" />
                        </h:selectOneMenu>
                        <h:message for="addressBeanExampleCountry" styleClass="error" />
                    </h:panelGroup>
                    <h:outputText />

                    <h:outputLabel for="addressBeanExampleState" value="State:" rendered="#{not empty addressBean.example.country}"/>
                    <h:panelGroup rendered="#{not empty addressBean.example.country}">
                        <p:autoComplete id="state" value="#{stateBean.state}" completeMethod="#{stateBean.getAllByCountry()}" minQueryLength="3"/>
                        <h:message for="addressBeanExampleState" styleClass="error" />
                    </h:panelGroup>

The problem is that the method is not evoked and the autocomplete does not shows after I choose the country.

What seems to be wrong? What is the best/correct way to implement this logic for autocomplete?

  • Don't mix `CDI` and `EJB` like that. Create `CDI` bean and `@Inject` or `@EJB` your `EJB` to it. Your `getAllByCountry(Country country, String name)` method have 2 parameters but you invoke it in EL without any `#{stateBean.getAllByCountry()}`. Probably you want to get them from other bean (`#{addressBean.example.country}`) – Geinmachi Sep 14 '15 at 18:28
  • Yes, but this was created using forge scaffolding procedures. The getAllByCountry() is not beeing invoked yet because the panelgroup is not being rendered. That is part of the problem as described above. Why after I choose the country the panelGroup does not shows up? – Daniel Ferreira Castro Sep 14 '15 at 18:44
  • When you choose something it is not seen in backing bean yet, only when you submit form. If you want to see value immediately then you can do partial processing, and update your panel, but first wrap it with some element. Things to add are: `` for `` and for example `` for your existing ``. Probably there are more things to fix. – Geinmachi Sep 14 '15 at 19:00
  • Create an mcve. To much noise. – Kukeltje Sep 15 '15 at 20:27
  • @Kukeltje, what is a MCVE? Any good reads about that to recommend me? I google it but no results so far. Thanks for the tip anyway. – Daniel Ferreira Castro Sep 16 '15 at 12:10
  • @Geinmachi What would be a good and clear way to implement my idea? You strongly recommend me to no mix EJB and CDI. Ok, I agree with that, it may improve readability and that is awesome. But what would be a good pattern to achieve the autocomplete logic, the EJB that does the CRUD operations and a lazy datatable way to show results? – Daniel Ferreira Castro Sep 16 '15 at 12:16
  • [MVCE](http://stackoverflow.com/help/mcve) In `CDI` you should focus on modeling your `xhtml` file and doing logic in `EJB`. Does your `` render now? If yes then method in `completeMethod` has to take only 1 `String` parameter, your method takes 2 so it won't invoke. Check more `autoComplete` examples [here](http://www.primefaces.org/showcase/ui/input/autoComplete.xhtml). Good example would be implementing `completeMethod` the way that it forwards logic to injected `EJB`. – Geinmachi Sep 16 '15 at 12:51
  • and also here: https://stackoverflow.com/tags/jsf/info – Kukeltje Sep 16 '15 at 13:46

0 Answers0