String [] intereses={"programación","sistemas","qa","cine","juegos","software libre","datos abiertos"}
for (String interes in intereses)
{
console.log(interes)
}
lunes, 12 de julio de 2021
Lectura para el verano
sábado, 26 de junio de 2021
Tests dinámicos con JUnit5
Hoy os quiero hablar de los test dinámicos.
Cuando pensamos en realizar test, normalmente tenemos muy claro las funcionalidades que queremos comprobar, pero a veces esas funcionalidades varían con el paso del tiempo, y nuestras pruebas tienen que adaptarse a estos cambios.
Aquí es donde entran en juego los test dinámicos.
Os voy a poner un par de ejemplos de este tipo de test:
- Imaginaros que tenéis que chequear un menú dentro de una pagina web, y ese menú actualmente tiene 4 opciones. Puede pasar que dentro de unos meses las opciones aumenten. Un test dinámico, primero leerá todas las opciones que tiene el menú, y después realizará las pruebas establecidas por cada una de ellas.
- Pensar en una base de datos que se carga todos los días a las 03:00 AM, y a las 04:00 AM se lanzan una serie de consultas de BBDD para verificar que la información es correcta. Imaginaros que algunas consultas se leen de un directorio que contiene ficheros *.QRY en los cuales están las consultas y el número de registros que se deben devolver. Un test dinámico primero procesará el directorio, para leer cada fichero, después lanzará tantos test como consultas haya leído en cada fichero.
private Integer[] getData() { List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(0); list.add(1); Integer[] array = list.toArray(new Integer[0]); return array; }
Stream<DynamicNode> dynamicTestsFromCollection() { return Stream.of(getData()) .map(number -> DynamicContainer.dynamicContainer("True or False Test" + number, Stream.of( DynamicTest.dynamicTest("is " + number + " true?", () -> assertTrue(Util.checkOne(number))), DynamicTest.dynamicTest("is " + number + " false?", () -> assertFalse(Util.checkOne(number)))))); }
- Test OK (1 es true)
- Test KO (1 es false)
- Test KO (0 es true)
- Test OK (0 es false)
- Test OK (1 es true)
- Test KO (0 es false)
domingo, 30 de mayo de 2021
Apache Derby vs. SQLite
Hoy os traigo un pequeño análisis para contaros las diferencias entre dos bases de datos que nos pueden venir muy bien para proyectos pequeños o para infraestructuras con un tamaño inicial reducido.
La primera se llama SQLite (https://www.sqlite.org), y es un sistema de base de datos que se encuentra dentro de muchas aplicaciones que utilizamos normalmente como navegadores o aplicaciones del móvil.
Es muy ligera, cada base de datos se gestiona dentro de un solo fichero y es ideal para procesos que no necesitan acceso concurrente. Por ejemplo para una aplicación de consola que se ejecuta periódicamente, y lo único que necesita es actualizar la información a través de un solo hilo en cada ejecución.
La otra se llama Apache Derby (https://db.apache.org/derby/), esta base de datos también se ejecuta en memoria, ocupa muy poquito espacio, y la mayor diferencia es que está preparada para procesos concurrentes. Por ejemplo una aplicación web donde varios hilos pueden escribir/consultar a la vez. Oracle la distribuye como JAVA DB
Como lo mejor en estos casos es hacer una pequeña prueba, próximamente voy a intentar hacer un pequeño proyecto con Apache Derby.
Nos vemos pronto.
miércoles, 21 de abril de 2021
Procesando ficheros grandes en JAVA
Cuando nos enteramos de estas cosas, nos gustaría saber si se han filtrado nuestros datos, pero para eso hay que tener los datos (algo que a veces es difícil de encontrar) y después tener las herramientas para abrir esos ficheros.
En los dos casos que he comentado, los ficheros eran texto plano, en formato CSV.
El primero ocupaba 800 MB y el segundo 5,36 GB
Yo no he conseguido abrir ninguno con las herramientas habituales.
Así que he escrito un pequeño programa que lee línea a línea cualquier fichero, busca en cada línea la cadena que nos interese, y las coincidencias que encuentra las escribe en otro fichero.
Podéis acceder a ese desarrollo desde aquí: https://github.com/tecnificados/bigFileOpps
Espero que os sea útil.
Nos vemos pronto.
Muchas gracias a Hugo y a Valandil por su ayuda consiguiendo los datos.
domingo, 18 de abril de 2021
Spring Boot: un CRUD hecho y derecho
Este es el quinto (y último) artículo de la serie sobre Spring Boot que comenzamos el mes de Febrero. Estos son los anteriores:
Hoy vamos a coger todo lo que hemos aprendido y transformar nuestras diferentes pruebas en un CRUD de Incidencias.
Antes de nada, ¿qué es eso? CRUD es un acrónimo de CREATE, READ, UPDATE Y DELETE. Cuando alguien nos habla de este término, a lo que se refiere es a un proyecto que permite realizar estas operaciones sobre una o más entidades.
En los diferentes commits que he hecho estos dos días he ido añadiendo operación por operación los diversos cambios en un nuevo Controlador (IncidenciasController), y añadiendo las diferentes JSPs:
lunes, 29 de marzo de 2021
Spring Boot: Seguridad básica
Este es el cuarto artículo de la serie sobre Spring Boot que comenzamos el mes de Febrero. Estos son los anteriores:
Usuario Tecnificado (Commit 69e7131)
@Bean @Override public UserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("Tecnificado") .password("ironman") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); }
Página de login y Lógica (Commit 2615f63)
public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/hello").setViewName("hello"); registry.addViewController("/login").setViewName("login"); }
<form class="form-signin" action="<c:url value='/login' />" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Página Hello y retoques (Commit 38fea25)
sábado, 13 de marzo de 2021
Spring Boot: Trabajando con bases de datos
Clases de acceso a datos, modelo, servicio y script de BBDD (Commit 92a6848)
CREATE TABLE incidencia (
id int(11) NOT NULL,
titulo varchar(255) DEFAULT NULL,
descripcion varchar(2000) DEFAULT NULL,
estado int(20) NOT NULL,
autor varchar(50) NOT NULL
);
ALTER TABLE incidencia
ADD PRIMARY KEY (id);
@Entitypublic class Incidencia {
@Id private Long id;
@Column private String titulo;
@Column private String descripcion;
@Column private Integer estado;
@Column private String autor;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTitulo() { return titulo; }
public void setTitulo(String titulo) { this.titulo = titulo; }
public String getDescripcion() { return descripcion; }
public void setDescripcion(String descripcion) { this.descripcion = descripcion; }
public Integer getEstado() { return estado; }
public void setEstado(Integer estado) { this.estado = estado; }
public String getAutor() { return autor; }
public void setAutor(String autor) { this.autor = autor; }
}
public interface IncidenciaDAO extends CrudRepository<Incidencia, Long> {
@Query(value = "SELECT coalesce(max(id), 0) FROM Incidencia") Long getMaxTransactionId();
}
- GenericService.java: interfaz genérica (que nos sirve para cualquier tabla).
- GenericServiceImp.java: implementación de la anterior.
- IncidenciaService.java: interfaz para Incidencia (aquí nos definimos las particularidades de nuestra clase).
- IncidenciaServiceImpl.java: implementación.
Configuración del pool de conexiones (Commit 1b9d186)
#Configuración del Pool de conexionesspring.datasource.initial-size=10spring.datasource.max-active=20spring.datasource.max-idle=5spring.datasource.min-idle=1
Cambios en el controlador que utilizan la BBDD (Commit e55a9aa)
@RequestMapping(DEFAULT) public ModelAndView index() {
List<Incidencia> list = incidenciaService.getAll(); ModelAndView model = new ModelAndView(); model.addObject("list", list); model.setViewName("index");
return model; }
DEFAULT es una constante que se corresponde con "/" que es la página por defecto: localhost:8080
@RequestMapping(ADD) @ResponseBody public String add() { Long id=incidenciaService.maxId()+1; Incidencia incidencia = new Incidencia(); incidencia.setId(id); incidencia.setAutor("Juan Carlos"); incidencia.setTitulo("Incidencia "+incidencia.getId()); incidencia.setDescripcion("La aplicación no arranca"); incidencia.setEstado(0); incidenciaService.save(incidencia);
return "added"; }
.antMatchers(StartController.DEFAULT, StartController.ADD, StartController.EMPTY, "/login", /resources/**").permitAll() .anyRequest().authenticated()
Cambios en la página inicial para mostrar la información de Incidencias (Commit 8a10cf3)
Ahora con logs (Commit f342578)
sábado, 27 de febrero de 2021
Spring Boot: Página inicial con Bootstrap
En el primer artículo vimos cómo descargar nuestro proyecto configurado para nuestros intereses y listo para ser importado en nuestro IDE (nosotros usaremos Eclipse).
Lo primero que vamos a hacer es importar el proyecto:
- File -> Import
- Existing Maven Projects
- Seleccionamos el fichero pom.xml en la carpeta donde lo hemos descomprimido y esperamos unos segundos
Con Spring Boot no necesitamos configurar el servidor, ya se encarga él de facilitarnos la vida. Lo único que tenemos que hacer es arrancar la clase BootApplication.java, que se encargará de arrancar Tomcat y dejar nuestra aplicación funcionando en el puerto 8080.
Y si todo fuera bien, podríamos acceder a través de la URL: http://localhost:8080/
Pero ahora mismo tenemos un error de conexión con base de datos que nos impide que la aplicación arranque.
Vamos a empezar a hacer unas cuantas modificaciones para que todo empiece a funcionar.
Para poder seguir todos los cambios he creado este repositorio en Github: https://github.com/tecnificados/boot
Ahora mismo tiene los siguientes commits:
Los tres primeros commits son la creación del repositorio y la subida del código que descargamos de https://start.spring.io/
El cuarto commit es una corrección para que no nos dé problemas la configuración con la base de datos, si no añadimos estas líneas en el pom.xml, nuestro desarrollo será incapaz de conectarse con la base de datos.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
Los dos últimos commits son los que quiero revisar con vosotros, ya que son los que nos van permitir hacer que la aplicación arranque y trabajar con JSPs, JSTL y añadir Bootstrap a través de sus recursos (css y js).
Cambios para poder trabajar con JSPs (Commit 757e5f2)
Lo primero que vamos a hacer es arreglar el problema con la base de datos. Debemos configurarla. Vamos a utilizar MySQL. Puedes instalarlo directamente, o utilizar la máquina virtual que subimos a Mega hace unas semanas (aquí el artículo).
No hace falta tener ninguna tabla, simplemente que el servicio esté funcionando.
Vamos a editar el fichero application.properties y dejarlo con la configuración de conexión a BBDD:
logging.level.root=info
#Configuración de Base de Datos
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#Url donde está el servicio de tu mysql y el nombre de la base de datos
spring.datasource.url=jdbc:mysql://localhost:3306/boot_demo?useSSL=false&serverTimezone=Europe/Madrid
#Usuario y contrasena para tu base de datos descrita en la línea anterior
spring.datasource.username=boot_demo
spring.datasource.password=boot_demo
#[opcional]Imprime en tu consola todo el SQL.
spring.jpa.show-sql = true
- /: la pagina inicial
- /resources/**: ruta donde estarán nuestros recursos estáticos
- /login: nuestra página de acceso
spring.mvc.view.suffix=.jsp
@Controllerpublic class StartController { @RequestMapping("/") public String mensaje() { return "index"; }}
Y para acabar este punto vamos a necesitar añadir la dependencia que permite ejecutar JSPs en nuestro fichero pom.xml:
<dependency> |
<groupId>org.apache.tomcat.embed</groupId> |
<artifactId>tomcat-embed-jasper</artifactId> |
<scope>provided</scope> |
Si ahora arrancamos de nuevo y accedemos a nuestro http://localhost:8080/ ahora deberíamos ver un saludo como este:
Es un poco simple, pero es un comienzo.Cambios para desarrollar con recursos. Bootstrap añadido (Commit 37cfa22)
Este commit es muy importante, ya que vamos a crear la clase de configuración del proyecto (MvcConfig), donde vamos a poder ir añadiendo 'piezas' según las vayamos necesitando. Y la primera pieza a añadir es decirle a Spring que nos permita servir recursos estáticos como CSS y ficheros JS.
Para empezar vamos a ir por esos recursos, nos vamos a la web oficial de Bootstrap y nos descargamos la versión que nos interese (4.6 por ejemplo): https://getbootstrap.com/docs/4.6/getting-started/download/
Esto nos descargará un zip, vamos a descomprimir su contenido en la carpeta: "src\main\webapp\resources"
Ahora ya tenemos que ya tenemos los recursos vamos a decirle a Spring dónde están y que nos permita acceder a ellos. Para esto creamos la clase MvcConfig.java
En el método addResourceHandlers configuramos dónde están nuestros recursos y con InternalResourceViewResolver configuramos dónde están nuestras JSPs. Esto último lo habíamos escrito en las primeras líneas del application.properties, como ahora debe estar aquí, lo borramos de ese fichero.
Ahora vamos a añadir dos dependencias nuevas a nuestro fichero pom.xml:
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
La primera es para poder usar las etiquetas JSTL en nuestras JSPs (los recursos los añadiremos con c:url) y la segunda es para que si hacemos modificaciones en nuestras páginas, Spring detecte los cambios sin tener que reiniciar.
Y para terminar vamos a modificar nuestra página de inicio para añadir acceso a los recursos que necesitamos y darle un formato un poco más llamativo.
Aquí os dejo un par de ejemplos para que veáis cómo se insertan recursos estáticos:
<script src="<c:url value="/resources/js/vendor/jquery.slim.min.js"/>"></script>
<link rel="stylesheet" href="<c:url value="/resources/css/bootstrap.min.css"/>" >
La página inicial la he modificado basándome en el ejemplo Jumbotron de Bootstrap.
De modo que ahora nuestra página de inicio, tiene un aspecto bastante diferente del anterior:
En este punto ya tenemos lista nuestra aplicación para interactuar con nuestra base de datos y poder aplicar seguridad a diferentes páginas. Y lo iremos viendo poco a poco en los siguientes artículos de la serie.
Nos vemos pronto.
sábado, 13 de febrero de 2021
Spring Boot: Introducción
Este el primero de una serie de artículos donde nos vamos a meter en Spring Boot.
Aquí en Tecnificados llevamos años trabajando con Spring, así que os voy a contar un poco de qué se trata.
Spring es un framework de desarrollo que contiene muchos proyectos (o módulos) que nos ayudan en el desarrollo de aplicaciones JAVA.
Por ejemplo, el más conocido es Spring MVC, que nos ayuda a generar aplicaciones web siguiendo el Modelo Vista Controlador, ayudado por la inyección de dependencias, que es la autentica revolución de este framework.
También podemos usar Spring Data para ayudarnos con las conexiones de BBDD, o Spring Security para securizar nuestra aplicación de diversas formas,... Si queréis profundizar más acerca de los diferentes proyectos, podéis acceder a esta página: https://spring.io/projects
Volviendo a Spring Boot, vamos a hacer un pequeño repaso a las fase de creación de un proyecto web sin utilizarlo:
- Seleccionaríamos las librerías (JARs) que necesitamos.
- Empezamos a codificar.
- Desplegamos en un servidor web (Tomcat normalmente).
Estas tres fases, normalmente no paran de iterar en un desarrollo, y a veces tenemos pequeños problemas que nos hacen perder tiempo (interacciones con el servidor sobre todo...)
Con Spring Boot esto no pasa, solo te tienes que centrar en la codificación, ya que con un pequeño paso inicial se establecen los parámetros iniciales (librería y servidor), y ya te puedes olvidar de ellos.
Pero no os asustéis, durante el desarrollo se pueden añadir más librerías (algo muy común), o cambiar de servidor (esto menos común).
Hoy os quiero enseñar a dar ese primer paso inicial. Para esto los desarrolladores de Spring han creado una herramienta online, que te permite generar la estructura inicial de tu proyecto con Spring Boot: https://start.spring.io/
Nosotros en la parte de la derecha hemos seleccionado estas opciones:
Las dependencias serán gestionadas con Maven, el desarrollo será en JAVA, utilizaremos la versión 2.4.2 de Spring Boot, y le ponemos nombre a nuestro desarrollo.
- Spring Web: desarrollo web, con Spring MVC que además nos permite realizar desarrollos REST.
- Spring Security: vamos a añadir una seguridad básica a nuestra aplicación, y controlar que las llamadas REST sean internas.
- Spring Data: toda la gestión de conexión con BBDD la realizará este módulo
- MySQL Driver: esta será nuestra BBDD.
Y esto nos descargará un fichero "boot.zip", para poder abrirlo con nuestro IDE favorito (el mío es eclipse).
sábado, 6 de febrero de 2021
SQuirreL SQL Client - Un cliente para dominarlos a todos
Está desarrollado con JAVA (versión desde 1.8 a 14), para empezar ese es el único requisito que tenemos que cumplir.
En la sección de descargas tenemos que elegir el jar que se ajuste a nuestro sistema operativo. Una vez descargado, hacemos doble click en él, y se inicia un instalador de tipo next, next, next...
En el caso de Windows la ruta por defecto, da un error por permisos:
Yo la he cambiado a "D:\squirrel" y todo ha acabado bien.
Una vez instalado, si lo ejecutamos, veremos una pantalla en blanco, antes de nada debemos pulsar en la pestaña "Drivers" de la izquierda:
domingo, 31 de enero de 2021
Cambio disco duro a SSD en ordenador portátil
- El disco duro: había discos duros más baratos, pero prefiero apostar por una buena marca: Western Digital. Más información.
- El adaptador de disco duro interno. Más información.
- El adaptador a USB. Más información.
- Extraer el disco duro original y meterlo dentro del "caddy".
- Colocar el nuevo disco donde estaba el original.
- Volver a colocar los tornillos y la tapa.
- Colocar el caddy y apretar el último tornillo.