GraalVM, una máquina virtual políglota que proporciona un tiempo de ejecución compartido para ejecutar aplicaciones escritas en múltiples lenguajes como Java, C, Python y JavaScript, ha lanzado la versión 19.3 con soporte para JDK 11. Las versiones anteriores de GraalVM se basaban en JDK 8.
Las numerosas funciones de lenguaje y mejoras de plataforma como cadenas compactas, inferencia de tipo variable, Java Platform Module System (JPMS) y cliente HTTP, que se entregaron entre la versión Java 9 y la versión Java 11 ahora pueden ser utilizadas por aplicaciones JVM creadas en GraalVM.
Por ejemplo, el siguiente fragmento muestra cómo se puede construir e invocar una solicitud simple a una API REST de bitcoin utilizando el nuevo cliente HTTP Java 11:
public class BPI {
public static void main(String... args) {
var request = HttpRequest
.newBuilder()
.uri(URI.create("https://api.coindesk.com/v1/bpi/currentprice.json"))
.GET()
.build();
var response = HttpClient
.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofInputStream());
var json = Json
.createReader(response.body())
.readObject()
.getJsonObject("bpi");
…
System.out.printf("Current Bitcoin Price: $%s %s", price, indicator);
}
}
Con JAVA_HOME y PATH apuntando a una instalación de GraalVM, las clases basadas en Java 11 como la clase de ejemplo anterior se pueden compilar utilizando el compilador javac o una herramienta de compilación como Maven.
La utilidad de generación de imágenes nativas de GraalVM también se ha actualizado para admitir Java 11 como una característica de tecnología. Una imagen nativa es un código de bytes Java compilado con anticipación empaquetado como un ejecutable independiente. La imagen nativa generalmente logra un tiempo de inicio más rápido. La imagen nativa no es compatible con Java Platform Module System y no tiene introspección de módulo en tiempo de ejecución de imagen. La utilidad de imagen nativa es un paquete opcional que se puede instalar usando el Actualizador GraalVM, gu. gu es un administrador de paquetes que descarga e instala paquetes no incluidos en la distribución principal de GraalVM.
Para aquellos que usan Maven como herramienta de compilación, se proporciona un complemento Maven para ayudar en el proceso de generación de imágenes.
También tenga en cuenta que dado que el recolector de basura Garbage-First (G1) es el recolector de basura predeterminado en Java 11, se debe tener cuidado al migrar aplicaciones sensibles al rendimiento de GraalVM basado en JDK 8 a GraalVM basado en JDK 11.
Además del soporte para JDK 11, esta primera versión de soporte a largo plazo (LTS) de GraalVM proporciona mejoras en la generación de imágenes nativas, el compilador GraalVM, herramientas como cobertura de código y GraalVM VisualVM junto con actualizaciones en tiempo de ejecución de los lenguajes NodeJS, Python y R.
Dejo link: https://www.graalvm.org/
Translate
domingo, 5 de enero de 2020
jueves, 2 de enero de 2020
Libros Gratuitos de Java Code Geek
|
lunes, 30 de diciembre de 2019
Feliz año nuevo!!!
El 2019 se fue un gran año, para la tecnología y para el blog...
Sin más espero que tengan un excelente año!!!
jueves, 26 de diciembre de 2019
Empezando con Rust, parte 4
Seguimos con Rust...
Ahora vamos a modificar la función main de este modo:
use std::io;
fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Este código contiene mucha información, así que repasemos línea por línea. Para obtener la entrada del usuario y luego imprimir el resultado como salida, necesitamos la biblioteca io (entrada / salida) . La biblioteca io proviene de la biblioteca estándar (que se conoce como std):
use std::io;
La función principal es el punto de entrada al programa:
fn main() {
La sintaxis fn declara una nueva función, los paréntesis, (), indican que no hay parámetros, y el corchete, {, inicia el cuerpo de la función.
println! es una macro que imprime una cadena en la pantalla:
println!("Guess the number!");
println!("Please input your guess.");
Ahora vamos a modificar la función main de este modo:
use std::io;
fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
println!("You guessed: {}", guess);
}
Este código contiene mucha información, así que repasemos línea por línea. Para obtener la entrada del usuario y luego imprimir el resultado como salida, necesitamos la biblioteca io (entrada / salida) . La biblioteca io proviene de la biblioteca estándar (que se conoce como std):
use std::io;
La función principal es el punto de entrada al programa:
fn main() {
La sintaxis fn declara una nueva función, los paréntesis, (), indican que no hay parámetros, y el corchete, {, inicia el cuerpo de la función.
println! es una macro que imprime una cadena en la pantalla:
println!("Guess the number!");
println!("Please input your guess.");
A continuación, crearemos un lugar para almacenar la entrada del usuario, así:
let mut guess = String::new();
Tenga en cuenta que esta es una declaración let, que se utiliza para crear una variable. Aquí hay otro ejemplo:
let foo = bar;
Esta línea crea una nueva variable llamada foo y la vincula al valor de la variable de bar. En Rust, las variables son inmutables por defecto. El siguiente ejemplo muestra cómo usar mut antes del nombre de la variable para hacer que una variable sea mutable:
let foo = 5; // immutable
let mut bar = 5; // mutable
Volvamos al programa de juego de adivinanzas. Ahora sabe que let mut guess introducirá una variable mutable llamada guess. En el otro lado del signo igual (=) está el valor al que está vinculado la conjetura, que es el resultado de llamar a String :: new, una función que devuelve una nueva instancia de una cadena. String es un tipo de cadena proporcionado por la biblioteca estándar que es un bit de texto codificado en UTF-8 que puede crecer.
La sintaxis :: indica que new es una función asociada del tipo String. Una función asociada se implementa en un tipo, en este caso String, en lugar de en una instancia particular de un String. Lo podríamos pensar como un método estático.
Esta nueva función crea una nueva cadena vacía.
Para resumir, let mut guess = String :: new (); ha creado una variable mutable que actualmente está vinculada a una nueva instancia vacía de una Cadena.
Recuerde que incluimos la funcionalidad de entrada / salida de la biblioteca estándar con use std :: io; en la primera línea del programa. Ahora llamaremos a la función stdin desde el módulo io:
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
La función stdin devuelve una instancia de std :: io :: Stdin, que es un tipo que representa un identificador de la entrada estándar para su terminal.
La siguiente parte del código, .read_line (& mut guess), llama al método read_line en el identificador de entrada estándar para obtener información del usuario. También estamos pasando un argumento a read_line: & mut guess.
El trabajo de read_line es tomar lo que el usuario escriba en la entrada estándar y colocarlo en una cadena, por lo que toma esa cadena como argumento. El argumento de cadena debe ser mutable para que el método pueda cambiar el contenido de la cadena agregando la entrada del usuario.
El & indica que este argumento es una referencia, lo que le brinda una manera de permitir que múltiples partes de su código accedan a un dato sin necesidad de copiar esos datos en la memoria varias veces. Las referencias son una característica compleja, y una de las principales ventajas de Rust es lo seguro y fácil que es usar referencias. No necesita conocer muchos de esos detalles para finalizar este programa. Por ahora, todo lo que necesita saber es que, como las variables, las referencias son inmutables por defecto. Por lo tanto, necesita escribir & mut guess en lugar de & guess para hacerlo mutable.
No hemos terminado con esta línea de código. Aunque lo que hemos discutido hasta ahora es una sola línea de texto, es solo la primera parte de la única línea lógica de código. La segunda parte es este método:
.expect("Failed to read line");
Cuando llama a un método con la sintaxis .foo(), a menudo es aconsejable introducir una nueva línea y otros espacios en blanco para ayudar a dividir las líneas largas. Podríamos haber escrito este código como:
io::stdin().read_line(&mut guess).expect("Failed to read line");
Sin embargo, una línea larga es difícil de leer, por lo que es mejor dividirla: dos líneas para dos llamadas a métodos.
read_line coloca lo que el usuario escribe en la cadena que lo estamos pasando, pero también devuelve un valor, en este caso, un io :: Result. Rust tiene varios tipos llamados Result en su biblioteca estándar: un Result genérico y versiones específicas para submódulos, como io :: Result.
Los tipos de resultados son enumeraciones, a menudo denominadas enums. Una enumeración es un tipo que puede tener un conjunto fijo de valores, y esos valores se denominan variantes de la enumeración.
Para Result, las variantes son Ok o Err. La variante Ok indica que la operación fue exitosa, y dentro de Ok está el valor generado con éxito. La variante Err significa que la operación falló, y Err contiene información sobre cómo o por qué falló la operación.
El propósito de estos tipos de resultados es codificar la información de manejo de errores. Los valores del tipo Resultado, como los valores de cualquier tipo, tienen métodos definidos en ellos. Una instancia de io :: Result tiene un método de espera al que puede llamar. Si esta instancia de io :: Result es un valor de Err, esperar hará que el programa se bloquee y muestre el mensaje que pasó como un argumento para esperar. Si el método read_line devuelve un Err, probablemente sea el resultado de un error proveniente del sistema operativo subyacente. Si esta instancia de io :: Result es un valor Ok, esperar tomará el valor de retorno que Ok tiene y le devolverá ese valor para que pueda usarlo. En este caso, ese valor es el número de bytes en lo que el usuario ingresó en la entrada estándar.
Si no llama a wait, el programa se compilará, pero recibirá una advertencia:
$ cargo build
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
warning: unused `std::result::Result` which must be used
--> src/main.rs:10:5
|
10 | io::stdin().read_line(&mut guess);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
Rust le advierte que no ha utilizado el valor Resultado devuelto por read_line, lo que indica que el programa no ha manejado un posible error.
La forma correcta de suprimir la advertencia es escribir realmente el manejo de errores, pero debido a que solo desea bloquear este programa cuando se produce un problema, puede usar expect.
Además de los corchetes de cierre, solo hay una línea más para discutir en el código agregado hasta ahora, que es el siguiente:
println!("You guessed: {}", guess);
Esta línea imprime la cadena en la que guardamos la entrada del usuario. El conjunto de llaves, {}, es un marcador de posición: piense en {} como pequeñas pinzas de cangrejo que mantienen un valor en su lugar. Puede imprimir más de un valor usando llaves: el primer conjunto de llaves contiene el primer valor que aparece después de la cadena de formato, el segundo conjunto contiene el segundo valor, y así sucesivamente. Impresión de múltiples valores en una llamada a println! se vería así:
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
Este código imprimiría x = 5 e y = 10.
Y listo!! puf escribi mucho...
No hemos terminado con esta línea de código. Aunque lo que hemos discutido hasta ahora es una sola línea de texto, es solo la primera parte de la única línea lógica de código. La segunda parte es este método:
.expect("Failed to read line");
Cuando llama a un método con la sintaxis .foo(), a menudo es aconsejable introducir una nueva línea y otros espacios en blanco para ayudar a dividir las líneas largas. Podríamos haber escrito este código como:
io::stdin().read_line(&mut guess).expect("Failed to read line");
Sin embargo, una línea larga es difícil de leer, por lo que es mejor dividirla: dos líneas para dos llamadas a métodos.
read_line coloca lo que el usuario escribe en la cadena que lo estamos pasando, pero también devuelve un valor, en este caso, un io :: Result. Rust tiene varios tipos llamados Result en su biblioteca estándar: un Result genérico y versiones específicas para submódulos, como io :: Result.
Los tipos de resultados son enumeraciones, a menudo denominadas enums. Una enumeración es un tipo que puede tener un conjunto fijo de valores, y esos valores se denominan variantes de la enumeración.
Para Result, las variantes son Ok o Err. La variante Ok indica que la operación fue exitosa, y dentro de Ok está el valor generado con éxito. La variante Err significa que la operación falló, y Err contiene información sobre cómo o por qué falló la operación.
El propósito de estos tipos de resultados es codificar la información de manejo de errores. Los valores del tipo Resultado, como los valores de cualquier tipo, tienen métodos definidos en ellos. Una instancia de io :: Result tiene un método de espera al que puede llamar. Si esta instancia de io :: Result es un valor de Err, esperar hará que el programa se bloquee y muestre el mensaje que pasó como un argumento para esperar. Si el método read_line devuelve un Err, probablemente sea el resultado de un error proveniente del sistema operativo subyacente. Si esta instancia de io :: Result es un valor Ok, esperar tomará el valor de retorno que Ok tiene y le devolverá ese valor para que pueda usarlo. En este caso, ese valor es el número de bytes en lo que el usuario ingresó en la entrada estándar.
Si no llama a wait, el programa se compilará, pero recibirá una advertencia:
$ cargo build
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
warning: unused `std::result::Result` which must be used
--> src/main.rs:10:5
|
10 | io::stdin().read_line(&mut guess);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
Rust le advierte que no ha utilizado el valor Resultado devuelto por read_line, lo que indica que el programa no ha manejado un posible error.
La forma correcta de suprimir la advertencia es escribir realmente el manejo de errores, pero debido a que solo desea bloquear este programa cuando se produce un problema, puede usar expect.
Además de los corchetes de cierre, solo hay una línea más para discutir en el código agregado hasta ahora, que es el siguiente:
println!("You guessed: {}", guess);
Esta línea imprime la cadena en la que guardamos la entrada del usuario. El conjunto de llaves, {}, es un marcador de posición: piense en {} como pequeñas pinzas de cangrejo que mantienen un valor en su lugar. Puede imprimir más de un valor usando llaves: el primer conjunto de llaves contiene el primer valor que aparece después de la cadena de formato, el segundo conjunto contiene el segundo valor, y así sucesivamente. Impresión de múltiples valores en una llamada a println! se vería así:
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
Este código imprimiría x = 5 e y = 10.
Y listo!! puf escribi mucho...
Java Code Geeks
Quiero compartir estos libros gratuitos de Java Code Geeks :
|
|
martes, 24 de diciembre de 2019
Cuartos pasos en GIT
En Git, y otros sistemas de control de versiones distribuidos, clonar es la operación standard. Para obtener archivos se crea un clon de un repositorio entero. En otras palabras, prácticamente se crea una copia idéntica del servidor central. Todo lo que se pueda hacer en el repositorio principal, también podrás hacerlo.
Nosotros podemos inicializar un repositorio en un servidor central y luego clonarlo en nuestro equipo:
$ git clone otra.computadora:/ruta/a/archivos
y luego de clonarlo podemos hacer commit o pull :
$ git commit -a
$ git pull otra.computadora:/ruta/a/archivos HEAD
va a traer (pull) el estado de los archivos desde la otra máquina hacia la que estás trabajando. Si hiciste cambios que generen conflictos en un archivo, Git te va a avisar y deberías hacer commit luego de resolverlos.
Muchas veces deseamos hacer un fork de un proyecto, porque queremos probar una tecnología o porque queremos hacer cambios grandes, sin estorbar nuestro día a día por lo que podemos hacer un fork del proyecto y luego mergearlo cuando queramos, Entonces en tu servidor:
$ git clone git://servidor.principal/ruta/a/archivos
Y luego clonamos dicho fork en cada uno de los cliente, si terminamos el cambio de tecnología podemos mergear con el repositorio principal.
Empezando con Rust, parte 3
Seguimos con Rust...
Ahora implementaremos un clásico problema de programación : un juego de adivinanzas. Así es como va a funcionar: el programa generará un número entero aleatorio entre 1 y 100. Luego le pedirá al jugador que ingrese una suposición. Después de ingresar una suposición, el programa indicará si la suposición es demasiado baja o demasiado alta. Si la suposición es correcta, el juego imprimirá un mensaje de felicitación y saldrá.
Creemos un nuevo proyecto usando Cargo, así:
$ cargo new guessing_game
$ cd guessing_game
El primer comando, cargo new, toma el nombre del proyecto (guesssing_game) como primer argumento. El segundo comando cambia al directorio del nuevo proyecto.
Mire el archivo generado Cargo.toml:
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies]
Por supuesto cambiamos la info que viene por defecto.
cargo new genera un programa "¡Hola, mundo!" algo así:
fn main() {
println!("Hello, world!");
}
Ahora compilemos este programa "¡Hola, mundo!" Y ejecútelo en el mismo paso con el comando de ejecución de cargo:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/debug/guessing_game`
Hello, world!
El comando de ejecución es útil cuando necesitamos ejecutar rápidamente en un proyecto.
Ya tenemos nuestro proyecto, ahora a seguir en otro post ...
Ahora implementaremos un clásico problema de programación : un juego de adivinanzas. Así es como va a funcionar: el programa generará un número entero aleatorio entre 1 y 100. Luego le pedirá al jugador que ingrese una suposición. Después de ingresar una suposición, el programa indicará si la suposición es demasiado baja o demasiado alta. Si la suposición es correcta, el juego imprimirá un mensaje de felicitación y saldrá.
Creemos un nuevo proyecto usando Cargo, así:
$ cargo new guessing_game
$ cd guessing_game
El primer comando, cargo new, toma el nombre del proyecto (guesssing_game) como primer argumento. El segundo comando cambia al directorio del nuevo proyecto.
Mire el archivo generado Cargo.toml:
[package]
name = "guessing_game"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies]
Por supuesto cambiamos la info que viene por defecto.
cargo new genera un programa "¡Hola, mundo!" algo así:
fn main() {
println!("Hello, world!");
}
Ahora compilemos este programa "¡Hola, mundo!" Y ejecútelo en el mismo paso con el comando de ejecución de cargo:
$ cargo run
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 1.50 secs
Running `target/debug/guessing_game`
Hello, world!
El comando de ejecución es útil cuando necesitamos ejecutar rápidamente en un proyecto.
Ya tenemos nuestro proyecto, ahora a seguir en otro post ...
domingo, 22 de diciembre de 2019
Terceros pasos en GIT.
Seguimos con GIT.
Cuando trabajamos de forma profesional debemos compartir nuestros cambios de forma tal de poder trabajar de forma colaborativa con nuestros compañeros, normalmente hacemos release cuando terminamos. Para hacer esto con Git, en el directorio donde guardamos nuestro código hacemos :
$ git init
$ git add .
$ git commit -m "Primer lanzamiento"
Entonces podemos decirle los otros desarrolladores que ejecuten:
$ git clone tu.maquina:/ruta/al/script
para descargar tu código. Esto asume que tienen acceso por ssh. Si no es así, podemos ejecutar git daemon y nuestros compañeros pueden usar:
$ git clone git://tu.maquina/ruta/al/script
De ahora en más, cada vez que necesitemos compartir código, escribimos :
$ git commit -a -m "Siguiente lanzamiento"
y los demás desarrolladores puede actualizar su versión yendo al directorio y ejecutando:
$ git pull
Averigua que cambios hiciste desde el último commit con:
$ git diff
O desde ayer:
$ git diff "@{yesterday}"
O entre una versión en particular y 2 versiones hacia atrás:
$ git diff SHA1_HASH "master~2"
En cada caso la salida es un patch (parche) que puede ser aplicado con git apply
Para ver cambios desde hace 2 semanas, se puede hacer:
$ git whatchanged --since="2 weeks ago"
Ojo ver esto se hace un tanto difícil, por lo que es una buena idea utilizar una software que nos deje ver los cambios de una forma más gráfica. Si te gusta la consola tig es una buena opción.
Cuando trabajamos de forma profesional debemos compartir nuestros cambios de forma tal de poder trabajar de forma colaborativa con nuestros compañeros, normalmente hacemos release cuando terminamos. Para hacer esto con Git, en el directorio donde guardamos nuestro código hacemos :
$ git init
$ git add .
$ git commit -m "Primer lanzamiento"
Entonces podemos decirle los otros desarrolladores que ejecuten:
$ git clone tu.maquina:/ruta/al/script
para descargar tu código. Esto asume que tienen acceso por ssh. Si no es así, podemos ejecutar git daemon y nuestros compañeros pueden usar:
$ git clone git://tu.maquina/ruta/al/script
De ahora en más, cada vez que necesitemos compartir código, escribimos :
$ git commit -a -m "Siguiente lanzamiento"
y los demás desarrolladores puede actualizar su versión yendo al directorio y ejecutando:
$ git pull
Averigua que cambios hiciste desde el último commit con:
$ git diff
O desde ayer:
$ git diff "@{yesterday}"
O entre una versión en particular y 2 versiones hacia atrás:
$ git diff SHA1_HASH "master~2"
En cada caso la salida es un patch (parche) que puede ser aplicado con git apply
Para ver cambios desde hace 2 semanas, se puede hacer:
$ git whatchanged --since="2 weeks ago"
Ojo ver esto se hace un tanto difícil, por lo que es una buena idea utilizar una software que nos deje ver los cambios de una forma más gráfica. Si te gusta la consola tig es una buena opción.
jueves, 19 de diciembre de 2019
Aprende los fundamentos de la inteligencia artificial para tu empresa
Microsoft nos regala un e-book el cual nos invita a leerlo de la siguiente manera:
Prepárate para unirte al 85 % de las empresas que se prevé que usarán inteligencia artificial (IA) en 2020.
Lee el e-book Conceptos básicos de IA para empresas para entender cómo aplicar la inteligencia artificial para generar nuevo valor comercial y reinventar tu organización. Comienza con algunos aspectos básicos, como una introducción a la inteligencia artificial e indicadores clave para implementar tus primeras tecnologías inteligentes. Los temas incluyen el uso de IA para:
- Transformar tus procesos empresariales.
- Interactuar con los clientes y empoderarlos.
- Optimizar tus operaciones.
Dejo link: https://info.microsoft.com/ww-landing-aI-basics-for-business-eBook.html?lcid=es-es&WT.mc_ID=NEWS_EPG_Spain_DICIEMBRE&wt.mc_id=AID2392225_EML_6224385
Libros de Java Code Geeks
|
martes, 17 de diciembre de 2019
Segundos pasos en GIT
Sigamos revisando algunos comandos de GIT. Si necesitamos ir a un commit anterior debemos saber su id, el id es un hash del commit, por lo tanto podemos listar todos los commit recientes con :
$ git log
Luego podemos ir hasta el commit determinado con :
$ git reset --hard SHA1_HASH
Ojo esto va a borrar a los commit más nuevos. Pero si queremos saltar a un estado anterior temporalmente usamos :
$ git checkout SHA1_HASH
Esto te lleva atrás en el tiempo, sin tocar los commits más nuevos. Sin embargo,
como en los viajes en el tiempo de las películas de ciencia ficción, estarás en una
realidad alternativa, porque tus acciones fueron diferentes a las de la primera
vez. Esta realidad alternativa se llama branch (rama). Por ahora solo recordemos que :
$ git checkout master
te llevará al presente. También, para que Git no se queje, siempre debemos hacer un commit o resetear los cambios antes de ejecutar checkout.
Puedes elegir commits específicos para deshacer.
$ git commit -a
$ git revert SHA1_HASH
va a deshacer solo el commit con el hash dado. Ejecutar git log revela que el
revert es registrado como un nuevo commit.
Hasta ahora solo hemos trabajado con nuestro repositorio local que es un poco raro, normalmente tambien tenemos un repositorio remoto donde poder compartir código con los demás desarrolladores. Si queremos obtener una copia de un repositorio remoto debemos clonar este repositorio:
$ git clone git://servidor/ruta/a/los/archivos
luego de clonarlo podemos obtener su última versión con pull :
$ git pull
$ git log
Luego podemos ir hasta el commit determinado con :
$ git reset --hard SHA1_HASH
Ojo esto va a borrar a los commit más nuevos. Pero si queremos saltar a un estado anterior temporalmente usamos :
$ git checkout SHA1_HASH
Esto te lleva atrás en el tiempo, sin tocar los commits más nuevos. Sin embargo,
como en los viajes en el tiempo de las películas de ciencia ficción, estarás en una
realidad alternativa, porque tus acciones fueron diferentes a las de la primera
vez. Esta realidad alternativa se llama branch (rama). Por ahora solo recordemos que :
$ git checkout master
te llevará al presente. También, para que Git no se queje, siempre debemos hacer un commit o resetear los cambios antes de ejecutar checkout.
Puedes elegir commits específicos para deshacer.
$ git commit -a
$ git revert SHA1_HASH
va a deshacer solo el commit con el hash dado. Ejecutar git log revela que el
revert es registrado como un nuevo commit.
Hasta ahora solo hemos trabajado con nuestro repositorio local que es un poco raro, normalmente tambien tenemos un repositorio remoto donde poder compartir código con los demás desarrolladores. Si queremos obtener una copia de un repositorio remoto debemos clonar este repositorio:
$ git clone git://servidor/ruta/a/los/archivos
luego de clonarlo podemos obtener su última versión con pull :
$ git pull
lunes, 16 de diciembre de 2019
Primeros pasos en GIT
Antes de empezar a leer, espero que estés familiarizado con conceptos como control de versiones, conflictos, merge, branch, etc… Porque no tengo ganas de explicarlos :(
Antes, cada proyecto usaba un control de versiones centralizado un ejemplo es SVN. Un servidor en algún lado contenía todo el código. Nadie más los tenía. Cada programador tenía una versión y una parte del código. Cada tanto debíamos actualizar del servidor central, obteníamos la última versión del servidor principal, programábamos un rato y volvía a subir al servidor para que todos los demás
pudieran usarlo.
Cual es el problema de este esquema? Que si 2 desarrolladores quieren comparar 2 soluciones para un mismo problema, no lo pueden hacer sin subir al repositorio central y eso esta mal porque no saben cual solución debe ser la mejor para ser compartida. GIT soluciona este problema utilizando un modelo distribuido, en el cual cada cliente tiene un repositorio y existe uno o varios repositorios remotos. De esta manera podemos subir nuestros cambios al repositorio local, comparar las soluciones y luego subirlas al repositorio compartido. A la vez el repositorio local contiene todo el historial del código, de esta manera es innecesario comunicación con el repositorio remoto para retornar a una versión antigua.
Al empezar con GIT podemos tomar un repositorio remoto o obtar por utilizar nuestro repositorio local. Veamos como podemos tener un proyecto y mantenerlo en el repositorio local:
Inicio el repositorio con init
$ git init
Agrego todos los archivos de esa carpeta
$ git add .
Hago commit es decir subo los archivos al repositorio
$ git commit -m "Mi primer commit"
Si deseamos volver a la version del repositorio:
$ git reset --hard
Si añades nuevos archivos o subdirectorios, deberás decirle a Git:
$ git add ARCHIVOSNUEVOS…
De manera similar, si quieres que Git se olvide de determinados archivos, porque (por ejemplo) los borraste:
$ git rm ARCHIVOSVIEJOS…
Renombrar un archivo es lo mismo que eliminar el nombre anterior y agregar el
nuevo. También puedes usar git mv que tiene la misma sintaxis que el comando
mv de linux. Por ejemplo:
$ git mv ARCHIVOVIEJO ARCHIVONUEVO
Y por este post estuvimos bien...
viernes, 13 de diciembre de 2019
Introducción a Jakarta NoSQL
EE4J no se detiene y ha aprobado el proyecto Jakarta NoSQL es una especificación en Jakarta EE para ayudar a los desarrolladores a crear aplicaciones de nivel empresarial utilizando tecnologías Java y NoSQL. JNoSQL es la implementación de referencia de Jakarta NoSQL, que proporciona un conjunto de APIs y una implementación estándar para una serie de bases de datos NoSQL, como Cassandra, MongoDB, Neo4J, CouchDB y OrientDB, entre otras.
Jakarta NoSQL consiste en una capa de comunicación (Diana), que extrae un conjunto de APIs diseñadas para definir la comunicación con las bases de datos NoSQL. Contiene cuatro módulos de acuerdo con cada tipo de base de datos NoSQL: clave-valor, familia de columnas, documento y grafo; y una capa de mapeo (Artemis), que proporciona una serie de APIs para ayudar a los desarrolladores a integrar aplicaciones Java con bases de datos NoSQL. La capa de mapeo se basa en anotaciones y utiliza tecnologías como CDI y Bean Validation, lo que facilita el uso de los desarrolladores. Es posible comparar la capa de mapeo con JPA / Hibernate en el mundo tradicional RDBMS.
La definición de una entidad es relativamente similar a JPA. Básicamente usa @Entity, @Id, @Column y así sucesivamente:
@Entity
public class Person {
@Id
private long id;
@Column
private String name;
@Column
private List phones;
}
Los repositorios se parecen a los repositorios de Spring Data, donde se extiende un Repositorio <T, ID>:
public interface PersonRepository extends Repository {
List<Person> findByName(String name);
Stream<Person> findByPhones(String phone);
}
Sin embargo, a partir de este momento, las cosas cambian, ya que las dependencias de Maven cambian de acuerdo con el tipo de base de datos NoSQL que se usa, así como la configuración y cómo inyectamos el repositorio en nuestros servicios.
Veamos 2 ejemplos, uno utilizando una base orientada a columna y otra documental. Importamos librerías :
<dependency>
<groupId>org.jnosql.artemis</groupId>
<artifactId>artemis-column</artifactId>
<version>0.0.9</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>cassandra-driver</artifactId>
<version>0.0.9</version>
</dependency>
Veamos el manager de nuestra base orientada a columna :
@ApplicationScoped
public class ColumnFamilyManagerProducer {
private static final String KEY_SPACE = "developers";
private ColumnConfiguration<> cassandraConfiguration;
private ColumnFamilyManagerFactory managerFactory;
@PostConstruct
public void init() {
cassandraConfiguration = new CassandraConfiguration();
managerFactory = cassandraConfiguration.get();
}
@Produces
public ColumnFamilyManager getManagerCassandra() {
return managerFactory.get(KEY_SPACE);
}
}
Y finalmente, un ejemplo de cómo ejecutar algunas inserciones / consultas:
Person person = Person.builder()
.withPhones(Arrays.asList("234", "432"))
.withName("Name")
.withId(id)
.build();
//using ColumnTemplate
ColumnTemplate columnTemplate = container.select(CassandraTemplate.class).get();
Person saved = columnTemplate.insert(PERSON);
System.out.println("Person saved" + saved);
ColumnQuery query = select().from("Person").where(eq(Column.of("id", 1L))).build();
Optional<Person> person = columnTemplate.singleResult(query);
System.out.println("Entity found: " + person);
//using PersonRepository
PersonRepository repository = container.select(PersonRepository.class).select(ofColumn()).get();
Person saved = repository.save(PERSON);
System.out.println("Person saved" + saved);
Optional<Person> person = repository.findById(1L);
System.out.println("Entity found: " + person);
Veamos un ejemplo con una base documental, primero las dependencias:
<dependency>
<groupId>org.jnosql.artemis</groupId>
<artifactId>artemis-document</artifactId>
<version>0.0.9</version>
</dependency>
<dependency>
<groupId>org.jnosql.diana</groupId>
<artifactId>mongodb-driver</artifactId>
<version>0.0.9</version>
</dependency>
Luego el manager :
@ApplicationScoped
public class DocumentCollectionManagerProducer {
private static final String COLLECTION = "developers";
private DocumentConfiguration configuration;
private DocumentCollectionManagerFactory managerFactory;
@PostConstruct
public void init() {
configuration = new MongoDBDocumentConfiguration();
Map<String, Object> settings = Collections.singletonMap("mongodb-server-host-1", "localhost:27017");
managerFactory = configuration.get(Settings.of(settings));
}
@Produces
public DocumentCollectionManager getManager() {
return managerFactory.get(COLLECTION);
}
}
y usamos el manager :
Person person = Person.builder()
.withPhones(Arrays.asList("234", "432"))
.withName("Name")
.withId(id)
.build();
//using DocumentTemplate
DocumentTemplate documentTemplate = container.select(DocumentTemplate.class).get();
Person saved = documentTemplate.insert(person);
System.out.println("Person saved" + saved);
DocumentQuery query = select().from("Person")
.where(eq(Document.of("_id", id))).build();
Optional<Person> personOptional = documentTemplate.singleResult(query);
System.out.println("Entity found: " + personOptional);
//using PersonRepository
PersonRepository repository = container.select(PersonRepository.class)
.select(ofDocument()).get();
repository.save(person);
List<Person> people = repository.findByName("Name");
System.out.println("Entity found: " + people);
repository.findByPhones("234").forEach(System.out::println);
Y listo!
Ustedes pensaran que feo tener diferentes modos de guardar y recuperar datos de nuestros almacenes de datos sql pero tengamos en cuenta que es el único camino para aprovechar al máximo sus particularidades y normalmente elegimos estas bases por sus particularidades.
Dejo link: https://github.com/eclipse-ee4j/nosql
Un IDE online para programar en javascript
Tiene muchas funcionalidades, la que más me gusta es que si necesitas alguna librería podes importarla ahí mismo...
Sin más ...
Dejo link :
https://codesandbox.io/
lunes, 9 de diciembre de 2019
Seguimos con Docker
Creo que recuerdan los post anteriores...
El ciclo de vida de un contenedor esta detallado en dicha ilustración :
La vida de un contenedor comienza en el estado creado o created, esta creado pero no esta funcionando, por lo que el siguiente estado es running y pasa a este estado con el comando run, donde el contenedor comienza a funcionar. Desde este estado puede pasar a diferentes estados.
Killed es cuando matamos el contenedor, normalmente se utiliza cuando hay un problema o el contenedor no contesta y el contenedor pasa a killed
Paused, nuestro contenedor es pausado cuando estamos haciendo una tarea y no podemos continuar en ese momento pero luego queremos seguir. Es como hibernar la pc.
Stopped (con el comando stop) es cuando paramos la imagen, la apagamos y luego podemos volver a running con el comando run.
El ciclo de vida de un contenedor esta detallado en dicha ilustración :
La vida de un contenedor comienza en el estado creado o created, esta creado pero no esta funcionando, por lo que el siguiente estado es running y pasa a este estado con el comando run, donde el contenedor comienza a funcionar. Desde este estado puede pasar a diferentes estados.
Killed es cuando matamos el contenedor, normalmente se utiliza cuando hay un problema o el contenedor no contesta y el contenedor pasa a killed
Paused, nuestro contenedor es pausado cuando estamos haciendo una tarea y no podemos continuar en ese momento pero luego queremos seguir. Es como hibernar la pc.
Stopped (con el comando stop) es cuando paramos la imagen, la apagamos y luego podemos volver a running con el comando run.
Suscribirse a:
Entradas (Atom)