Java 8 – Convert collection of objects to another type with streams

I was trying to simplify the following lines with java 8

this.audiencias = new ArrayList<>();
        for(Audiencia audiencia: carpeta.getAudiencias()){
            this.audiencias.add(new AudienciaDTO(audiencia));
        }

to this

this.audiencias = carpeta.getAudiencias.stream().map(AudienciaDTO::new).collect(Collectors.toList());

although it seems correct, and no error was thrown, it was returning an empty list.

As it happens, the list type is important. The attribute this.audiencias is of type Collection and carpeta.getAudiencias returns the same type, but the method stream() apparently only works with List types.

If I change the code to

List<Audiencia> asList = new ArrayList(carpeta.getAudiencias());
        this.audiencias = asList.stream().map(AudienciaDTO::new).collect(Collectors.toList());

it works as expected, but it is cumbersome the need to convert the Collection to a List type first.

for a one liner it would be

this.audiencias = new ArrayList<>(carpeta.getAudiencias()).stream().map(AudienciaDTO::new).collect(Collectors.toList());

fuentes:
http://tutorials.jenkov.com/java-collections/streams.html
https://docs.oracle.com/javase/tutorial/collections/interfaces/index.html

Anuncios

Jackson JSON – Deserializar un array en una petición REST

En un servicio REST (jax-rs) puedes enviar los parámetros de una petición de varias formas: en la URL (@QueryParam), en el cuerpo del mensaje con el encabezado “application/x-www-form-urlencoded” (@FormParam), como parte de la URL (@PathParam).

Pero que pasa si el cliente envía toda la información en el cuerpo del mensaje en formato JSON.
Por ejemplo:

    {
        "tipo":"URGENTE",
        "actores":[
        {
            "nombre":"Juan",
            "apellidos":"Peréz",
            "idEstado":null,
            "idMunicipio":null,
            "idColonia":null,
            "calle":"Calle 2",
            "numero":"155",
            "codigoPostal":"76800"
        }
        ],
        "demandados":[
        {
            "nombre":"María",
            "apellidos":"López",
            "idEstado":null,
            "idMunicipio":null,
            "idColonia":null,
            "calle":"Calle 4",
            "numero":"45",
            "codigoPostal":"76800"
        }
        ]
    }

Podríamos crear una clase que reflejará esta estructura, pero si solo nos interesa algún campo o la petición no tiene nada que ver con nuestro modelo, no parece la mejor opción.

En este caso, en nuestro modelo existiría una clase Actor y Demandado que comparten los mismos campos, por lo que podríamos usar la herencia.

    public class Parte {
        String id;
        String nombre;
        String apellidos;
        String idEstado;
        String idMunicipio;
        String idColonia;
        String calle;
        String numero;
        String codigoPostal;
        public Parte() {
        }
        //... getter's y setter's, métodos, etc.
    }
    public class Actor extends Parte{
        //... otras propiedades
        public Actor() {
        }
        //... otros métodos
    }
    public class Demandado extends Parte{
        //... otras propiedades
        public Actor() {
        }
        //... otros métodos
    }

en nuestro servicio REST (Apache CXF) podríamos deserializar el arreglo de Actores de la siguiente forma

    @Path("solicitar/")
    public String solicitar(String data){
        String response = null;
        try{
            ObjectMapper mapper=new ObjectMapper();
            mapper.configure(SerializationConfig.Feature.WRITE<em>DATES</em>AS<em>TIMESTAMPS, false);
            mapper.configure(Feature.FAIL</em>ON<em>UNKNOWN</em>PROPERTIES, false);
            Map<String, Object> map = mapper.readValue(data, new TypeReference<Map<String, Object>>(){});
            String tipo = (String) map.get("tipo");
            List
<Parte> actores = mapper.convertValue(map.get("actores"), new TypeReference
<List<Parte>>() {});
            //... registrar la solicitud
            response = mapper.writeValueAsString(actores);
        }catch(Exception e){
            String error = "Ocurrió un problema al hacer la solicitud";
            log.error(error, e);
            response = String.format("{\"response\":{\"status\": -1, \"data\": \"%s\"}}", error);
        }
        return response;
    }

Fuentes:
http://wiki.fasterxml.com/JacksonDataBinding
http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-DealingwithParameters

Java – ¿Qué uso, Array o List?

ArrayVSList
Dentro de nuestros programas siempre habrá algun pedazo de código donde utilicemos arreglos.
Mientras implementaba unos métodos para insertar y eliminar registros de una clase, noté que en algunos había utilizado Arrays y en otros Lists. Por ello decidí buscar que es lo que recomendaban otros programadores al respecto, fue así como encontré este artículo.

Finalmente quede convencido de utilizar Lists debido a la flexibilidad que ofrecen.

Ejemplo:

public static void insert(List<Dato> datos) {
  //... configuracion de conexion
  for(Dato dato:datos){
	db.executeUpdate("insert into datos(desc,cantidad) values(:desc,:cantidad)",
	new Object[]{dato.getDescripcion(),dato.getCantidad()});
  }
}

VS.

public static void insert(Dato[] datos) {
  //... configuracion de conexion
  for(Dato dato:datos){
	db.executeUpdate("insert into datos(desc,cantidad) values(:desc,:cantidad)",
	new Object[]{dato.getDescripcion(),dato.getCantidad()});
  }
}

Como puedes observar, es prácticamente lo mismo, la diferencia es que al invocar el primer método puedes pasar como párametro un ArrayList, LinkedList, Vector o tu propia clase que implemente la interfaz List ;-).

byte!