Java DTO with Spring Boot 2

Asked

Viewed 1,499 times

2

I am trying to implement DTO and am having a no size headache. I would like a help. Follow my project, with spring boot 2.

I have 3 tables @Entity as follows.

Abstract Client with only 1 attribute, the "id" and the respective get and set. 2 classes inherited from client,

Personal


Personal

each one with its respective attributes (Cpf, name, cnpj, social reason...) and methods.

I created 3 classes DTO, Clientedto, PFDTO and PJDTO.

In the Customer Class, which is my @Restcontroller, I have among other methods, the insert method, that instead of using the Customer Entity, I want to use the Customer

@PostMapping()
public ResponseEntity<Void> inserir(@RequestBody Cliente objetoCliente) {
objetoCliente = clienteService.inserir(objetoCliente);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(objetoCliente.getId()).toUri();
return ResponseEntity.created(uri).build();
}

And I want you to change for that

@PostMapping()
public ResponseEntity<Void> inserir(@RequestBody ClienteDTO objetoClienteDTO) {
Cliente objetoCliente = clienteService.converteParaDTO(objetoClienteDTO);
objetoCliente = clienteService.inserir(objetoCliente);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(objetoCliente.getId()).toUri();
return ResponseEntity.created(uri).build();
}

It turns out that in Clienteservice, my customer service, the method convert:

public Cliente converteParaDTO(ClienteDTO objetoClienteDTO) {
if (objetoClienteDTO instanceof PessoaFisicaDTO) {
return new PessoaFisica(objetoClienteDTO.getNome(), objetoClienteDTO., objetoClienteDTO.getRg(),
objetoClienteDTO.getEmail(), objetoClienteDTO.getDataDeNascimento(), objetoClienteDTO.getNaturalidade(),
objetoClienteDTO.getProfissao(), objetoClienteDTO.getGenero(), objetoClienteDTO.getEstadoCivil(), objetoClienteDTO.getPessoaFisicaTipo()) {
};
}
if (objetoClienteDTO instanceof PessoaJuridicaDTO) {
return new PessoaJuridica(objetoClienteDTO.getRazaoSocial(), objetoClienteDTO.getNomeFantasia(),
objetoClienteDTO.getDataDeConstituicao(), objetoClienteDTO.getInscricaoEstadual(), objetoClienteDTO.getInscricaoFederal(),
objetoClienteDTO.getPessoaJuridicaTipo());
}
return null;
}

The error is as follows: My Clientedto has only 2 attributes, id and name. The other attributes and methods are specific to each class. Then the objectClienteDTO.getInscriptionState() for example, does not exist, among others.

Wanted a help as I solve this problem. As I call a class or other (PFDTO or PJDTO) through a single method.

  • If you have additional questions, click the blue "Ask a question" button that is up there instead of posting questions as if they were answers.

2 answers

4


What happens is that the serialization library looks at the type declared in the method signature (which in your case is ClienteDTO) and tries to convert for him.

An alternative is to give a "hint" to the serializer which subclass it should instantiate.

It is possible to do this with the annotation JsonTypeInfo:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = PessoaFisicaDTO.class, name = "fisica"),
    @JsonSubTypes.Type(value = PessoaJuridicaDTO.class, name = "juridica")
})
class ClienteDTO {
  private Long id;
  private String type;
}
class PessoaFisicaDTO extends ClienteDTO {
  private String email;
  private String profissao;
}
class PessoaJuridicaDTO extends ClienteDTO {
  private String dataDeConstituicao;
  private String inscricaoEstadual;
}

In this case it was defined in property that there will be a camp type in JSON. This, in turn, can have the values fisica or juridica. The serializer will read this information and try to convert to the appropriate type.

Using this solution, your JSON should contain an additional attribute stating the type:

{ 
    "type": "fisica",
    "email": "[email protected]",
    "profissao":"desenvolvedor"
}

2

You need to do the cast of ClienteDTO for PessoaFisicaDTO or PessoaJuridicaDTO before picking up the attributes, imagining that an instance of each actually arrives in your method. Example:

public Cliente converteParaDTO(ClienteDTO objetoClienteDTO) {
    if (objetoClienteDTO instanceof PessoaFisicaDTO) {
        PessoaFisicaDTO pfDto = (PessoaFisicaDTO) objetoClienteDTO;
        return new PessoaFisica(pfDto.getNome(),...

And to PessoaJuridicaDTO:

    if (objetoClienteDTO instanceof PessoaJuridicaDTO) {
        PessoaJuridicaDTO pjDto = (PessoaJuridicaDTO) objetoClienteDTO;
        return new PessoaJuridica(pjDto.getRazaoSocial(), ...

However, it would be better to avoid this instanceof using a single service and implementing two separate services: one for an individual and the other for a legal entity.

Browser other questions tagged

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