Lucas Sartori
Lucas Sartori

Reputation: 61

How do I add an object to a list in another object and persist it in JSF?

I'm new to JSF and Java EE and I've been struggling on persisting an Entity named Room which has one or more Beds, which consists of the following code:

package ninfa.javahostel.domain;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Bed {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToOne
private Room room;

private Integer number;
private Double pricePerNight;
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public Room getRoom() {
    return room;
}
public void setRoom(Room room) {
    this.room = room;
}
public Integer getNumber() {
    return number;
}
public void setNumber(Integer number) {
    this.number = number;
}
public Double getPricePerNight() {
    return pricePerNight;
}
public void setPricePerNight(Double pricePerNight) {
    this.pricePerNight = pricePerNight;
}

}

The Entity Room consists of the following code:

package ninfa.javahostel.domain;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Room {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String number;
    @OneToMany (cascade = CascadeType.ALL, mappedBy = "room")
    private Set<Bed> beds;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getNumber() {
            return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
    public Set<Bed> getBeds() {
        return beds;
    }
    public void setBeds(Set<Bed> beds) {
        this.beds = beds;
    }

}

I have a bedRegistrationService which is used to persist and get objects from the dabatase and a roomRegistrationService which is used to persist rooms. Other than that I have only one controller which is responsible for everything, I know the architecture is really bad but I'm just trying to implement a simple CRUD and get used to JSF. Code is as follows (I tried the backticks for a code span but they seem not to work):

Bed converter: https://pastebin.com/b1ZwYS75

roomRegistrationService: https://pastebin.com/sBaDzrfh

bedRegistrationService: https://pastebin.com/jjsMbVPA

registrationController: https://pastebin.com/cfZeB16d

roomcreate.xhtml: https://pastebin.com/UMCcW7U7

Form renders correctly with all the beds in the database

Whenever I try to submit I get the following error on console: 10:07:08,205 INFO [javax.enterprise.resource.webcontainer.jsf.renderkit] (default task-35) WARNING: FacesMessage(s) have been enqueued, but may not have been displayed. sourceId=roomRegForm:j_idt41[severity=(ERROR 2), summary=(roomRegForm:j_idt41: Validation Error: Value is not valid), detail=(roomRegForm:j_idt41: Validation Error: Value is not valid)]

Thinking that I might have to use bed.number as value on the xhtml instead of bed (since the converter parses the html string and converts it to a Bed, I tried to change to bed.number just to see what happens and the following occurs: enter image description here

Don't know why "on" is showing instead of the wrong value. I'm pretty much clueless, I think it might have to do with the converter or my lack of expression language knowledge. My only goal is to persist the room with one or more beds. I apologize for the awful English and newbie question, but I've been stuck on this problem for days. Thanks in advance for the help.

Upvotes: 0

Views: 96

Answers (1)

Vsevolod Golovanov
Vsevolod Golovanov

Reputation: 4226

selectManyCheckbox probably expects the selected item to be present in its known selectItems, so it does an equality check. This check fails because your converter creates a new Bed instance and your Bed class doesn't have hashCode/equals defined. So bed.equals(sameConvertedBed) would always fail based on instance equality.

You should define hashCode and equals in your entity classes, e.g. based on instanceof Bed && id equality. Remember about proxies when implementing. I.e. do other.getId(), not other.id.

Upvotes: 1

Related Questions