DTO Assembler, how do you actually use it?

0

I'm reading about DTO and tbm viewmodel in ASP.NET and wanted to do something like this in JAVA. If I'm not mistaken, DTO is a way to traffic data between layers in a specific way without having to change domain entities.

Well, in ASP we have the automapper that will transform an Entity into a ViewModel / DTO and for java I have found some solutions that make it easier.

My problem is the reverse process, transforming a ViewModel / DTO into an entity. Imagine the following scenario:

I have an entity:

public class Pedido{
   private long codigo;
   private Cliente cliente;
   private Vendedor vendedor;
}

and a DTO

public class PedidoDTO{
   private long codigo;
   private long codCliente;
   private long nomeCliente;
   private long codVendedor;
   private long nomeVendedor;
}

Turning the entity into a DTO is easy, because the DTO is much simpler, you can even create a lib to do this, but the reverse process is more complex. I even created a mapper here to do this "on hand".

    public Pedido preencherModelo(PedidoDTO pDTO, Pedido pPedido) {     
            pPedido.setCodigo(pDTO.getCodigo());
            if (pDTO.getCodCliente() > 0){
                Cliente lCliente = _servicoCliente.buscar(pDTO.getCodCliente()); 
                pPedido.setCliente(lCliente);
            }       
            if (pDTO.getCodVendedor() > 0){
                Vendedor lVendedor = _servicoVendedor.buscar(pDTO.getCodVendedor()); 
                pPedido.setVendedor(lVendedor);
            }
            return pPedido;
}

The question is: Are you doing bullshit? Do you have a better solution than this?

    
asked by anonymous 18.11.2016 / 23:43

1 answer

1

Converting Entity to DTO through the pattern assembler is wrong, it breaks the sense of the DTO which is a pattern for transferring objects. See that it can be made up of several entities. The correct thing is to use set methods of the object instances in the service classes, taking the values of these DTOs and assembling the entities, on the contrary, as you yourself said it is simple, because you would be working correctly with the pattern. / p>

But it has a form that even if it is wrong it would work, but would only be valid if the association was 1x1 between entity x DTO, using function.

Ex: to convert using transformes to objects and lists with Guava:

import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Function;

    /**
     * Classe de transformação para popular os dados em DTOs, seguindo o pattern
     * Transfer Object Assembler.
     */
    public class Transformer {

        /**
         * Executa a transformação de um objeto para um DTO.
         * 
         * @param from
         * @param function
         * @return <F, T> T
         */
        public static <F, T> T transform(F from, Function<? super F, ? extends T> function) {
            return (from == null) ? null : function.apply(from);
        }

        /**
         * Executa a transformação de uma lista de objetos para uma lista de DTOs.
         * 
         * @param fromList
         * @param function
         * @return <F, T> List<T>
         */
        public static <F, T> List<T> transform(List<F> source, Function<? super F, ? extends T> function) {
            List<T> out = new ArrayList<>(source.size());

            for (F from : source) {
                out.add(function.apply(from));
            }    
            return out;
        }    
    }

Pattern assembler:

import java.util.List;
import br.com.myapp.model.dto.AuthUserDTO;
import br.com.myapp.model.entity.AuthUser;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

/**
 * Classe que transforma entidade USUARIOS em DTO.
 * 
 * @author Dilnei Cunha
 */
public class AuthUserDTOAssembler implements Function<AuthUser, AuthUserDTO>{

    /**
     * Método responsável por fazer a conversão da entidade USUARIOS em um AuthUserDTO.
     */
@Override
public AuthUserDTO apply(AuthUser e) {

    AuthGroupDTO groupDTO = Transformer.transform(e.getAuthGroup(), new  AuthGroupDTOAssembler());

    return new AuthUserDTO(e.getId(),
                       e.getName(),
                       e.getPassword(),
                       e.getEmail(),
                       e.getCreationDate(),
                       e.getLastModificationdate(),
                       e.getLastAccessDate(),
                       e.getAtivo(),
                       e.getUserName(),
                       e.getRamal(),
                       groupDTO);
    }
}

What would be the service that would use these patterns ...

/**
 * Método responsável por buscar um AuthUserDTO pelo ID do usuário.
 */
@Override
public AuthUserDTO findById(Long id) {
    return Transformer.transform(authUserRepository.findUserById(id), new AuthUserDTOAssembler());
}

Now let's do the inverse process of turning one or a list of DTOs into objects, but keeping in mind that the association was 1x1. To do this, simply invert the objects in the implementation of the function, eg:

import java.util.List;
import br.com.myapp.model.dto.AuthUserDTO;
import br.com.myapp.model.entity.AuthUser;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

/**
 * @author Dilnei Cunha
 */
public class AuthUserAssembler implements Function<AuthUserDTO, AuthUser>{

@Override
public AuthUser apply(AuthUserDTO e) {

    AuthGroup group = Transformer.transform(e.getAuthGroupDTO(), new  AuthGroupAssembler());

    return new AuthUser(e.getId(),
                       e.getName(),
                       e.getPassword(),
                       e.getEmail(),
                       e.getCreationDate(),
                       e.getLastModificationdate(),
                       e.getLastAccessDate(),
                       e.getAtivo(),
                       e.getUserName(),
                       e.getRamal(),
                       group);
    }
}
    
20.11.2016 / 01:02