Thymeleaf not loading the data - java

i have a spring boot application, and when i load the data in thymeleaf it doesn't load, it's empty. I'm using H2, so every time i launch the app i do some inserts to test, but it never loads the data. I've tried the enpoints with Postman, and they all work. I'm thinking it's something with the method i'm using, but i don't know yet.
Here's my application models:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "estudiante")
public class Estudiante {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "estudiante_generator")
private Long id;
#Column(name = "nombre")
private String nombre;
#Column(name = "apellido")
private String apellido;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "profesor_id", nullable = false)
#OnDelete(action = OnDeleteAction.CASCADE)
#JsonIgnore
private Profesor profesor;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "profesor")
public class Profesor {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "profesor_generator")
private Long id;
#Column(name = "nombre")
private String nombre;
#Column(name = "apellido")
private String apellido;
#Column(name = "curso")
private String curso;
public Profesor(String nombre, String apellido, String curso){
this.nombre = nombre;
this.apellido = apellido;
this.curso = curso;
}
}
The controller for the index, and the controller for the backend:
#GetMapping("/index")
public String mostrarProfesores(Model model){
List<Profesor> profesor = profesorRepository.findAll();
model.addAttribute("profesores", profesor);
return "index";
}
#GetMapping("/profesores")
public ResponseEntity<List<Profesor>> getProfesores(){
List<Profesor> profesor = new ArrayList<Profesor>();
profesorRepository.findAll().forEach(profesor::add);
if(profesor.isEmpty()){
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(profesor, HttpStatus.OK);
}
And the thymeleaf template:
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<h2>Users</h2>
<table>
<thead>
<th>Nombre</th>
<th>Apellido</th>
</thead>
<tbody>
<th:block th:each="profesor : ${profesores}">
<tr>
<td>[[${profesor.nombre}]]</td>
<td>[[${profesor.apellido}]]</td>
</tr>
</th:block>
</tbody>
</table>
</div>
</body>
</html>
Any help is appreciated, thanks in advance for your help.

You should iterate the collection inside the <tr> label.
<tbody>
<tr th:each="profesor : ${profesores}">
<td th:text="${profesor.nombre}"></td>
<td th:text="${profesor.nombre}"></td>
</tr>
</tbody>

Related

How do I convert string into Java Class in Spring?

I'm creating a new java entity with html post form,but I don't understand how to convert system id to a class System (that I pass with model.addAttribute("System",id); in controller).
Release
#Table(name = "treleas")
public class Release {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "release_id")
Integer releaseId;
#Column(name = "release_name", nullable = false)
private String releaseName;
#Column(name = "create_date", nullable = false)
private LocalDateTime releaseDate = LocalDateTime.now();
#ManyToOne
#JoinColumn(name = "system_id")
private System system;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="release_id")
private List<Req> requirements;
}
System
#Entity
#Table(name = "tsystem")
public class System {
#Id
#Column(name = "system_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
Integer systemId;
#Column(name = "system_name", nullable = false)
private String systemName;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="system_id")
private List<Release> releases;
}
Html new release
<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Новый релиз</title>
</head>
<body>
<form th:method="POST" th:action="#{|/systems/${System}/releases|}"
th:object="${release}">
<label for="releaseName" >Введите название релиза: </label>
<input type="text" th:field="*{releaseName}" id="releaseName"/>
<div style="color:#f80d0d" th:if="${#fields.hasErrors('releaseName')}" th:errors="*{releaseName}"
>Name error</div>
<input type="hidden" th:field="*{system}" th:value="|${System}|"/>
<br/>
<input type="submit" value="Create!"/>
</form>
</body>
</html>
Exception
Caused by: org.postgresql.util.PSQLException: ОШИБКА: значение NULL в столбце "system_id" отношения "treleas" нарушает ограничение NOT NULL
Подробности: Ошибочная строка содержит (5, ReleaseName, 2022-05-15, null).
which means that it cannot insert release with a null system id

Invalid property 'projection' of bean class

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>
Use th:field="*{hall.name}" instead of th:field="*{projection.hall.name}" and th:field="*{movie.movieName}" instead of th:field="*{projection.movie.movieName}"

How can I fill two entities with data after i click submit

I am looking for a solution all day, but I still can not find anything.
When I create a book, how can I create an author and assign it to a book at the same time?
I have two entities
Book
#Data
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
#ManyToOne
private Author author;
}
Author
#Data
#Entity
public class Author {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#OneToMany(mappedBy = "author")
private Set<Book> books;
}
Controller
#Controller
public class BookController {
private BookRepository bookRepository;
public BookController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
#RequestMapping(value="/booklist", method= RequestMethod.GET)
public String bookList(Model model) {
model.addAttribute("books", bookRepository.findAll());
return "booklist";
}
#RequestMapping(value = "/add")
public String addBook(Model model){
model.addAttribute("book", new Book());
return "addbook";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(Book book){
bookRepository.save(book);
return "redirect:booklist";
}
}
VIEW
<body>
<div>
<form th:object="${book}" th:action="#{save}" action="#" method="post">
<label for="title">Title</label>
<input type="text" id="title"
th:field="*{title}" />
<label for="author">Author</label>
<input type="text" id="author" th:field="*{author.name}" />
<input type="submit" value="Save"></input>
</form>
</div>
</body>
When I try to create a book I got this error
There was an unexpected error (type=Internal Server Error, status=500).
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
After i click submit button
it should look like this
Try adding cascede to Author in entity like this
#Data
#Entity
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
#ManyToOne(cascade=CascadeType.ALL)
private Author author;
}
or use prepersist annotation on your entity
#PrePersist
protected void onCreate() {
//check author is exist if not persist the author first
}

Spring MVC: put data from table cascade to JSP

I have similar tables:
I need to create JSP files that contains measured values for Device.
My idea is web page (table) like this:
Device:
SensorA:
Temp (table row 1)
Temp (table row 2)
Temp (table row n)
SensorB:
Hum (table row 1)
Hum (table row 2)
Hum (table row n)
There is my code:
#Entity
#Table(name="device")
public class Device implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique=true, nullable=false)
private int id;
#Column(length=45)
private String title;
#OneToMany(mappedBy="device")
private List<Value> values;
public Device() {
}
// getters and setters....
}
#Entity
#Table(name="`values`")
public class Value implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique=true, nullable=false)
private int id;
#org.hibernate.annotations.Source(SourceType.DB)
#org.hibernate.annotations.Generated(value = GenerationTime.INSERT)
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "date", insertable = true, updatable = false)
private Date date;
#OneToMany(mappedBy="value")
private List<SensorA> sensorA;
#OneToMany(mappedBy="value")
private List<SensorB> sensorB;
#ManyToOne
#JoinColumn(name="device_id", nullable=false)
private Device device;
public Value() {
}
// getters and setters...
}
#Entity
#Table(name="sensor_a")
public class SensorA implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique=true, nullable=false)
private int id;
#Column(name="TEMP", nullable=false)
private float temp;
#ManyToOne
#JoinColumn(name="values_id", nullable=false)
private Value value;
public SensorA() {
}
// getters and setters...
}
#Entity
#Table(name="sensor_b")
public class SensorB implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(unique=true, nullable=false)
private int id;
#Column(name="HUM", nullable=false)
private float hum;
#ManyToOne
#JoinColumn(name="values_id", nullable=false)
private Value value;
public SensorB() {
}
// getters and setters...
}
#RequestMapping("/value")
#Controller
public class ValueController {
#Autowired
DeviceManager deviceManager;
#RequestMapping(value="/{date}", method=RequestMethod.GET)
public String getPage(Model model, #PathVariable("date") Date date) {
Device d = deviceManager.findByDate(date);
List<Value> values = d.getValues();
model.addAttribute("values", values);
return "value";
}
}
And JSP:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page session="false" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h3>Values with datas</h3>
<div>
<table>
<tr>
<th>value id</th>
<th>sensor_a id</th>
<th>temp</th>
</tr>
<c:forEach var="value" items="${values}">
<tr>
<td><c:out value="${value.id}" /></td>
<td><c:out value="${value.sensorA.id}" /></td>
<td><c:out value="${value.sensorA.temp}" /></td>
</tr>
</c:forEach>
</table>
</div>
How can I send all values with all sensorA and sensorB sensors to JSP? And how can I access it? My JSP writes only table header.

Using spring-form tags to insert/update entity with non-primitive attributes

In my spring application, the forms for insert/update a entity in the database have a structure similar to this:
<jsp:include page="../../common/cadastrar.jsp">
<jsp:param name="entity" value="Usuario"/>
<jsp:param name="arguments" value="login"/>
<jsp:param name="arguments" value="senha"/>
<jsp:param name="arguments" value="first_name"/>
<jsp:param name="arguments" value="last_name"/>
<jsp:param name="arguments" value="email"/>
</jsp:include>
which redirect to this shared jsp page (common to all the views):
<c:url value="${param.entity}/cadastra" var="cadastra"/>
<form:form class="form" role="form" method="post" action="${cadastra}">
<table>
<c:forEach var="item" items="${paramValues.arguments}">
<c:choose>
<c:when test="${item == 'senha'}">
<tr>
<td><form:label path="${item}">${item}</form:label></td>
<td><form:input path="${item}" type="password"/></td>
</tr>
</c:when>
<c:otherwise>
<tr>
<td><form:label path="${item}">${item}</form:label></td>
<td><form:input path="${item}"/></td>
</tr>
</c:otherwise>
</c:choose>
</c:forEach>
<tr>
<td colspan="2">
<button type="submit" class="btn btn-lg btn-primary">Cadastrar</button>
</td>
</tr>
</table>
</form:form>
When my entity class have only primitive attributes (Integer, String, etc), this code works fine. But I can't figure out how to do the same for classes like that:
#Entity
#Table(name="cliente")
public class Cliente extends Entidade {
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#OneToOne
#JoinColumn(name="fk_usuario")
private Usuario usuario;
#Column(name="documento")
private String documento;
#Column(name="cpf")
private String cpf;
#Column(name="cnpj")
private String cnpj;
#ManyToMany
#JoinTable(name="endereco_entrega", joinColumns={#JoinColumn(name="fk_cliente")}, inverseJoinColumns={#JoinColumn(name="fk_endereco")})
#LazyCollection(LazyCollectionOption.FALSE)
private List<Endereco> endereco;
#ManyToMany
#JoinTable(name="pedido_cliente", joinColumns={#JoinColumn(name="fk_cliente")}, inverseJoinColumns={#JoinColumn(name="fk_pedido")})
#LazyCollection(LazyCollectionOption.FALSE)
private List<Pedido> pedido;
}
where some of the attributes are other entities. Anyone can point me a direction to do this?
UPDATE 1
Usuario.java
#Entity
#Table(name="usuario")
public class Usuario extends Entidade {
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name = "login")
private String login;
#Column(name = "senha")
private String senha;
#Column(name="first_name")
private String first_name;
#Column(name="last_name")
private String last_name;
#Column(name="email")
private String email;
#ManyToMany
#JoinTable(name="role_members", joinColumns={#JoinColumn(name="fk_user")}, inverseJoinColumns={#JoinColumn(name="fk_role")})
#LazyCollection(LazyCollectionOption.FALSE)
private List<Role> Autorizacao = new ArrayList<Role>();
}
Endereco.java
#Entity
#Table(name="endereco")
public class Endereco {
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="logadouro")
private String logradouro;
#Column(name="numero")
private String numero;
#Column(name="complemento")
private String complemento;
#Column(name="bairro")
private String bairro;
#Column(name="cidade")
private String cidade;
#Column(name="estado")
private String estado;
#Column(name="cep")
private String cep;
}
Pedido.java
#Entity
#Table(name="pedido")
public class Pedido {
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#ManyToMany
#JoinTable(name="produtos_do_pedido", joinColumns={#JoinColumn(name="fk_pedido")}, inverseJoinColumns={#JoinColumn(name="fk_produto")})
#LazyCollection(LazyCollectionOption.FALSE)
private List<Produto> produto;
#ManyToMany
#JoinTable(name="cobranca_do_pedido", joinColumns={#JoinColumn(name="fk_pedido")}, inverseJoinColumns={#JoinColumn(name="fk_cobranca")})
#LazyCollection(LazyCollectionOption.FALSE)
private List<Cobranca> cobranca;
}

Categories

Resources