#ManyToMany no entries in linking table - jsf

Perhaps someone here can give me a tip where the error could be situated (JSF 2.2, Glassfish 4.0):
I have two entities with a manytomany relation (see example)
When I deploy my project in glassfish all tables (also the linking table) are generated correctly (create-tables enabled in persistence.xml): TAGUSERWISH, TAGUSERWISH_WISH (linking table), WISH
When I execute a persist (see example) entity "wish" and "tagUserWish" is persisted correctly, but nothing is written into the linking table when I look directly into the mysql table. But when I read "wish" out with JPA, the List<TagUserWish> is filled
As soon as a new session starts (redeploy) List<TagUserWish> is also empty when read out with JPA
Owner entity:
#Entity
public class Wish implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String subject;
private String abstractT;
#OneToOne
private User user;
#ManyToMany(mappedBy = "wishes", cascade = {CascadeType.ALL} )
private List<TagUserWish> tags = new LinkedList<>();
public void addTag(TagUserWish tag){
tags.add(tag);
}
public void setTags(List<TagUserWish> tags) {
this.tags = tags;
}
public void removeTag(TagUserWish tag){
tags.remove(tag);
}
public List<TagUserWish> getTags(){
return tags;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getAbstractT() {
return abstractT;
}
public void setAbstractT(String abstractT) {
this.abstractT = abstractT;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Wish)) {
return false;
}
Wish other = (Wish) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "eu.citato.main.model.Wish[ id=" + id + " ]";
}
}
Entity 2:
#Entity
public class TagUserWish implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
public TagUserWish() {
}
public TagUserWish(String name) {
this.name = name;
}
#ManyToMany
private List<Wish> wishes = new LinkedList<>();
public void addWish(Wish wish){
wishes.add(wish);
}
public void setWishes(List<Wish> wishes) {
this.wishes = wishes;
}
public void removeWish(Wish tag){
wishes.remove(tag);
}
public List<Wish> getWishes(){
return wishes;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof TagUserWish)) {
return false;
}
TagUserWish other = (TagUserWish) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "eu.citato.main.model.Tag[ id=" + id + ", name="+name+" ]";
}
}
How I persist it:
#javax.inject.Named
#SessionScoped
public class WishPM implements Serializable {
#EJB
private WishService wls;
public void commitEditWish(){
List<TagUserWish> selTags = new ArrayList<>();
selTags.add(new TagUserWish("Tag1"));
selTags.add(new TagUserWish("Tag2"));
currentWish = new Wish();
currentWish.setSubject("wishSubject");
currentWish.setAbstractT("wishAbstract");
currentWish.setTags(selTags);
wls.createWish(currentWish);
}
}
And the wish Service:
#Stateless
public class WishService implements Serializable{
#PersistenceContext(unitName = "WishlistPU")
private EntityManager em;
public void createWish(Wish entity){
em.persist(entity);
}
}

Relationships are persisted based to the owner side of relationship. Owner of the bidirectional relationship is one that is value of mappedBy in inverse side. In following case owner of the relationship is wishes field in TagUserWish entity
#ManyToMany(mappedBy = "wishes", cascade = {CascadeType.ALL} )
private List<TagUserWish> tags = new LinkedList<>();
Because instance of TagUserWish do have empty wishes collection, relationship is not persisted. Problem can be solved by adding related Wish to the instance of TagUserWish, for example as follows:
...
TagUserWish tuw1 = new TagUserWish("Tag1")
TagUserWish tuw2 = new TagUserWish("Tag2")
selTags.add(tuw1);
selTags.add(tuw2);
currentWish = new Wish();
tuw1.addWish(currentWish); //setting to owner side of relationship
tuw2.addWish(currentWish); //setting to owner side of relationship
...

Related

Lombok #EqualsAndHashCode and Jhipster TestUtil.equalsVerifier

I am using Jhipster and Lombok for my Java project.
I removed the entity object equals() and hashcode() method generated by Jhipster and replaced with lombok #EqualsAndHashCode
Originally generated By Jhipster
#Entity
#Table(name = "category")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Size(max = 100)
#Column(name = "name", length = 100)
private String name;
// jhipster-needle-entity-add-field - JHipster will add fields here
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public Category name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Category)) {
return false;
}
return id != null && id.equals(((Category) o).id);
}
#Override
public int hashCode() {
return 31;
}
// prettier-ignore
#Override
public String toString() {
return "Category{" +
"id=" + getId() +
", name='" + getName() + "'" +
"}";
}
}
Modified to use Lombok
#Entity
#Data
#EqualsAndHashCode(callSuper = true)
#Table(name = "category")
public class Category extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Size(max = 100)
#Column(name = "name", length = 100)
private String name;
}
The problem is the test generated by Jhipster below fails. At the last 2 lines of the test
/**
* Verifies the equals/hashcode contract on the domain object.
*/
public static <T> void equalsVerifier(Class<T> clazz) throws Exception {
T domainObject1 = clazz.getConstructor().newInstance();
assertThat(domainObject1.toString()).isNotNull();
assertThat(domainObject1).isEqualTo(domainObject1);
assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode());
// Test with an instance of another class
Object testOtherObject = new Object();
assertThat(domainObject1).isNotEqualTo(testOtherObject);
assertThat(domainObject1).isNotEqualTo(null);
// Test with an instance of the same class
T domainObject2 = clazz.getConstructor().newInstance();
assertThat(domainObject1).isNotEqualTo(domainObject2); //this fails
// HashCodes are equals because the objects are not persisted yet
assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode()); //this also fails
}
May I know what is the purpose of the test?
every clazz.getConstructor().newInstance(); object should not be equal with each other? The content of the object is the same. Why not?
every clazz.getConstructor().newInstance(); object should have same hashCode? If so, why lombok #EqualsAndHashCode gives different hashcode?
How can I fix the problem?
*Note that the class extends AbstractAuditingEntity
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#CreatedBy
#Column(name = "created_by", nullable = false, length = 50, updatable = false)
#JsonIgnore
private String createdBy;
#CreatedDate
#Column(name = "created_date", updatable = false)
#JsonIgnore
private Instant createdDate = Instant.now();
#LastModifiedBy
#Column(name = "last_modified_by", length = 50)
#JsonIgnore
private String lastModifiedBy;
#LastModifiedDate
#Column(name = "last_modified_date")
#JsonIgnore
private Instant lastModifiedDate = Instant.now();
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Instant lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}

Get JSF Drop down value and save to database [duplicate]

This question already has answers here:
How to populate options of h:selectOneMenu from database?
(5 answers)
Closed 7 years ago.
I have two tables into database: Book and Category. Now I want to make page where user can add books into Book table, but with selecting appropriate category from Category table.
I can add book into table but I can not save value category in Book table.
[
As you can see category from Book table is Foreign key with category_id from Category table.
Here are model classes:
Book model
#Entity
#Table(name = "book")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Book.findAll", query = "SELECT b FROM Book b"),
#NamedQuery(name = "Book.findByBookId", query = "SELECT b FROM Book b WHERE b.bookId = :bookId")})
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "book_id")
private Integer bookId;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 65535)
#Column(name = "name")
private String name;
#Lob
#Size(max = 65535)
#Column(name = "description")
private String description;
#JoinColumn(name = "category", referencedColumnName = "category_id")
#ManyToOne
private Category category;
public Book() {
}
public Book(Integer bookId) {
this.bookId = bookId;
}
public Book(Integer bookId, String name) {
this.bookId = bookId;
this.name = name;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
#Override
public int hashCode() {
int hash = 0;
hash += (bookId != null ? bookId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Book)) {
return false;
}
Book other = (Book) object;
if ((this.bookId == null && other.bookId != null) || (this.bookId != null && !this.bookId.equals(other.bookId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.biblioteka.app.domen.Book[ bookId=" + bookId + " ]";
}
}
Category model
#Entity
#Table(name = "category")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Category.findAll", query = "SELECT c FROM Category c"),
#NamedQuery(name = "Category.findByCategoryId", query = "SELECT c FROM Category c WHERE c.categoryId = :categoryId")})
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "category_id")
private Integer categoryId;
#Basic(optional = false)
#NotNull
#Lob
#Size(min = 1, max = 65535)
#Column(name = "name")
private String name;
#Lob
#Size(max = 65535)
#Column(name = "description")
private String description;
#OneToMany(mappedBy = "category")
private Collection<Book> bookCollection;
public Category() {
}
public Category(Integer categoryId) {
this.categoryId = categoryId;
}
public Category(Integer categoryId, String name) {
this.categoryId = categoryId;
this.name = name;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#XmlTransient
public Collection<Book> getBookCollection() {
return bookCollection;
}
public void setBookCollection(Collection<Book> bookCollection) {
this.bookCollection = bookCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (categoryId != null ? categoryId.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Category)) {
return false;
}
Category other = (Category) object;
if ((this.categoryId == null && other.categoryId != null) || (this.categoryId != null && !this.categoryId.equals(other.categoryId))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.biblioteka.app.domen.Category[ categoryId=" + categoryId + " ]";
}
}
Now I have JSF page where I add bookes to database. I have dropdown lists that loads categories into it. User should select one category and save book to table.
This is code from JSF addBook page.
<p:layoutUnit position="center">
<h:form>
<p:inputText value="#{bookBean.name}" a:placeholder="Ime knjige"></p:inputText><br/>
<p:inputText value="#{bookBean.description}" a:placeholder="Opis knjige"></p:inputText><br/>
<p:selectOneMenu value="#{bookBean.category}">
<f:selectItems value="#{categoryBean.allCategories}" var="c"
itemLabel="#{c.name}" itemValue="#{c.categoryId}"/>
</p:selectOneMenu>
<b/><b/>
<p:commandButton value="Dodaj knjigu" action="#{bookBean.addBook()}"/>
</h:form>
</p:layoutUnit>
As you can see I use selectOneMenu with value bookBean.category and then I am not sure what I need to set as value in selectItems.
This is BookBean code:
#ManagedBean
#ApplicationScoped
public class BookBean {
String name;
String description;
int categoryId;
Category category;
#Inject
public BookEJB bookEJB;
public void addBook(){
Book book = new Book();
book.setName(name);
book.setDescription(description);
book.setCategory(category);
bookEJB.addBook(book);
}
public List<Book> getAllBooks(){
return bookEJB.getAll();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getCategoryId() {
return categoryId;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public BookEJB getBookEJB() {
return bookEJB;
}
public void setBookEJB(BookEJB bookEJB) {
this.bookEJB = bookEJB;
}
}
Try this :
<f:selectItems value="#{categoryBean.allCategories}" var="c"
itemLabel="#{c.name}" itemValue="#{c}"/>
Listed item name would be category name and category will be assigned to bookBean.category and this can be set as book category and persisted.
Hope this helps.

JSF issue with Scopes

Following is my managed bean code:
public class SelectEntries implements Serializable {
private static final long serialVersionUID = 1217595612573680L;
private List<SelectEntry> selectEntries = new ArrayList<SelectEntry>();
private SelectEntry selectEntry;
#PostConstruct
private void init() {
selectEntries.add(new SelectEntry("1001", new CheckEntry("Line 1"),
new CheckEntry("Line 2"), new CheckEntry("Line 3")));
selectEntries.add(new SelectEntry("1002", new CheckEntry("Line 4"),
new CheckEntry("Line 5"), new CheckEntry("Line 6")));
selectEntries.add(new SelectEntry("1003", new CheckEntry("Line 7"),
new CheckEntry("Line 8"), new CheckEntry("Line 9")));
}
public List<SelectEntry> getSelectEntries() {
return selectEntries;
}
public void setSelectEntries(List<SelectEntry> selectEntries) {
this.selectEntries = selectEntries;
}
public SelectEntry getSelectEntry() {
return selectEntry;
}
public void setSelectEntry(SelectEntry selectEntry) {
this.selectEntry = selectEntry;
}
public String getTemplatesString() {
String templatesString = "";
for (CheckEntry oneCheckEntry : getSelectEntry().getCheckEntries()) {
if (oneCheckEntry.getCheck()) {
templatesString += oneCheckEntry.getName();
}
}
return templatesString;
}
}
Here is the SelectEntry class:
public class SelectEntry implements Serializable {
private static final long serialVersionUID = 7298341984562171094L;
private String name;
private List<CheckEntry> checkEntries = new ArrayList<CheckEntry>();
public SelectEntry(String name, CheckEntry... checkEntries) {
this.name = name;
if (checkEntries != null) {
this.checkEntries.addAll(Arrays.asList(checkEntries));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CheckEntry> getCheckEntries() {
return checkEntries;
}
public void setCheckEntries(List<CheckEntry> checkEntries) {
this.checkEntries = checkEntries;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SelectEntry other = (SelectEntry) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
And the CheckEntry class:
public class CheckEntry implements Serializable {
private static final long serialVersionUID = 1730874183104100662L;
private String name;
private Boolean check;
public CheckEntry(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getCheck() {
return check;
}
public void setCheck(Boolean check) {
this.check = check;
}
}
I have a simple function in the managed bean to get create a String on the bases of which check entries have been selected.This only functions with SessionScope and if I use RequestScope, the boolean values of CheckEntries are null and I get runtime error. Why is it so?
As per JEE7 tutorial:
Request (#RequestScoped): Request scope persists during a single HTTP
request in a web application. In an application like hello1, where
the application consists of a single request and response, the bean
uses request scope.
So once your page is loaded, the resquest scoped backing bean is gone for subsequent interactions (even ajax).
You should note that it is encouraged to use the scopes from package javax.enterprise.context
For your application, looks like the minimum scope required is ViewScope. Since javax.enterprise.context doesn't implement view scope, you might consider using Omnifaces.

PickList PrimeFaces not working

I try to use the pickList component of Primefaces. My converter does not work properly and I don't know why.
This is my ManagedBean:
#ManagedBean(name = "comMB")
#SessionScoped
public class TeamCompetitionBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private DualListModel<Team> teams;
List<Team> source;
List<Team> source1;
List<Team> target;
#ManagedProperty("#{team}")
private TeamServiceI teamService;
List<String> teamNameList ;
// public TeamCompetitionBean() {
public DualListModel<Team> getTeams() {
// Players
teamNameList = new ArrayList<String>();
source = new ArrayList<Team>();
target = new ArrayList<Team>();
source.addAll(getTeamService().getTeam());
teams = new DualListModel<Team>(source, target);
return teams;
}
public void setTeams(DualListModel<Team> teams) {
this.teams = teams;
}
public void onTransfer(TransferEvent event) {
StringBuilder builder = new StringBuilder();
for (Object item : event.getItems()) {
builder.append(((Team) item).getTeamName()).append("<br />");
}
FacesMessage msg = new FacesMessage();
msg.setSeverity(FacesMessage.SEVERITY_INFO);
msg.setSummary("Items Transferred");
msg.setDetail(builder.toString());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public TeamServiceI getTeamService() {
return teamService;
}
public void setTeamService(TeamServiceI teamService) {
this.teamService = teamService;
}
public List<Team> getSource() {
return source;
}
public void setSource(List<Team> source) {
this.source = source;
}
public List<Team> getTarget() {
return target;
}
public void setTarget(List<Team> target) {
this.target = target;
}
public void afficher(){
System.out.println(target);
System.out.println(source);
}
}
and this is my entity class that I would like to load in my pickList:
#Entity
#Table(name = "team", catalog = "competition_manager")
public class Team implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer idTeam;
private Stadium stadium;
private League league;
private String teamName;
// getters and setters
#Override
public String toString() {
return teamName.toString();
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Team)) {
return false;
}
Team f = (Team) obj;
return (this.idTeam == f.getIdTeam());
}
Now, this is my custom Converter:
#FacesConverter(forClass = Team.class, value = "teamConverter")
public class TeamConverter implements Converter {
Team team;
public Object getAsObject(FacesContext facesContext, UIComponent component,
String value) {
System.out.println("hello object");
if (value == null || value.length() == 0) {
return null;
}
ApplicationContext ctx = FacesContextUtils
.getWebApplicationContext(FacesContext.getCurrentInstance());
TeamBean controller = (TeamBean) ctx.getBean("teamMB");
List<Team> liststagiaire = controller.getTeamList();
for (int i = 0; i < liststagiaire.size(); i++)
{
team = liststagiaire.get(i);
if (team.getIdTeam() == getKey(value)) {
break;
}
}
return team;
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
public String getAsString(FacesContext facesContext, UIComponent component,
Object object) {
System.out.println("hello string");
if (object == null) {
System.out.println("hello string null");
return null;
}
if (object instanceof Team) {
System.out.println("hello string intance of");
Team o = (Team) object;
String i = getStringKey(o.getIdTeam());
return i;
} else {
System.out.println("hello throw");
throw new IllegalArgumentException("object " + object
+ " is of type " + object.getClass().getName()
+ "; expected type: " + Team.class.getName());
}
}
}
And finally this is my XHTML page:
<p:pickList id="teamPickList" value="#{comMB.teams}" var="team"
itemValue="#{team}" itemLabel="#{team}" converter="teamConverter">
</p:pickList>
Your problem is comming from this line (in your class TeamConverter) :
if (team.getIdTeam() == getKey(value)) {
You can't compare Integer objects like that, because doing like this you are comparing reference. You should replace this line by
if (team.getIdTeam().intValue() == getKey(value).intValue()) {
You have the same problem in your class Team :
return (this.idTeam == f.getIdTeam());
should be replaced by :
return (this.idTeam.intValue() == f.getIdTeam().intValue());
Not related :
You don't need to use getKey and getStringKey, you could replace them simply like this :
getKey(value) // this
Integer.valueOf(value) // by this
and
getStringKey(o.getIdTeam()) // this
o.getIdTeam().toString() // by this
Also you should replace itemLabel="#{team}" by itemLabel="#{team.teamName}" in your view.

selectOneMenu in dataTable, default value not getting set properly

When I place a selectOneMenu within a dataTable, it does not display the correct default value in the selectOneMenu. The datatable is bound to a list of POJO's. The POJO entity Badge references a POJO entity we will call Facility. This Facility should be the selected value of the selectOneMenu in the row (the row being each Badge).
The following is my simple example of a table:
<h:dataTable id="examp" value="#{managedBean.badges}" var="badge">
<h:column rowHeader="rowie">
<h:selectOneMenu value="#{badge.facility}" id="col1">
<f:converter converterId="facilityConverter" />
<f:selectItems value="#{managedBean.facilities}"
/>
</h:selectOneMenu>
</h:column>
</h:dataTable>
The selectItems are a List of SelectItem objects that are created at PostConstruct. These are within my managedbean that is in ViewScope.
public class ListBadges extends BaseBean {
private List<Badge> badges = new ArrayList<Badge>();
private List<SelectItem> facilities = new ArrayList<SelectItem>();
public ListBadges() {
getBadgesFromDatabase(true);
}
#PostConstruct
public void init() {
if (facilities.size() <= 0) {
try {
List<Facility> facilityBeans = FacilityHelper.getFacilities();
for (Facility fac : facilityBeans) {
facilities.add(new SelectItem(fac, fac.getFacilityName()));
}
} catch (tException e) {
log.error("ListBadges.init(): " + e.getMessage());
e.printStackTrace();
}
}
}
public void getBadgesFromDatabase(boolean forceRefresh) {
if (forceRefresh || badges == null || badges.isEmpty())
badges = BadgeHelper.getBadgeList();
}
///
/// Bean Properties
///
public List<Badge> getBadges() {
return badges;
}
public void setBadges(List<Badge> badges) {
this.badges = badges;
}
public List<SelectItem> getFacilities() {
return facilities;
}
public void setFacilities(List<SelectItem> facilities) {
this.facilities = facilities;
}
Stepping through the code I confirm that all of the data is correct. In my converter, I verified that the arguments passed to getAsString is correct, so it should have identified the correct item.
#FacesConverter("facilityConverter")
public class FacilityConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String from) {
try {
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
ListBadges neededBean =
(ListBadges) context.getApplication().getELResolver().getValue(elContext, null, "managedBean");
long id = Long.parseLong(from);
for (SelectItem sItem : neededBean.getFacilities()) {
Facility facility = (Facility)sItem.getValue();
if (facility.getFacilityId() == id)
return facility;
}
} catch (Exception e) {
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
try {
Facility facility = (Facility)value;
return facility.getFacilityId() + "";
} catch (Exception e) {
}
return null;
}
}
Here is the Facility class which has equals and hashCode implemented:
public class Facility implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private long facilityId;
private String facilityName;
private String address1;
private String address2;
private String city;
private String state;
private String postalCode;
private String url;
private String phone;
private String siteManager;
public Facility() {
}
public Facility(String facilityName) {
this.facilityName = facilityName;
}
public Facility(String facilityName,
String address1, String address2, String city, String state,
String postalCode, String url, String phone, String siteManager) {
this.facilityName = facilityName;
this.address1 = address1;
this.address2 = address2;
this.city = city;
this.state = state;
this.postalCode = postalCode;
this.url = url;
this.phone = phone;
this.siteManager = siteManager;
}
public long getFacilityId() {
return this.facilityId;
}
public void setFacilityId(long facilityId) {
this.facilityId = facilityId;
}
public String getFacilityName() {
return this.facilityName;
}
public void setFacilityName(String facilityName) {
this.facilityName = facilityName;
}
public String getAddress1() {
return this.address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return this.address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getPostalCode() {
return this.postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSiteManager() {
return siteManager;
}
public void setSiteManager(String siteManager) {
this.siteManager = siteManager;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Facility) || (o == null))
return false;
if (o == this)
return true;
Facility obj = (Facility)o;
return obj.getFacilityId() == this.getFacilityId();
}
#Override
public int hashCode() {
return (new Long(this.getFacilityId()).hashCode()) ^
((this.getAddress1() == null) ? 0 : this.getAddress1().hashCode()) ^
((this.getAddress2() == null) ? 0 : this.getAddress2().hashCode()) ^
((this.getCity() == null) ? 0 : this.getCity().hashCode()) ^
((this.getFacilityName() == null) ? 0 : this.getFacilityName().hashCode()) ^
((this.getPhone() == null) ? 0 : this.getPhone().hashCode()) ^
((this.getPostalCode() == null) ? 0 : this.getPostalCode().hashCode()) ^
((this.getSiteManager() == null) ? 0 : this.getSiteManager().hashCode()) ^
((this.getUrl() == null) ? 0 : this.getUrl().hashCode());
}
}
I would greatly appreciate any feedback.
I found the problem and it is nothing to do with JSF.
Eclipse was loading an older version of the Facility bean class that had a programmatic mistake in its equals method. Even after fully cleaning, republishing, cleaning the working directory, restarting the web server, and restarting Eclipse this old class was still getting loaded. I restarted my computer and finally the correct class was being loaded and this problem went away.
Thanks for looking at this BalusC. Without this blog article you wrote I would be completely lost! http://balusc.blogspot.com/2007/09/objects-in-hselectonemenu.html

Resources