Buscando artículos sobre " Programación"
23-abril-2022
admin

Uso de Profiles en Spring-boot

Distintas formas de manejar de los profiles con spring-boot para personalizar las ejecuciones:

1 – Establecer el profile en la property spring.profiles.active. Esto lo que hace es que si por ejemplo le establecemos el profile prof1 la aplicación irá a buscar la configuración al application-prof1.properties.

//file: application.properties
spring.profiles.active = prof1

2 – Podemos en ejecución decirle a una clase que utilice un profile distinto al marcado. Utilizando para ello la anotación @ActiveProfiles

@SpringBootTest
@ActiveProfiles("prof2")
class Example2ProfileTest {
...
}

3 – Puedes definir beans en función de un profile utilizando la anotacion @Profile en la clase que vas a definirlos.
A continuación, un ejemplo de como se genera un bean en función de si el profile es prof3 u otro con un test de prueba.

@Profile("prof3")
@Configuration
public class Prof3Configuration {
	@Bean
	public String helloWorld() {
		return "Hello World prof3";
	}
}

@SpringBootTest
@ActiveProfiles("prof3")
class Example3ProfileTest {
	@Resource(name = "helloWorld")
	private String helloWorld;
	@Test
	void dummyTest() {
		Assertions.assertEquals(helloWorld, "Hello World prof3");
	}
}
@Profile("!prof3")
@Configuration
public class NotProf3Configuration {
	@Bean
	public String helloWorld() {
		return "Hello World other not prof3";
	}
}

@SpringBootTest
@ActiveProfiles("other")
class ExampleNot3ProfileTest {
	@Autowired
	private String helloWorld;
	@Test
	void dummyTest() {
		Assertions.assertEquals(helloWorld, "Hello World other not prof3");
	}
}

4 – Se puede utilizar la property spring.profile.include para incluir profiles adicionales a la ejecución:

//application.properties
spring.profiles.include=prof4a,prof4b

//application-prof4a.properties
custom.hello.world.4a=Hello World prof4a
custom.hello.world.4b=x

//application-prof4b.properties
custom.hello.world.4b=Hello World prof4b
@SpringBootTest
class Example4ProfileTest {
	@Value("${custom.hello.world.4a}")
	private String customHelloWorld4a;
	@Value("${custom.hello.world.4b}")
	private String customHelloWorld4b;
	@Test
	void dummyTest() {
		Assertions.assertEquals(customHelloWorld4a, "Hello World prof4a");
		Assertions.assertEquals(customHelloWorld4b, "Hello World prof4b");
	}
}

5 – Uso de profiles de maven junto con los de Spring-Boot


	
		
			prof1
	        
	            true
	        
			
				prof1
			
		
		
			prof5
			
				prof5
			
		
	



	    
	        
	            src/main/resources
	            true
	        
	    
...

//application.properties
spring.profiles.active=@spring.profiles.active@
@SpringBootTest
class Example5ProfileTest {

	@Value("${custom.hello.world}")
	private String customHelloWorld;
	
	@Value("${spring.profiles.active}")
	private String profileActive;
	
	 @BeforeEach
	 public void beforeMethod() {
		 assumeTrue( profileActive.equals("prof5"));
	 }
	 
	@Test
	void dummyTest() {
		Assertions.assertEquals(customHelloWorld, "Hello World prof5");
	}

}

Al contruir con maven podemos indicar un profile definido en el pom.xml o bien no poner ninguno y que coje el indicado como default «prof1»

mvn clean test -Pprof5

Ejemplos

17-abril-2022
admin

Cifrado de contraseñas en Spring-Boot con Jasypt

Jasypt se trata de una herramienta de cifrado simplificado de Java. Te permite agregar funciones básicas de cifrado a los proyectos sin mucha complejidad.

Un ejemplo de uso muy sencillo con Spring-Boot, sería tal que así:

1 – Incorporamos la dependencia al pom.xml.

	
	        com.github.ulisesbocchio
	        jasypt-spring-boot-starter
	        3.0.4
	

2 – Podemos incorporar el plugin de maven para jasypt que nos va permitir ejecutarlo via mvn.

	
		
		      com.github.ulisesbocchio
		      jasypt-maven-plugin
		      3.0.4
		 
	
# Encriptamos 'theValueYouWantToEncrypt' con la contraseña 'the password'
mvn jasypt:encrypt-value -Djasypt.encryptor.password="the password" -Djasypt.plugin.value="theValueYouWantToEncrypt"

[INFO] 
ENC(MQoklieA16Tq1gTsyuaGm63ii3skRWMaWyAyObD8Ca7Nqx/SouDq3J4HigJUKDn90xxMIrZQmoQ7hDW7HjNDaQ==)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.361 s
[INFO] Finished at: 2022-03-04T08:11:23-08:00
[INFO] ------------------------------------------------------------------------


# Desencriptamos la clave 'MQoklieA16Tq1gTsyuaGm63ii3skRWMaWyAyObD8Ca7Nqx/SouDq3J4HigJUKDn90xxMIrZQmoQ7hDW7HjNDaQ==' con la contraseña 'the password'
mvn jasypt:decrypt-value -Djasypt.encryptor.password="the password" -Djasypt.plugin.value="MQoklieA16Tq1gTsyuaGm63ii3skRWMaWyAyObD8Ca7Nqx/SouDq3J4HigJUKDn90xxMIrZQmoQ7hDW7HjNDaQ=="

[INFO] 
theValueYouWantToEncrypt
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.801 s
[INFO] Finished at: 2022-03-04T08:12:45-08:00
[INFO] ------------------------------------------------------------------------

3 – Configuración
Jasypt tiene una serie de propiedades para su configuración. Todas tienen un valor por defecto a excepción de jasypt.encryptor.password que contiene la contraseña que se va utilizar para la encriptación.
Por otro lado, a las propiedades encriptadas se les debe poner como valor el prefijo ENC( y el sufijo ) (esto también es configurable).

Para un ejemplo sencillo voy definir unicamente en el application.properties la password de encriptación y la propiedad encriptada:

	
jasypt.encryptor.password=the password
prop.encrypt=ENC(m2laknHcOeMybfARtNAPY6E8490/XBNFovqcaX1cvlcNt+roju7RF0IaE1XByYTKXxfQD39F5e/UfYBHLyWjwA==)

3 – Test de prueba

	
@SpringBootTest
@EnableEncryptableProperties
class ExampleJasyptApplicationTests {
	@Autowired
	Environment environment;
	
	@Test
	void encryption_test() {
	    assertEquals(
	      "theValueYouWantToEncrypt", 
	      environment.getProperty("prop.encrypt"));
	}
}

– Documentación Oficial

– Github con ejemplo

9-abril-2022
admin

Medición de tiempo de ejecución con StopWatch

StopWatch es un simple cronómetro que permite medir el tiempo de las tareas. Expone el tiempo total de ejecución y el tiempo de ejecución de cada tarea nombrada.

Documentación Oficial – StopWatch

A continuación, se exponen una serie de formas de utilizarlo con Spring-Boot:

Medición tests configurando el StopWatch en las fases ( @AferAll, … )

@SpringBootTest
class StopwatchApplicationTests {

	static StopWatch stopWatch = new StopWatch();
	
	@BeforeAll
	static void setUp() {
		stopWatch =  new StopWatch();
	}
	
	@BeforeEach
	void timeSetUp(TestInfo testInfo) {
		stopWatch.start( testInfo.getTestMethod().get().getName());
	}
	
	@AfterAll
	static void setDown() {
		System.out.print( stopWatch.prettyPrint() );
	}
	
	@AfterEach
	void timeSetDown() {
		stopWatch.stop();
	}

	@Test
	void test_one() throws InterruptedException {
		Thread.sleep(2000);
	}
	...
}

Resultado obtenido

StopWatch '': running time = 6011364520 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
2008182259  033 %  test_one
2001327545  033 %  test_two
2001854716  033 %  test_three

Medición de los test utilizando un TestExecutionListener
Es necesario crear un listener que extienda de AbstractTestExecutionListener, el cuál nos permitirá sobreescribir los métodos beforeTestClass, afterTestClass, afterTestMethod,…

public class ExecutionTimeTestListener extends AbstractTestExecutionListener {
    private StopWatch stopWatch;

    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {
        super.beforeTestClass(testContext);
        stopWatch = new StopWatch(testContext.getTestClass().getSimpleName());
    }

    @Override
    public void beforeTestMethod(TestContext testContext) throws Exception {
        super.beforeTestMethod(testContext);
        stopWatch.start(testContext.getTestMethod().getName());
    }

    @Override
    public void afterTestMethod(TestContext testContext) throws Exception {
        if (stopWatch.isRunning()) {
            stopWatch.stop();
        }
        super.afterTestMethod(testContext);
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        System.out.println(stopWatch.prettyPrint());
        super.afterTestClass(testContext);
    }
}

Forma de utilización:

@ExtendWith(SpringExtension.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, 
	ExecutionTimeTestListener.class})
class StopwatchWithListenerApplicationTest {
	@Test
	void test_one() throws InterruptedException {
		Thread.sleep(2000);
	}
	...
}

Resultado obtenido

StopWatch 'StopwatchWithListenerApplicationTest': running time = 6017421650 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
2013933526  033 %  test_one
2001191940  033 %  test_two
2002296184  033 %  test_three

Configuración utilizando Aspectj
Se crea un aspecto para que capture todas las ejecuciones del paquete service. Ademas se le pone el @Around para que envuelva el método que captura. Así podemos poner el StopWatch para que medir el tiempo que tarda en ejecutarlo.

Requiere añadir la dependencia spring-boot-starter-aop.

	    
	        org.springframework.boot
	        spring-boot-starter-aop
	    
@Aspect
@Component  
public class StopWatchAOP {
	
    @Around("execution(* es.com.disastercode.examplesspringboot.stopwatch.service.*.*(..))")
    public Object measureMethod(ProceedingJoinPoint pjp) throws Throwable
    {
        StopWatch sw = new StopWatch();
        Object retVal;
        try {
            sw.start(pjp.getTarget()+"."+pjp.getSignature());
            retVal = pjp.proceed();
        } catch (Throwable e) {
            throw e;
        } finally {
            sw.stop();
            System.out.println(sw.prettyPrint());
        }
        return retVal;
    }
}

Ejemplo de test.

@SpringBootTest
class StopwatchWithAopApplicationTests {
	@Autowired
	private ProductService productService;
	@Test
	void test_one() throws InterruptedException {
		assertEquals("name 2", this.productService.findNameProductById(2));
	}
}

Resultado obtenido

StopWatch '': running time = 2050920963 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
2050920963  100 %  es.com.disastercode.examplesspringboot.stopwatch.service.ProductServiceImpl@3d20e575.String es.com.disastercode.examplesspringboot.stopwatch.service.ProductServiceImpl.findNameProductById(Integer)

Github con los ejemplos.

3-abril-2022
admin

Gestión de múltiples versiones de pyton en Ubuntu

– Paso previo, añadir software-properties-common y repositorio.

sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa

– Instalación de las versiones de python: 3.10 y 2.7.

sudo apt install python3.10
python3.10 --version

sudo apt install python2.7
python3.7 --version

– Configuración de ubuntu para facilitar el cambio de una version a otra.

//Creas enlaces simbolicos con update-alternatives
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.10 2

//Menu para seleccionar la version elegida
sudo update-alternatives --config python

//comprobar la versión activa
python --version

https://www.python.org/downloads/

20-marzo-2022
admin

Url dinámicas con react

Podemos parametrizar las urls en React. Esto nos va a permitir tener url dinámicas en función a unos parametros. Para ver su funcionamiento se muestra un ejemplo:

1 – Definición de parámetros en la url
Dado un route, podemos indicar los parámetros como en el ejemplo :category y :type





Fuente

2 – Utilización de esos parámetros en el componente invocado
La forma de recoger luego esos párametros seria con useParams.

import { useParams } from "react-router-dom"
...
const { category } = useParams()
...

Fuente

12-marzo-2022
admin

Hooks de React: useState y useEffect

Para poder utilizar estos hooks lo primero es importarlos.

import React, { useState, useEffect } from 'react';

– useState: se trata de una función que crea una variable donde se puede almacenar el estado del componente. Acepta un valor inicial para esa variable y devuelve un array con dos elementos, el valor de la variable y la función para modificarla.

const [isLoading, setIsLoading] = useState(false);

– useEffect: se usa para la inicialización o modificación de variables, llamadas a APIs, etc. La llamada a useEffect acepta una función como argumento que se ejecuta por defecto cuando el componente se renderiza por primera vez, y después cada vez que el componente se actualice o cuando se modifique alguno de los argumentos pasados como parámetros (en el ejemplo category y type).

  useEffect(() => {
    const fetchDataTxt = async () => {
      setIsLoading(true);
      try {
        const result = await axios("http://" + window.location.host + "/" + category + "/" + type + "/description.txt");
        setData(result.data);
      }catch(err){
        console.log("error http://" + window.location.host + "/" + category + "/" + type + "/description.txt");
      }
      setIsLoading(false);
    };
    fetchDataTxt();
  }, [category, type]);

Ejemplos

27-febrero-2022
admin

Enrutado dinámico en React: BrowserRouter vs HashRouter

En react para configurar las rutas tenemos la libreria react-router-dom. Podemos instalar con:

npm install react-router-dom

Esa librería tiene los componentes BrowserRouter y HashRouter. La principal diferencia entre ellos está en que con HashRouter se añade el # a las rutas url. Tal que así:

– HashRouter: https://gallery-react.disastercode.com.es/#/gallery/animales/gatos
En este caso el servidor ignora lo en la url lo que hay despues del #. Y el cliente es el que se encarga de interpretar esa parte de la ruta.

– BrowserRouter: https://gallery-react.disastercode.com.es/gallery/animales/gatos
En este otro caso el servidor intentará manejar la ruta completa. Por eso al recargar la página nos devolverá 404, al ser rutas que no existen en el lado del servidor.

Ejemplo con HashRouter

Fuente

19-febrero-2022
admin

Uso de dangerouslySetInnerHTML en React

Esta función te permite incrustar html directamente con React. Se utiliza en lugar de innerHTML.

const App = () => {
  const data = 'lorem ipsum';
  return (
dangerouslysetinnerhtml={{__html: data}}
  );
}
export default App;

Fuente

13-febrero-2022
admin

Dynamic React Gallery

Aplicación web realizada en React que partiendo de un fichero *.json completa dinámicamente todo su contenido. Generando una galeria de imágenes divididas por categorias.

El código se encuentra subido en el siguiente repositorio:
https://github.com/roberto-pf/DynamicReactGallery

Se ha generado la documentación mediante Compodoc y puede consultarse la documentación aquí:
https://roberto-pf.github.io/DynamicReactGallery/

Demo funcionando en este enlace: http://gallery-react.disastercode.com.es

27-septiembre-2020
admin

Resumen generación de documentación con Compodoc para Angular 10

Compodoc facilita la generación de la documentación de tu proyecto de Angular. A continuación, voy a exponer un resumen de como utilizarlo.

1 – Instalación

npm install -g @compodoc/compodoc

2 – Añadir en package.json el comando que lo ejecuta.

"scripts": {
"compodoc": "npx compodoc -p tsconfig.app.json"      
//En angular 10 tuve que poner tsconfig.base.json para 
//que me generase bien la documentación.
}

3 – Ejecutar la creación de la documentacion

npm run compodoc

————————————————————————

Aunque hay muchas más, como se puede ver en la documentación que facilita la gente de Compodoc. Algunas de las opciones que se puede ir añadiendo al comando de ejecución son:

-d ---------> directorio destino
-o ---------> abre automáticamente la documentación en el navegador
-s ---------> levanta el servidor de node
--theme -----> selecciona el tema
--includes --> documentacion adicional. Se pone el directorio del summary.json. 
Se crean ficheros md. https://docs.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax
-w ---------> detecta los cambios en el código y actualiza la documentación.
--customFavicon -> cambia el favicon.
--hideGenerator -> oculta el logotipo de compodoc.
-y ----------> hoja de estilos propia para compodoc. Se le indica un directorio 
donde haya un style.css.

El comando de generación añadiendo todos esos flags quedaría así:

 "compodoc": "npx compodoc -p tsconfig.base.json -d docs -o -s 
--theme vagrant --includes ./aditionaldoc -w --customFavicon ./src/favicon.ico 
--hideGenerator -y ./src/assets/cssCompodoc"

————————————————————————

Los comentarios deben añadirse así:

- Documentar un método, variable, componente,....
/**
 *
 */

- Documentar parámetro de un método
/**
 * @param variable
 */

- Documentar retorno de un método
/**
 * @returns
 */

- Ignorar en la documentacion para que no salga
/**
 * @ignore
 */

- Ejemplo de uso de un componente u otro objeto.
/**
 * @example
 *
 */

. Se puede comprobar el nivel de comentarios añadidos en la sección de cobertura de código que te genera.

Excluir en el tsconfig.base.json los ficheros que no queremos que se revisen. Así no saldrán en la cobertura.

"exclude": [
"src/test.ts",
"e2e/**"
]

Ejemplo de uso

Fuente

Páginas:1234567...15»

Categorias

Linkedin