Java DTO with Spring Boot 2

2

I'm trying to implement DTO and am having a sizeable headache. I'd like some help. Here is 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 that inherit from client,

PersonPhysical

PersonalJuridica

each with their respective attributes (cpf, name, cnpj, business name ....) and methods.

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

In the ClientResource class, which is my @RestController, I have, among other methods, the insert method, which instead of using the Entity Client, I want it to use the ClientDTO

@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 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 ClientService, my client service, the method converteParaDTO is giving error:

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 ClientDTO has only 2 attributes, id and name. The other attributes and methods are specific to each class. So, the objectDAT.getSet () for example, does not exist, among others.

I wanted some help how I solve this problem. As I call one class or another (PFDTO or PJDTO) through a single method.

    
asked by anonymous 19.06.2018 / 06:39

2 answers

2

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

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

You can 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 type field in JSON. This, in turn, may have the fisica or juridica values. The serializer will read this information and try to convert to the appropriate type.

Using this workaround, your JSON should contain one more attribute telling the type:

{ 
    "type": "fisica",
    "email": "[email protected]",
    "profissao":"desenvolvedor"
}
    
19.06.2018 / 13:28
1

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

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

And for PessoaJuridicaDTO :

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

However, it would be best to avoid this instanceof using a single service and implement two separate services: one for individual and one for legal entity.

    
19.06.2018 / 13:51