Error passing a Thymeleaf object to the Spring Boot controller (post)

Asked

Viewed 408 times

1

I have this controller:

@PostMapping("/salvar")
public String salvar(@Valid OrdemServico ordemServico, BindingResult result,
                     RedirectAttributes attr) {

    if (result.hasErrors()){
        return "ordemServico/cadastro";
    }

    service.save(ordemServico);
    attr.addFlashAttribute("success", "Ordem de Servico inserido com sucesso");
    return "redirect:/os/cadastrar";

}

in the Thymeleaf template:

<form th:action="@{/os/salvar}"
                  th:object="${ordemServico}" method="POST">
                <div class="form-row">
                    <div class="form-group col-md-4">
                        <label for="cliente">Cliente</label>
                        <select id="cliente" class="form-control" th:field="*{cliente}"
                                th:classappend="${#fields.hasErrors('cliente')} ? 'is-invalid'">
                            <option value="">Selecione...</option>
                            <option th:each="cliente : ${clientes}" th:value="${cliente}"
                                    th:text="${cliente.nome}">Cliente</option>
                        </select>
                        <div class="invalid-feedback">
                            <span th:errors="*{cliente}"></span>
                        </div>
                    </div>
                </div>

The goal is to register a service order, which relates to a Customer(entity tbm)

public class OrdemServico{


@Id
@GenericGenerator(name="seq_id", strategy="com.web.mja.mja.domain.CodigoOSGenerator")
@GeneratedValue(generator="seq_id")
@Column(unique = true, nullable = false, length = 10)
private String codigo;

@Column
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date dataEntrada;

@Column
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date dataAtualizacao;


@ManyToOne
@JoinColumn(name = "cliente_id_fk")
private Cliente cliente;

@NotNull
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private TipoEquipamento tipo;

@NotNull
@Enumerated(EnumType.STRING)
private Marca marca;

But when choosing a client in the template, fill in other fields and send the request. It gives conversation error. Go a String instead of the chosen client object.

error: Failed to Convert Property value of type java.lang.String to required type com.web.mja.mja.Domain.Client for Property client; nested Exception is java.lang.Illegalstateexception: Cannot Convert value of type java.lang.String to required type com.web.mja.mja.Domain.Client for Property client: no matching Editors or Conversion Strategy found

1 answer

1

<option th:each="cliente : ${clientes}" th:value="${cliente}"
                                    th:text="${cliente.nome}">Cliente</option>

at this point you are setting th:value with the client object, however Thymeleaf converts this value to a String (the value field does not accept object), that is, value is being equal to the memory address of the client object.

Example: com.web.mja.mja.domain.Cliente@2b93571c

the value of your option is more or less this example above.

Since you will not have a client object on the page, you could change the client attribute to string or long and make this relationship only in the database.

Example: in the customer column of the service order would be only the ID or the customer’s Code/Name, in the database this column would be a Foreign key of the client table. and the option would look like this:

<option th:each="cliente : ${clientes}" th:value="${cliente.id}"
                                    th:text="${cliente.nome}">Cliente</option>

This is an option that would circumvent this problem.

Another option is to create an Ordemservicodao class with the attribute String client, in the controller you would receive Ordemservicodao and not Ordemservico, then you send it to the service layer and there you would convert Ordemservicodao to Ordemservico.

Example:

@PostMapping("/salvar")
public String salvar(@Valid OrdemServicoDAO ordemServicoDAO, BindingResult result,
                     RedirectAttributes attr) {

    if (result.hasErrors()){
        return "ordemServico/cadastro";
    }

    service.save(ordemServicoDAO);
    attr.addFlashAttribute("success", "Ordem de Servico inserido com sucesso");
    return "redirect:/os/cadastrar";

}

in the save method just create an Ordemservic object and pass the order valuesServicoDAO to it, in the client field you search the client in the database through the String client of the ordemServicoDAO and assign it to the Ordemservic attribute. example:

ordemServico.setCliente(clienteRepository.findById(ordemServicoDAO.getCliente()));

Browser other questions tagged

You are not signed in. Login or sign up in order to post.