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 class="navbar navbar-expand-lg navbar-light bg-light"> <img src="../pictures/cinemalogo.png" th:src="@{pictures/cinemalogo.png}" class = "center"alt="logo" width="120" height="100"/> <ul class="navbar-nav"> <li class="nav-item"> <h1>Our cinema!</h1> </li> </ul> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="/logout">Logout</a> </li> </ul> </nav> </nav> <br> <br> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h1>Add projection</h1><br> <form th:action="@{/projection}" method="post" th:object="${projection}"> <div class="form-group"> <label class="control-label" for="date"> Date </label> <input id="date" class="form-control" th:field="*{date}" required autofocus="autofocus" /> </div> <div class="form-group"> <label class="control-label" for="startTime"> Start time</label> <input id="startTime" class="form-control" th:field="*{startTime}" required autofocus="autofocus" /> </div> <div class="form-group"> <label class="control-label" for="hallName"> Hall name </label> <input id="hallName" class="form-control" th:field="*{projection.hall.name}" required autofocus="autofocus" /> </div> <div class="form-group"> <label class="control-label" for="movieName"> Movie name </label> <input id="movieName" class="form-control" th:field="*{projection.movie.movieName}" required autofocus="autofocus" /> </div> <div class="form-group"> <button type="submit" class="btn btn-success">Submit</button> </div> </form> </div> </div> </div> </body> </html>
Advertisement
Answer
Use th:field="*{hall.name}"
instead of th:field="*{projection.hall.name}"
and th:field="*{movie.movieName}"
instead of th:field="*{projection.movie.movieName}"