Hi I need a little help with my code. I tried solutions online but I couldn't fix my bug. I working in java and spring with mysql and tymeleaf. My error is short:
Invalid property 'projection' of bean class [com.bakulic.CinemaTicketShop.model.dto.requests.CreateOrUpdateProjectionDTO]: Bean property 'projection' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
And I found that my problem is in the html file createProjectionForm whitch I will put below as well as the entities and all that is needed. My projection entity has a relation to Hall and Movie and I'm not sure how to get attributes of Movie and Hall in my html. For the fiel I tried to put ${projection.hall.name} and ${projection.movie.movieName}. Zou will find it in the code. Thank you in advance.
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "projections")
public class Projection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int projectionId;
@Column(name = "date")
private String date;
@Column(name = "startTime")
private String startTime;
@ManyToOne
@JoinColumn(name = "idHall")
private Hall hall;
@ManyToOne
@JoinColumn(name = "idMovie")
private Movie movie;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "projection", cascade = CascadeType.ALL)
private List<Seat> seatList;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "projection", cascade = CascadeType.ALL)
private List<Ticket> ticketList;
}
@Entity
@Table(name = "halls")
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Hall {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int hallId;
@Column(name = "name")
private String name;
@Column(name = "numberofseats")
private Integer numberOfSeats;
@Column(name = "description")
private String description;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "hall", cascade = CascadeType.ALL)
private List<Projection> projectionList;
}
@Entity
@Table(name = "movies")
@Data
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int movieId;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@Column (name = "length")
private String length;
@Column(name = "picture")
private String picture;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "movie", cascade = CascadeType.ALL)
private List<Projection> projectionList;
}
@Data
public class ProjectionDTO implements Serializable {
private int id;
private String date;
private String startTime;
private List<Seat> seatList;
private List<Ticket> ticketList;
private Hall hall;
private Movie movie;
public ProjectionDTO(Projection projection){
if(projection != null){
this.id = projection.getProjectionId();
this.date = projection.getDate();
this.startTime = projection.getStartTime();
this.seatList = projection.getSeatList();
this.ticketList = projection.getTicketList();
this.hall = projection.getHall();
this.movie = projection.getMovie();
}
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CreateOrUpdateProjectionDTO implements Serializable {
private String date;
private String startTime;
private List<Seat> seatList;
//aditional info
private String name;
private String movieName;
}
/** create projection*/
public Projection createProjection(CreateOrUpdateProjectionDTO createProjectionDTO){
if(createProjectionDTO == null){
throw new InvalidDataException("Projection cannot be null");
}
timeValidator.checkTime(createProjectionDTO.getStartTime());
dateValidator.checkDate(createProjectionDTO.getDate());
Projection proj = new Projection();
proj.setDate(createProjectionDTO.getDate());
proj.setStartTime(createProjectionDTO.getStartTime());
Hall hall = proj.getHall();
if(hall == null){
hall = new Hall();
}
hall.setName(createProjectionDTO.getName());
Integer numOfSeats = hall.getNumberOfSeats();
Movie movie = proj.getMovie();
if(movie == null){
movie = new Movie();
}
movie.setName(createProjectionDTO.getMovieName());
List<Seat> list = createProjectionDTO.getSeatList();
for(int i=1; i<=numOfSeats; i ){
Seat seat = new Seat();
seat.setSeatNumber(i);
seat.setStatus("empty");
list.add(seat);
}
Projection projCreated = projectionRepository.save(proj);
log.info(String.format("Projection %s has been created.", proj.getProjectionId()));
return projCreated;
} The function is similar for update.
<
<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Create theater</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
</head>
<body style="background-color:lightgrey;">
<nav >
<img src="../pictures/cinemalogo.png" th:src="@{pictures/cinemalogo.png}" class = "center"alt="logo" width="120" height="100"/>
<ul >
<li >
<h1>Our cinema!</h1>
</li>
</ul>
<ul >
<li >
<a href="/logout">Logout</a>
</li>
</ul>
</nav>
</nav>
<br>
<br>
<div >
<div >
<div >
<h1>Add projection</h1><br>
<form th:action="@{/projection}" method="post" th:object="${projection}">
<div >
<label for="date"> Date </label>
<input id="date" th:field="*{date}"
required autofocus="autofocus" />
</div>
<div >
<label for="startTime"> Start time</label> <input
id="startTime" th:field="*{startTime}" required
autofocus="autofocus" />
</div>
<div >
<label for="hallName"> Hall name </label> <input
id="hallName" th:field="*{projection.hall.name}" required
autofocus="autofocus" />
</div>
<div >
<label for="movieName"> Movie name </label> <input
id="movieName" th:field="*{projection.movie.movieName}" required
autofocus="autofocus" />
</div>
<div >
<button type="submit" >Submit</button>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
CodePudding user response:
Use th:field="*{hall.name}"
instead of th:field="*{projection.hall.name}"
and th:field="*{movie.movieName}"
instead of th:field="*{projection.movie.movieName}"