Spark Scala con Maven en IntelliJ

Este es un post que la verdad no había tenido en mente crear pero últimamente se me ha convertido en una necesidad y la verdad he disfrutado hacer y es que en estos ya casi 5 años involucrado en temas relacionados con Big Data y la nube la verdad es que he podido notar como construir un proyecto Spark desde cero se convierte en algo fácil pero netamente basado en copiar y pegar de proyectos anteriores, pero … y qué sucede cuando no hay un proyecto anterior jejeje, pero no es el único caso y qué sucede con aquellos que están aprendiendo, es cuestión de indagar por Internet y encuentras 30 formas distintas de armar un proyecto desde cero de Spark con Scala con Maven y en un IDE en este caso IntelliJ, pero cual es la idónea, cual es la que verdaderamente funciona.

Pues he decidido crear un esqueleto de proyecto (el cual espero poder ir evolucionando y mejorarlo) que seguramente no es la mejor pero desde mi humilde punto de vista es funcional.

Configurar el IDE

Lo primero antes que nada es instalar el jsdk (1.8 como mínimo), luego en la instalación o inmediatamente después es asegurarnos de contar con los plugins de Maven y Scala, para ello en la ventana de inicio vamos a los plugins.

Buscamos el plugin de Scala para verificar que este instalado si no lo está lo instalamos y luego en la misma ventana en la parte superior junto a Marketplace hacemos clic en installed y verificamos que el plugin de maven por defecto este habilitado.

Creamos el proyecto

Seleccionamos la opción de crear un nuevo proyecto.

Ventana de inicio de IntelliJ

Acto seguido seleccionamos la opción de proyecto maven y marcamos la opción de Create from archetype. Seleccionamos el archetype net.alchim31.maven:scala-archetype-simple y pulsamos el botón «Next». Si el archetype no existe pulsamos el botón de Añadir Archetype (Add Archetype) cumplimentamos la información con los siguientes datos:
GroupId: net.alchim31.maven
ArtifactId: scala-archetype-simple
Version: 1.7

Una vez añadido lo seleccionamos y como habíamos indicado antes pulsamos el botón «Next».

Indicamos el archetype en caso de no estar presente en la lista
Lista de archetypes para crear el proyecto

Inmediatamente después le daremos nombre a nuestro proyecto y si queremos ser más específicos indicamos el GroupId, ArtifactId y versión de nuestro proyecto (OJO esto último es opcional), pulsamos «Next» y por último en la ventana resumen pulsamos «Finish».

Configuración de nuestro artifact

Lo primero que deberemos hacer para que nos facilite la tarea será habilitar la autoimportación de las dependencias maven como señalamos en la imagen.

Habilitamos la autoimportación de dependencias

El construir el proyecto a partir de un archetype (arquetipo) maven consiste en armar el esqueleto de un proyecto a partir de una plantilla definiendo una estructura minima por defecto, por lo cual veremos un fichero pom.xml (gestión de dependencias maven) con algunas dependencias y una estructura de carpetas para el código fuente y pruebas unitarias, con ficheros incluidos.

Estructura del proyecto reciéntame creado

Aprovechamos de dar un vistazo a la clase App y a las pruebas unitarias que por defecto nos añade al proyecto e incluso podemos compilar el proyecto para contrastar que todo está de maravilla y para ello solamente necesitamos hacer clic en la pestaña maven ubicado en la parte derecha, donde aparece el nombre de nuestro proyecto desplegar lifecycle y hacer doble clic en compile y esto iniciará el proceso de compilación terminando exitosamente.

Añadimos dependencias

Ya estamos llegando al final, ahora lo que haremos será añadir al fichero pom.xml las dependencias spark que utilizaremos para este ejemplo. Empezaremos por editar las propiedades quedando estas así:

Añadimos las dependencias de spark al conjunto de dependencias existentes

Por último modificaremos nuestra clase App quedando esta así:

Para de nuevo volver a compilar el proyecto, que deberá culminar exitosamente.

Ejecución

La forma que indicaremos para la ejecución de los jobs desde IntelliJ no es la mejor pero es una forma sencilla y funcional para probar cosas y sobre todo para quien comienza a hacer tests sin necesidad de empaquetar y crear un jar y desplegarlo en una máquina virtual o en un cluster. ¿Cuál sería entonces la mejor forma? A mi modo de ver las cosas la mejor forma sería mediante prueba unitarias y de integración donde podamos probar todo el job de inicio a fin y para explicarles como ya tengo en mente preparar otro post paso a paso indicando como hacerlo y las herramientas para lograrlo. Continuando con la configuración de la ejecución, si sencillamente con botón derecho del ratón hacemos clic en Run ‘App’ nos arrojará el error.

Exception in thread «main» java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession$
at com.josedeveloper.App$.main(App.scala:13)
at com.josedeveloper.App.main(App.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.spark.sql.SparkSession$
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
… 2 more

Error ejecutando la clase App

El error se debe a que no encuentra las clases con las que fue compilado previamente y eso se debe a que las dependencias de spark las hemos añadido con el alcance «provided».
¿Por qué provided? Debido a que en un entorno empresarial esas dependencias no debemos agregarlas ya que las provee la infraestructura Big Data de la empresa.

Entonces para solventar el error sencillamente debemos ir al menu «Run» y hacemos clic en «Edit Configurations» y allí marcamos la opción de incluir dependencias provided (Include dependencies with «Provided» scope).

Marcamos la opción que incluya las dependencias con alcance «Provided»

Hecho eso volvemos a ejecutar la clase App y veremos como si se logra ejecutar la aplicación. Sin más espero que les haya servido de ayuda y les comento que mi próximo paso será crear un archetype (arquetipo) y a su vez explicarles como hacerlo para que cada quien pueda construir uno acorde con las necesidades de su organización y así dotamos de más profesionalidad y agilidad nuestro trabajo y evitamos el copiar+pegar donde en ocasiones terminamos añadiendo mas dependencias y plugins innecesarios así como también arrastrando problemas y errores (de haberlos).

Aquí les dejo el video

Repo GitHub

Mi receta para aprobar la certificación CCA Spark and Hadoop Developer

Hola de nuevo mi gente, como ya es costumbre tenía tiempo sin escribir, de hecho la última vez fue para anunciarles que había aprobado la certificación de solution architect de AWS y comentarles mi receta para aprobarla, bueno en esta ocasión les traigo mi receta para aprobar la certificación CCA Spark and Hadoop Developer (CCA175) de Cloudera. Bueno primero comentarles que esta certificación me resulto fascinante, por distintas cosas, la primera fue que tenía un completo desconocimiento sobre la forma como sería el examen, la segunda es que es totalmente práctica y el contenido dependiendo de como se mire puede ser amplio o no, de acuerdo a cuanto se desee profundizar.

Algunos aspectos del examen: tiene una duración de 2 horas, se aprueba con el 70% y pueden ser entre 8 y 12 preguntas (en mi caso fueron 9). El examen se lleva a cabo de forma online a través de un máquina virtual a la que accederás desde el navegador (chrome), de tu ordenador y será estrictamente necesario tener una webcam mediante la cual un vigilante (proctor) estará atento a que no hagas trampa, también tendrás a disposición una serie de enlaces de documentación referente a las herramientas que puedes utilizar en el examen, como pueden ser la documentación oficial de sqoop, spark, hive, cloudera, por mencionar algunas. En el examen no te veras obligado a utilizar una herramienta en especial, es decir, lo que importa es el resultado final, si este lo consigues con Pig, Hive, Spark, impala, Flume, pues perfecto, lo que esta claro es que hay herramientas que terminan siendo más adecuadas que otras dependiendo del caso.

Dada mi experiencia les sugiero estudiar los siguientes tópicos:

  • Importar y exportar usando sqoop y en ambos casos considerar el uso y cambio de delimitadores de campos así como de lineas. En el caso particular de la importación tener en cuenta compresión (por ejemplo Gzip) y formatos de archivo (texto, avro, parquet), a su vez conocer como y cuando utilizar los argumentos, -m, -split-by, -where, -query, -columns, -warehouse-dir, -target-dir, por mencionar algunos.
  • Crear una tabla en Hive cuya fuente de datos sean ficheros de texto, o que los datos estén serializados en Parquet, ORC o AVRO (tener en cuenta evolución del schema) y que a su vez estén comprimidos. CTAS (Create Table as Select) y exportar desde hive un fichero tanto a HDFS como al FileSystem producto de una consulta.
  • Haciendo uso de Spark hacer Lectura de datos en distintos formatos (texto, json, orc, parquet o avro) e incluso comprimidos y a partir de estos llevar a cabo una transformación de los datos y exportar el resultado a uno de los posibles formatos mencionados anteriormente.
  • La Máquina virtual trae consigo eclipse y sublime, les sugiero hacer scripts en sublime y guardarlos para poder volver a ellos en caso de ser necesario. En el caso de spark al yo tener más experiencia con scala lo que hice fue lanzar los scripts con la spark-shell con el siguiente comando spark-shell -i script.scala  o sino desde la consola usando :load script.scala.
  • En el caso de spark al ser la versión 1.6 preferí trabajar con dataframes a tener que hacer la operativa con RDDs.
  • Hacer muchos ejercicios, prácticos. En mi caso creé un repositorio en Github donde hice unos cuantos ejercicios, unos inventados por mí y otros del sitio web itversity.
  • Es importante hacer una buena gestión del tiempo, sugiero tomar un par de minutos para leer las preguntas e ir a por las más sencillas al comenzar y si en algún momento te bloqueas, pues pasar a la siguiente de inmediato, de igual forma mientras se esté ejecutando una operación (puede que tarde 1 min + o -) aprovechar para al menos leer el enunciado siguiente.
  • Muy importante mucho cuidado con los datos fuentes y de ser posible respaldarlos.
  • La consola de la máquina virtual tiene un tamaño de fuente algo pequeño por lo que no es mala idea hacer un zoom in.

Yo he de confesar que de las 9 preguntas que me salieron solo respondí 8, porque no me dio tiempo he allí la razón por la que hago hincapié en la buena gestión del tiempo. El examen no resulta difícil si has estudiado, pero al contar con solo 2 horas es necesario haber practicado antes para no perder mucho tiempo buscando en la documentación.

Por último desearles mucha suerte y reiterar mi fascinación con esta certificación, he aprendido muchísimo y el examen en sí me genero una sensación de satisfacción increíble al conseguir aprobarla, sobre todo esa buena vibra de poner en practica todo aquello practicado.

 

Estadística simple con Spark V2

Sigo con mi pruebas con lo nuevo (y no tan nuevo de Spark 2), hoy comparto con ustedes una versión 2 de mi anterior post Estadística simple con Spark, pero en esta ocasión realizado con Spark 2.

¿Que tiene de nuevo esta versión?

Primeramente utiliza el módulo spark-csv lo cual nos hace más simple la carga del fichero en un Dataset. Segundo, que no manipulamos en ningún instante RDD alguno, sino que por el contrario estamos trabajando con DataFrames representados mediante la clase Dataset. Entre las cosas nuevas que contempla esta versión hecha en Spark 2 es que mientras antes al realizar un groupBy sobre un DataFrame esto nos devolvía un GroupedData ahora nos devuelve un RelationalGroupedData, esto debido a un cambio de nombre que se le ha dado a partir de esta nueva versión de Spark.

Esta nueva versión realizada con SparkSQL con Datasets tiene varias ventajas, la primera es simplicidad, es mucho mas simple, mas fácil de entender el código además de mas corto, de hecho con menos lineas obtuve más información que con la versión elaborada con RDD’s, es decir, es mas versátil. Por otro lado aunque hay que tener algo de nociones de conjuntos lo interesante es que esta versión esta libre de código SQL.

Sin más dilación he aquí el código y el enlace al proyecto en Github.

Para que comparen los resultados obtenidos aquí con respecto a la entrada anterior dejo un pantallazo de lo obtenido al ejecutarlo en mi local.

promedios por distrito

promedios por distrito

Otras agregaciones por distrito

Otras agregaciones por distrito

Total personas por distrito

Total personas por distrito

Enviar correo de GMAIL con Java

Este es otro post que quería compartir desde hace tiempo, entre otras cosas por su sencillez ya que en un proyecto anterior una solución de este tipo nos ayudó a resolver un problema puntual. Les pongo en contexto, debíamos desde nuestra empresa enviar una información que recabábamos diariamente, como es de suponer estábamos alejados fisicamente y en otra red y como no podía ser de otra forma no había permisos para por FTP o SSH hacer llegar la información, es por ello que dado las exigencias y con el poco tiempo que contábamos se nos ocurrió la idea «¿y si enviamos la información por email?»  y así hicimos, construimos un pequeño programa Java el cual se ejecutaba periódicamente para enviar unos ficheros adjuntos que sacábamos diariamente.

Primero que nada es necesario que desde la cuenta de GMAIL habilitemos el acceso de aplicaciones menos seguras. Para ello es necesario que ingresemos a nuestra cuenta de GMAIL y una vez dentro vayamos a la parte superior derecha donde este el icono de nuestra cuenta, hacemos clic en el icono y posteriormente al botón «Mi cuenta». Allí veremos la siguiente imagen

mi cuenta de GMAIL

mi cuenta de GMAIL

Como vemos en la imagen de arriba (resaltado en rojo), debemos hacer clic en el apartado de «Inicio de sesión y seguridad». Y allí nos desplazamos hasta la parte inferior y habilitamos/activamos la opción «Permitir el acceso de aplicaciones menos seguras», como en la imagen de abajo.

habilitar acceso de aplicaciones menos seguras

habilitar acceso de aplicaciones menos seguras

Hecho esto, vamos al programa, el cual hace uso de Java Mail. El programa es bastante sencillo consta de un fichero de configuración del siguiente tipo:

gmail.account: La cuenta de GMAIL desde la cual enviaremos el correo electrónico.

gmail.password: El password de la cuenta de GMAIL desde la cual enviaremos el correo electrónico.

emaildestinations: Lista de direcciones de correo electrónico separadas por punto y coma («;») a donde será enviado el correo.

attachmentfiles: Lista de rutas donde están ubicados los ficheros a adjuntar separados por punto y coma («;»).

A continuación el programa Java encargado del envío del correo electrónico.

El ejemplo es bastante sencillo, pero nos muestra como indicar el asunto del email, el texto del mensaje así como adjuntar ficheros. Espero que les pueda ser de utilidad. Aquí el enlace al proyecto en Github.

Primeros pasos con Apache Spark 2

Hace pocos días salió la esperada versión 2 de Apache Spark y como algunos de ustedes saben es un framework que ahora mismo atrae mucho mi atención y como no pudo ser de otra forma hice un pequeño proyecto donde quiero ir colocando ejemplos sencillos de Spark con las nuevas (y no tan nuevas) cosas de Spark.

Para empezar comentarles que yo todavía no he utilizado sbt sino por el contrario uso maven como herramienta de construcción de proyectos. He aquí los primeros cambios necesarios para trabajar con spark 2, las dependencias correspondientes a la versión (indicadas en el pom.xml).

Entre los nuevos cambios de spark está que el punto de entrada para los programas spark ya no serán el hiveContext o sqlContext sino que han sido subsumidas en una clase llamada SparkSession. Las clases HiveContext y SQLContext se han mantenido para proporcionar retrocompatibilidad. Ejemplo

Con el SparkSession haremos lo mismo que hacíamos con sqlContext por ejemplo obtener un Dataset

O por el contrario obtener un DataFrame

Otro punto importante ha sido la unificación de las clases Dataset y DataFrame (para Java y Scala) a partir de la versión 2.¿Qué significa esto? pues sencillamente que ahora solo existirá la clase Dataset, pero proporcionará la misma funcionalidad que nos daba la clase DataFrame, de hecho basta con comparar la API en la versión 1.6.2 y 2.0.0 y ver como los métodos de la clase DataFrame están ahora incluidos en la clase Dataset.

Dataset y Dataframe en Spark 2

Dataset y Dataframe en Spark 2

Aquellos interesados en leer más acerca de Dataset y Dataframe  visitar este link

Estos no son los únicos cambios en Spark, de hechos son muchos más, que se corresponden a optimizaciones a nivel de compilación y ejecución así como también a un nuevo parseador SQL, para leer mas acerca de lo nuevo en Spark 2 clic aquí.

Aqui les dejo en enlace al proyecto donde ire añadiendo clases y seguiré probando mas cosas nuevas de Spark.