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>@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?