Bitsmi Blog

Anidar listas de objetos de negocio en un modelo Json mediante Swagger

02-07-2018 - Xavsal

Implementación

Para poder anidar distintos objetos de negocio dentro del Swagger, el primer paso consiste en añadir éstos en la sección definitions del Swagger.

Aquí deben declararse todos los que se van a utilizar para crear la lista de objetos de tipo Element según el ejemplo que se ha desarrollado.

Una vez añadidas las definiciones se añade al Swagger el siguiente código:

ElementList:  
    type: array
    description: Elements List.
    items:
      $ref: '#/definitions/Element'

Type indica a Swagger que el elemento contenido es de tipo array. Description describe la lista de elementos de la lista.

items:
    $ref: '#/definitions/Element'      

Con esta sintaxis se indica a Swagger que cada elemento de la lista ElementList se corresponde con una definición de objeto de negocio cuya definición també aparecerá cuando Swagger muestre el modelo general.

Se pueden anidar varios niveles en la creación de un objeto complejo. En el caso de ejemplo que se describe en el apartado siguiente se puede visualizar tres niveles: ElementList -> Element que contiene a su vez listas del tipo Acces e Invoice.

more…

Error Handshake Failure al establecer una conexión SSL

25-05-2018 - Antonio Archilla

Descripción de error

Se produce un error de tipo Handshake Failure (detalle del tipo de error en este enlace) cuando se intenta establecer una conexión con un servidor externo a través del protocolo SSL.

more…

OCP7 11 – Hilos (02) – Control de Errores Inesperados

17-02-2018 - Antonio Archilla

La clase Thread cuenta con un mecanismo de control de errores para casos en que se produzca un final inesperado a la ejecución de éste. A través del método setUncaughtExceptionHandler de la clase Thread es posible recoger la causa de esta finalización anómala dentro del hilo principal de la aplicación y actuar en consecuencia.

more…

OCP7 08 – Aserciones

07-02-2018 - Antonio Archilla

La aserción es un mecanismo que permite comprobar suposiciones en el código que ayudan a confirmar el buen funcionamiento del mismo y que este está libre de errores. En el siguiente post se muestra su funcionamiento básico y las situaciones en las que es apropiado su uso y en las que no. Una expresión de tipo aserción se identifica por la palabra clave assert. Su sintaxis es la siguiente:

assert <expression> [: <message>]

Where:

  • expression: Expresión booleana que indicará si la suposición se cumple o no. En caso de que no se cumpla, se lanzará un error de tipo AssertionError
  • message: Opcional. Si se indica un valor en la expresión, este será adjuntado en el error AssertionError producido.

more…

OCP7 11 – Hilos (03) – Mecanismos básicos en la plataforma Java

27-01-2018 - Xavsal

En este artículo se exponen los mecanismos básicos que proporciona la plataforma estándar de Java para la implementación de tareas concurrentes detallada para su versión 7.

Se tratarán los siguientes conceptos:

  • Implementación de tareas mediante hilos de ejecución
  • Gestión del ciclo de vida de los hilos de ejecución mediante API

more…

OCP7 08 – Excepciones (II)

27-01-2018 - Xavsal

Extensión de los tipos de excepción estándar

En la medida de lo posible se deberá hacer uso de la jerarquía de excepciones provistas por la JDK. En caso de querer crear nuevos tipos, se deberán tener en cuenta los siguientes puntos:

  • Extender de RuntimeException o una de sus subclases en caso de definir un tipo de error no recuperable (Excepción no comprobada).
  • Extender de Exception o una de sus subclases (a excepción de RuntimeException) en caso de definir un tipo de error recuperable (Excepción comprobada) que debe ser explícitamente declarado y capturado.
  • No extender directamente de la clase Throwable, ya que la mayoría de tratamientos de errores mediante bloques try/catch se hace como mínimo a nivel de Exception. En estos casos, las excepciones derivadas directamente de Throwable no serían capturadas por estos bloques lo que podría provocar efectos no previstos.

Tratamiento y propagación de excepciones

Se puede encontrar más información aquí.

Propagación entre métodos

Cuándo se gestionan las excepciones, hay ocasiones que se desea relanzar una excepción que está siendo gestionada. Un programador novicio cree que el código siguiente puede hacer esto:

public class EjemploExceptionRethrow {
    public static void demoRethrow()throws IOException {
    try {
         
        // Se fuerza el lanzamiento de una IOException cómo ejemplo,
        // Normalmente la excepción es disparada por la ejecución de código.
        throw new IOException(Error);
    }
    catch(Exception exception) {
         
     /* Se trata la excepción y se relanza */
     throw exception;
    }
   }
 
    public static void main(String[] args) {
        try {
            demoRethrow();
        } catch (IOException exception) {
            System.err.println(exception.getMessage());
        }
    }
}

El código anterior no compilará correctamente en caso de hacerse con versiones de Java anteriores a 7 ya que el método demoRethrow explicitamente especifica en su firma que la excepción lanzada es de tipo IOException, mientras que el bloque catch declara la excepción capturada y relanzada de tipo Exception. En este caso el compilador no es capaz de inferir el tipo real de la excepción. En caso de la compilación del código se realice sobre la versión 7 o posterior, el código anterior será válido y compilará correctamente. En este caso, el compilador sí es capaz de inferir el tipo final al que pertenece de la excepción relanzada analizando las excepciones lanzadas dentro del bloque try.

El siguiente ejemplo muestra otro modo de gestionar la excepción y propagarla.

public class EjemploAntiguoExceptionRethrow {
    public static demoRethrow() {
    try {
     throw new IOException("Error");
    }
    catch(IOException exception) {
     /*
       * Se trata la excepción y se relanza
       */
     throw new RuntimeException(exception);
    }
   }
 
    public static void main(String[] args) {
        try {
            demoRethrow();
        } catch (RuntimeException exception) {
            System.err.println(exception.getCause().getMessage());
        }
    }
}

El problema con el código anterior es que realmente no está relanzando la excepción original. La está encapsulando con otra excepción, lo que implica que el código del catch del main necesita gestionar la excepción con la que se ha encapsulado el catch original.

Captura de excepciones mediante bloque try/catch/finally

Java 7 permite capturar múltiples excepciones en un mismo bloque catch. Este mecanismo es llamado multicatch.

try {
 
    // Ejecución que puede generar uno de los errores catch
 
} catch(SQLException e) {
    System.out.println(e);
} catch(IOException e) {
    System.out.println(e);
} catch(Exception e) {
    System.out.println(e);
}

A partir de Java 7 se puede implementar el multicatch.

try {
    // Ejecución que puede generar uno de los errores catch
} catch(SQLException | IOException e) {
    System.out.println(e);
} catch(Exception e) {
    System.out.println(e);
}

A destacar la utilización del carácter pipe | para separar los nombres de las clases. El carácter pipe | entre los nombres de las excepciones es el mecanismo cómo se declaran las múltiples excepciones a ser capturadas por el mismo catch.

Para un mayor detalle en el siguiente enlace se puede encontrar más información sobre la implementación del multicatch.

Bloque try with resources

Implementación de la interfaz Closeable. Para evitar que recursos como ficheros, comunicaciones con la BBDD u otros servicios queden en un estado indeterminado tras un error, Java cuenta con mecanismos para evitar este tipo de situaciones, uno de los cuáles es el try-with-resources, Similar al try pero con las siguientes diferencias:

  • Diferencia de que entre paréntesis se declaran aquellos recursos que se desean proteger.
  • Un recurso siempre debe ser cerrado después de que termine el programa.
  • Un recurso es cualquier objeto que implemente la clase java.lang.AutoCloseable.

Los recursos de este bloque de código deben implementar la interfaz java.io.Closeable (que hereda de AutoCloseable – se recomienda mejor utilizar este objeto). Utilizando este bloque de código el programador no tiene que preocuparse de cerrar los recursos utilizados dentro del try-with-resources.

Una de las ventajas de Autocloseable consiste en poder llamar varias veces a su método close() obteniendo siempre el mismo resultado. Las excepciones generadas durante el proceso de cierre de un recurso son totalmente ignoradas.

Es importante indicar que el orden del cierre de recursos es el opuesto al orden de apertura de esos recursos: el primer recurso en abrirse es el último recurso en cerrarse.

Ejemplo para definir un nuevo objeto try-with-resources

package TryWithResources;
 
public class NewResource implements AutoCloseable{
     
    String closingMessage;
  
    public NewResource(String closingMessage) {
        this.closingMessage = closingMessage;
    }
  
    public void doSomeWork(String work) throws ExceptionA{
        System.out.println(work);
        throw new ExceptionA("Exception thrown while doing some work");
    } 
 
    @Override
    public void close() throws ExceptionB{
        System.out.println(closingMessage);
        throw new ExceptionB("Exception thrown while closing");
    }
  
    public void doSomeWork(NewResource res) throws ExceptionA{
        res.doSomeWork("Wow res getting res to do work");
    }
}

Ejemplo de su utilización en la ejecución de un programa

package TryWithResources;
 
public class TryWithRes {
 public static void main(String[] args) {
   
        try(NewResource res = new NewResource("Res1 closing")) {
            res.doSomeWork("Listening to podcast");
    
        } catch(Exception e) {
            System.out.println("Exception: "+e.getMessage()
    +" Thrown by: "+e.getClass().getSimpleName());
        }
    }
}

Ejemplo cuándo existen recursos anidados ambos derivando de AutoCloseable.

package TryWithResources;
 
public class TryWithResV2 {
 
    public static void main(String[] args) {
 
        try (NewResource res = new NewResource("Res1 closing");
                 NewResource res2 = new NewResource("Res2 closing")) {
 
         try (NewResource nestedRes = new NewResource("Nestedres closing")) {
                nestedRes.doSomeWork(res2);
         }
        } catch (Exception e) {
            System.out.println("Exception: " + e.getMessage() 
                + " Thrown by: " + e.getClass().getSimpleName());
        }
    }
}

Nótese el uso del carácter » ; » cómo separador en la declaración de los recursos dentro del bloque try-with-resources.

Tratamiento de excepciones no capturadas

En el procesado de hilos (Threads) puede producirse que su ejecución termine de forma abrupta debido a que se ha producido una excepción y ésta no ha sido capturada. Java dispone a partir de la versión 5 de la Interface UncaughtExceptionHandler perteneciente al paquete java.lang. Esta interface es invocada cuándo un hilo (Thread) termina abruptamente su ejecución debido a una excepción no capturada.

El siguiente código de ejemplo muestra la utilización de esta Interface.

public class MultiplexUncaughtExceptionHandler implements UncaughtExceptionHandler {
    private final UncaughtExceptionHandler[] handlers;
 
    public MultiplexUncaughtExceptionHandler(UncaughtExceptionHandler... handlers) {
        super();
        this.handlers = Arrays.copyOf(handlers, handlers.length);
    }
 
    public void uncaughtException(Thread t, Throwable e) {
        for (UncaughtExceptionHandler handler : handlers) {
            try {
                handler.uncaughtException(t, e);
            } catch (Throwable th) {
                th.printStackTrace();
            }
        }
    }
}

Se puede encontrar más información en este enlace oficial de Oracle.

more…

OCP7 13 – Localización

18-10-2017 - Xavsal

Las especificaciones para el uso de recursos en formato de fichero de propiedades a través de la API ResourceBundle de Java definen unas reglas para la nomenclatura y ubicación de dichos ficheros que hay que seguir de forma que la JVM pueda localizar y recuperar los recursos definidos en ellos. No obstante, dicha API proporciona mecanismos que permiten personalizar este proceso. En este POST se explica cómo hacerlo.

more…

Spring Boot – Configuración del contenedor subyacente

14-05-2017 - Antonio Archilla

Una de las principales características del framework Spring Boot es permite la ejecución de aplicaciones web sin necesidad de usar servidores de aplicaciones externos donde desplegarlas. Esto lo consigue mediante el uso de un contenedor incrustado en la misma aplicación (Tomcat, Jetty o Undertow). Aunque el framework configura por defecto este contenedor con valores válidos en muchos de los casos, a veces las peculiaridades de las aplicaciones hacen que se tengan que modificar ciertos parámetros de la configuración, como por ejemplo el soporte para HTTPS o el tamaño máximo peticiones de las peticiones, por poner algunos ejemplos. En este post se explicará la manera de personalizar estos valores.

more…

SQL – Encapsulado de sentencias complejas

30-09-2016 - Antonio Archilla

En muchas ocasiones el acceso a un conjunto de datos almacenado en base de datos requiere de una consulta especialmente compleja. En los casos en que se debe permitir acceso a sistemas externos a estos datos, la solución ideal pasa por implementar una capa de negocio intermedia entre la aplicación consumidora de la información y la base de datos, sea mediante servicios web, un data-grid u otra componente que permita abstraer la complejidad de la obtención de los datos para facilitarla al sistema externo. Hay casos en que esto no es posible y por requerimientos de arquitectura en el sistema, las aplicaciones externas deben acceder directamente a la base de datos para obtener la información. En estos supuestos, es buena idea implementar una interfaz para la obtención de los datos, una API que permita crear una caja negra sobre la implementación real de la obtención de los datos. Con ello se consigue: Las modificación de las estructuras subyacentes de la base de datos no afectan a la integración con el sistema externo al mantenerse la interfaz de obtención de datos. Permite mantener el control de cómo se obtienen los datos, lo que minimiza la posibilidad de errores al estar centralizada en una única implementación. Ante la aparición de errores, se minimiza el tiempo necesario para la corrección, ya que estaría localizada en un único punto: La implementación de la interfaz. En este post se propone un posible mecanismo para construir estas interfaces de acceso aplicado a bases de datos Oracle.

more…

SQL – Expresiones de Tablas Comunes (CTE)

14-08-2016 - Antonio Archilla

Las Expresiones de Tabla Común, en inglés Common Table Expressions (CTE), se pueden definir cómo la especificación de un conjunto de resultados temporales que se obtienen a través de una subconsulta determinada. El ámbito de aplicación de este conjunto de datos queda restringido a una ejecución concreta de la instrucción SQL en la que se encuentra definida (SELECT, INSERT, UPDATE o DELETE), momento a partir del cual, dichos resultados son eliminados del contexto de ejecución. Dicho de una manera un tanto simplista y haciendo un símil con conceptos aplicables a la programación imperativa, sería cómo la definición de una subrutina local, en el sentido que permite definir un código, en este caso una consulta que devuelve un conjunto de resultados determinados, asignarlo a un identificador determinado y usarlo cómo referencia dentro de otras partes de la consulta principal.

Algunas de las ventajas que proporciona su utilización son:

  • Permite evitar la reevaluación de una subconsulta que se ejecute múltiples veces dentro de la consulta principal
  • Simplifica la escritura y legibilidad de consultas complejas en las que se realicen definiciones de tablas derivadas (definidas dentro de la clausula FROM cómo una subconsulta) en uno o múltiples niveles
  • Permite substituir la definición de vistas globales cuando sólo están restringidas a una sola consulta, ayudando a no ensuciar el espacio global de nombres con definiciones innecesarias
  • Permite realizar operaciones de agrupación o condicionales sobre datos derivados de operaciones escalares o no deterministas. En este caso se podrá definir el cálculo de las operaciones requeridas dentro de la consulta CTE y posteriormente realizar las agrupaciones necesarias en la consulta principal o en otra CTE como si de valores de una tabla corriente se tratara

Aunque forma parte del estándard SQL-99, su implementación por parte de los motores de base de datos que soportan este estándar es opcional:

  • Oracle: Soportado a partir de la versión 9i r2
  • MS SQL Server: Soportado a partir de la versión 2008
  • PostgreSQL: Soportado a partir de la versión 8.4
  • SQLLite: Soportado a partir de la versión 3.8.3
  • IBM DB2: Soportado
  • MySQL y su derivada MariaDB no lo soportan aún

more…

results matching ""

    No results matching ""