En este post voy a crear un pequeño proyecto en Spark + Scala (Vamos a usar Spark 2.1 y Scala 2.11.8), al cual iré añadiendo nuevas funcionalidades más adelante. Para comenzar voy a crear un fichero pom.xml de Maven que compilé el proyecto en Scala.
Antes de empezar vamos a necesitar tener instalado la versión 3.3 de Maven para poder generar el fichero pom.xml mediante: mvn archetype:generate. Está instrucción descarga una serie de ficheros binarios que son necesarios para la generación del pom.xml. Cuando se finalicen las descargas de los binarios, nos pedirá que introduzcamos el plugin de Maven que vamos a usar. Escribiremos “Scala” para que filtré por aquellos plugins que usan scala y de una lista más pequeña buscaremos el plugin “net.alchim31.maven:scala-archetype-simple“. Para finalizar introduciremos el número con el que venga asociado. Utilizaremos la versión 1.6.
Por último nos solicitará la siguiente información, y ya tendremos el proyecto de Maven creado.
- groupId: Introduciremos el nombre el dominio, “info.antoniomartin.spark”.
- artifactId: El nombre del proyecto, “app”.
- versión: La versión que queramos, en este caso 0.0.1-SNAPSHOT.
- package: Por defecto es el groupId pero podemos cambiarlo.
El proyecto generado seguirá el Arquetipo típico de Maven. Siendo breves, dentro de la carpeta del proyecto, vamos a encontrar dos carpetas: src y target (target tan solo cuando se haya generado la app). Dentro de la carpeta src (Source) veremos otras dos, main y test y a su vez, dentro de estas, una carpeta para scala y otra para java. Dentro de estas últimas veremos la estructura de carpetas introducida en el groupId. La carpeta Target incluye todos los ficheros generados y construidos como .class o .jar. Para más información puedes consultar la página Maven.
Ejemplo de la estructura:
app src main scala com/my-package/… *.scala java com/my-package/… *.java test scala com/my-package/… *.scala java com/my-package/… *.java target pom.xml
Dentro de la carpeta app, se habrá creado el fichero gitignore, que tendremos que mover a la carpeta anterior mediante:
mv .gitignore ../
Una vez generado el pom.xml vamos a modificarlo para poder utilizarlo tanto para código escrito en Java o en Scala. Si venís de Java, como yo, os resultará mucho más fácil esta forma de usar maven. Para ello buscamos en el fichero pom.xml, el lugar donde está indicado el plugin que estamos usando “net.alchim31.maven” y sustituimos los executions que trae por defecto por los siguiente:
<executions> <execution> <id>scala-compile-first</id> <phase>process-resources</phase> <goals> <goal>add-source</goal> <goal>compile</goal> </goals> </execution> <execution> <id>scala-test-compile</id> <phase>process-test-resources</phase> <goals> <goal>testCompile</goal> </goals> </execution> </executions>
Antes de hacer nada más, vamos a borrar las dependencias de specs2 y el código relacionado. Primero borramos el fichero test/scala/samples/specs.scala y del fichero pom.xml, borramos lo siguiente:
<dependency> <groupId>org.specs2</groupId> <artifactId>specs2-core_${scala.compat.version}</artifactId> <version>2.4.16</version> <scope>test</scope> </dependency>
Ahora podemos ejecutar los comandos de maven cómodamente:
mvn clean //Borra todo el código compilado mvn install //Compila el código mvn clean install //Para borrar y compilar el código y ejecutar los tests mvn clean install -DskipTets //Borra y compila el código pero no ejecuta los test
Una vez realizado estos pasos vamos a copiar el siguiente código de ejemplo que viene en la página de Spark, para ejecutar un pequeño ejemplo de código de Spark 2.1, para ello, yo voy a modificar la variable logFile y voy a poner la ruta de un fichero README.md que tengo en mi pc. En mi caso: “/usr/share/doc/containerd/README.md”. Ahora copio y pego el código en mi fichero App.scala
package info.antoniomartin.spark /* App.scala */ import org.apache.spark.SparkContext import org.apache.spark.SparkContext._ import org.apache.spark.SparkConf object App { def main(args: Array[String]) { val logFile = "/usr/share/doc/containerd/README.md" // Should be some file on your system val conf = new SparkConf().setAppName("Simple Application") val sc = new SparkContext(conf) val logData = sc.textFile(logFile, 2).cache() val numAs = logData.filter(line => line.contains("a")).count() val numBs = logData.filter(line => line.contains("b")).count() println(s"Lines with a: $numAs, Lines with b: $numBs") sc.stop() } }
Ahora si volvemos a intentar compilar, nos indicará que no encuentra ciertas librerías, eso es porque hay que añadir la dependencia con Spark 2.10 y woala!
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core_2.11 --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>2.1.0</version> </dependency>
Todo este código lo puedes encontrar en: https://github.com/antoniomeh/Spark
Bibliografía
https://docs.scala-lang.org/tutorials/scala-with-maven.html
https://davidb.github.io/scala-maven-plugin/index.html
http://davidb.github.io/scala-maven-plugin/example_java.html
https://spark.apache.org/docs/2.1.0/quick-start.html