I am new in scala/Spark development. I have created a simple streaming application from Kafka topic using sbt and scala. I have the following code
build.sbt
name := "kafka-streaming"
version := "1.0"
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
assemblyMergeStrategy in assembly := {
case PathList("org", "apache", "spark", "unused", "UnusedStubClass.class") => MergeStrategy.first
case PathList(pl # _*) if pl.contains("log4j.properties") => MergeStrategy.concat
case PathList("META-INF", "io.netty.versions.properties") => MergeStrategy.last
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
scalaVersion := "2.11.8"
resolvers += "jitpack" at "https://jitpack.io"
// still want to be able to run in sbt
// https://github.com/sbt/sbt-assembly#-provided-configuration
run in Compile <<= Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run))
fork in run := true
javaOptions in run ++= Seq(
"-Dlog4j.debug=true",
"-Dlog4j.configuration=log4j.properties")
libraryDependencies ++= Seq(
"com.groupon.sparklint" %% "sparklint-spark162" % "1.0.4" excludeAll (
ExclusionRule(organization = "org.apache.spark")
),
"org.apache.spark" %% "spark-core" % "2.4.0",
"org.apache.spark" %% "spark-sql" % "2.4.0",
"org.apache.spark" %% "spark-streaming" % "2.4.0" % "provided",
"org.apache.spark" %% "spark-streaming-kafka" % "1.6.3"
)
WeatherDataStream.scala
package com.supergloo
import kafka.serializer.StringDecoder
import org.apache.log4j.Logger
import org.apache.spark.SparkConf
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.dstream.{DStream, InputDStream}
import org.apache.spark.streaming.kafka.KafkaUtils
/**
* Stream from Kafka
*/
object WeatherDataStream {
val localLogger = Logger.getLogger("WeatherDataStream")
def main(args: Array[String]) {
// update
// val checkpointDir = "./tmp"
val sparkConf = new SparkConf().setAppName("Raw Weather")
sparkConf.setIfMissing("spark.master", "local[5]")
val ssc = new StreamingContext(sparkConf, Seconds(2))
val kafkaTopicRaw = "spark-topic"
val kafkaBroker = "127.0.01:9092"
val topics: Set[String] = kafkaTopicRaw.split(",").map(_.trim).toSet
val kafkaParams = Map[String, String]("metadata.broker.list" -> kafkaBroker)
localLogger.info(s"connecting to brokers: $kafkaBroker")
localLogger.info(s"kafkaParams: $kafkaParams")
localLogger.info(s"topics: $topics")
val rawWeatherStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topics)
localLogger.info(s"Manaaaaaaaaaf --->>>: $rawWeatherStream")
//Kick off
ssc.start()
ssc.awaitTermination()
ssc.stop()
}
}
I have created jar file using command
sbt package
and run the application using command
./spark-submit --master spark://myserver:7077 --class
com.supergloo.WeatherDataStream
/home/Manaf/kafka-streaming_2.11-1.0.jar
But i got error like this
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/streaming/kafka/KafkaUtils$
at com.supergloo.WeatherDataStream$.main(WeatherDataStream.scala:37)
at com.supergloo.WeatherDataStream.main(WeatherDataStream.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52)
at org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:849)
at org.apache.spark.deploy.SparkSubmit.doRunMain$1(SparkSubmit.scala:167)
at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:195)
at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86)
at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:924)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:933)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.spark.streaming.kafka.KafkaUtils$
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Based on my stack overflow analysis, i got idea about create jar using assembly command
sbt assembly
But I got an error like below when executing the assembly command
[error] 153 errors were encountered during merge
[trace] Stack trace suppressed: run last *:assembly for the full output.
[error] (*:assembly) deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.apache.arrow\arrow-vector\jars\arrow-vector-0.10.0.jar:git.properties
[error] C:\Users\amanaf\.ivy2\cache\org.apache.arrow\arrow-format\jars\arrow-format-0.10.0.jar:git.properties
[error] C:\Users\amanaf\.ivy2\cache\org.apache.arrow\arrow-memory\jars\arrow-memory-0.10.0.jar:git.properties
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Inject.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Inject.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Named.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Named.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Provider.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Provider.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Qualifier.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Qualifier.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Scope.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Scope.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\javax.inject\javax.inject\jars\javax.inject-1.jar:javax/inject/Singleton.class
[error] C:\Users\amanaf\.ivy2\cache\org.glassfish.hk2.external\javax.inject\jars\javax.inject-2.4.0-b34.jar:javax/inject/Singleton.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4BlockInputStream.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4BlockInputStream.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4BlockOutputStream.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4BlockOutputStream.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4Compressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4Compressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4Constants.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4Constants.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4Factory.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4Factory.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4FastDecompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4FastDecompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4HCJNICompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4HCJNICompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4HCJavaSafeCompressor$HashTable.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4HCJavaSafeCompressor$HashTable.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4HCJavaSafeCompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4HCJavaSafeCompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4HCJavaUnsafeCompressor$HashTable.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4HCJavaUnsafeCompressor$HashTable.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4HCJavaUnsafeCompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4HCJavaUnsafeCompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4JNI.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4JNI.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4JNICompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4JNICompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4JNIFastDecompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4JNIFastDecompressor.class
[error] deduplicate: different file contents found in the following:
[error] C:\Users\amanaf\.ivy2\cache\org.lz4\lz4-java\jars\lz4-java-1.4.0.jar:net/jpountz/lz4/LZ4JNISafeDecompressor.class
[error] C:\Users\amanaf\.ivy2\cache\net.jpountz.lz4\lz4\jars\lz4-1.2.0.jar:net/jpountz/lz4/LZ4JNISafeDecompressor.class
This issue is related to library versions. I have just updated my build.sbt like this
name := "kafka-streaming"
version := "1.0"
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false)
assemblyMergeStrategy in assembly := {
case PathList("org", "apache", "spark", "unused", "UnusedStubClass.class") => MergeStrategy.first
case PathList(pl # _*) if pl.contains("log4j.properties") => MergeStrategy.concat
case PathList("META-INF", "io.netty.versions.properties") => MergeStrategy.last
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
scalaVersion := "2.11.8"
resolvers += "jitpack" at "https://jitpack.io"
// still want to be able to run in sbt
// https://github.com/sbt/sbt-assembly#-provided-configuration
run in Compile <<= Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run))
fork in run := true
javaOptions in run ++= Seq(
"-Dlog4j.debug=true",
"-Dlog4j.configuration=log4j.properties")
libraryDependencies ++= Seq(
"com.groupon.sparklint" %% "sparklint-spark162" % "1.0.4" excludeAll (
ExclusionRule(organization = "org.apache.spark")
),
"org.apache.spark" %% "spark-core" % "1.6.2" % "provided",
"org.apache.spark" %% "spark-sql" % "1.6.2" % "provided",
"org.apache.spark" %% "spark-streaming" % "1.6.2" % "provided",
"org.apache.spark" %% "spark-streaming-kafka" % "1.6.2",
"com.datastax.spark" %% "spark-cassandra-connector" % "1.6.0"
)
Now the issue resolved.
This is the basic code to ingest messages from Kafka into Spark Streams to do a word frequency count. The code is customized for local machine.
import org.apache.kafka.clients.consumer.ConsumerConfig
import org.apache.kafka.common.serialization.StringDeserializer
import org.apache.spark.SparkConf
import org.apache.spark.streaming._
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.kafka010.LocationStrategies._
import org.apache.spark.streaming.kafka010.ConsumerStrategies._
import org.apache.spark.streaming.kafka010._`
object WordFreqCount {
def main( args:Array[String] ){
println("Start")
val conf = new SparkConf()
.setMaster("local[*]")
.setAppName("KafkaReceiver")
.set("spark.driver.bindAddress","127.0.0.1")
println("conf created")
val spark = SparkSession.builder().config(conf).getOrCreate()
val sc = spark.sparkContext
val ssc = new StreamingContext(sc, Seconds(10))
println("ssc created")
val topics = "wctopic"
val brokers = "127.0.0.1:9092"
val groupId = "wcgroup"
val topicsSet = topics.split(",").toSet
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> brokers,
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"group.id" -> groupId,
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
)
val messages = KafkaUtils.createDirectStream[String, String](
ssc,
PreferConsistent,
Subscribe[String, String](topicsSet, kafkaParams))
// Get the lines, split them into words, count the words and print
val lines = messages.map(_.value)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1L)).reduceByKey(_ + _)
wordCounts.print()
//val kafkaStream = KafkaUtils.createStream(ssc, "127.0.0.1:2181", "wcgroup",Map("wctopic" -> 1))
messages.print() //prints the stream of data received
ssc.start()
ssc.awaitTermination()
println("End")`
}
}
Related
Suppose in MongoDB there are multiple DBs(DB1, DB2, ... DBa, DBb, ....) and each of them has some collections(Col1A, Col1B, ... Col2A, Col2B, ...)
I want to find a way to manage multiple inputs and outputs in MongoDB. I want to have a self-contained Scala Application written in the Scala language. Here is pseudocode that shows my idea:
readconfig_DB1.Col1A=Read setting pointing to DB=DB1 and collection=Col1A
readconfig_DB2.Col2B=Read setting pointing to DB=DB2 and collection=Col2B
val rdd_DB1.Col1A = MongoSpark.load(sc_DB1.Col1A)
val rdd_DB2.Col2B = MongoSpark.load(sc_DB2.Col2B)
DF_Transofmration1 = Do some transformations on DF1a and DF2b
DF_Transofmration2 = Do some transformations on DF1b and DF2a
writeConfig_DBa.Col1A=Write setting pointing to DB=DB1 and collection=Col1A
writeConfig_DBb.Col2B=Write setting pointing to DB=DB2 and collection=Col2B
MongoSpark.save(DF_Transofmration1 , writeConfig_DBa.Col1A)
MongoSpark.save(DF_Transofmration2 , writeConfig_DBa.Col2B)
Edit1:
I tried to run the solution.
The structure of folders:
$find .
.
./src
./src/main
./src/main/scala
./src/main/scala/application.conf
./src/main/scala/SimpleApp.scala
./build.sbt
Content of build.sbt
scalaVersion := "2.11.12"
libraryDependencies ++= Seq(
"org.mongodb.spark" %% "mongo-spark-connector" % "2.4.1",
"org.apache.spark" %% "spark-core" % "2.4.1",
"org.apache.spark" %% "spark-sql" % "2.4.1"
)
Content of application.conf:
config{
database {
"spark_mongodb_input_uri": "mongodb://127.0.0.1/test.myCollection",
"spark_mongodb_user":"",
"spark_mongodb_pass":"",
"spark_mongodb_input_database": "test",
"spark_mongodb_input_collection": "myCollection",
"spark_mongodb_input_readPreference_name": "",
"spark_mongodb_output_database": "test",
"spark_mongodb_output_collection": "myCollection"
}
newreaderone {
"database": "test",
"collection": "myCollection",
"readPreference.name": ""
}
newwriterone {
"uri":"mongodb://127.0.0.1/test.myCollection"
"database": "test",
"collection": "myCollection",
"replaceDocument": "false",//If set to True, updates an existing document
"readPreference.name": "",
"maxBatchSize": "128"
}
}
content of SimpleApp.scala:
import com.mongodb.spark.MongoSpark
import com.mongodb.spark.config.ReadConfig
import org.apache.spark.sql.SparkSession
object FirstApp {
def main(args: Array[String]) {
import com.typesafe.{Config,ConfigFactory}
val appConfig: Config = ConfigFactory.load("application.conf")
import scala.collection.JavaConverters._
val initial_conf:Config = appconf.getConfig("config.database")
val confMap: Map[String,String] = initial_conf.entrySet()
.iterator.asScala
.map(e => e.getKey.replaceAll("_",".") -> e.getValue.unwrapped.toString).toMap
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame,SparkSession}
val sparkConfig: SparkConf=new SparkConf()
sparkConfig.setAll(confMap)
val spark: SparkSession = SparkSession.builder.config(sparkConf).enableHiveSupport.getOrCreate
import com.mongodb.spark._
val data: DataFrame = MongoSpark.load(spark)
import com.mongodb.spark.config._
val nreader = appConfig.getConfig("config.newreaderone")
val readMap: Map[String,Any] = nreader.entrySet()
.iterator.asScala
.map(e => e.getKey -> e.getValue.unwrapped)
.toMap
val customReader = ReadConfig(readMap)
val newDF: DataFrame = spark.read.mongo(customReader)
resultDF.write.mode("append").mongo()
}
}
Error after compilation:
sbt package
[info] Updated file /Path/3/project/build.properties: set sbt.version to 1.3.10
[info] Loading global plugins from /home/sadegh/.sbt/1.0/plugins
[info] Loading project definition from /Path/3/project
[info] Loading settings for project root-3 from build.sbt ...
[info] Set current project to root-3 (in build file:/Path/3/)
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
[info] Compiling 1 Scala source to /Path/3/target/scala-2.11/classes ...
[error] /Path/3/src/main/scala/SimpleApp.scala:8:13: object typesafe is not a member of package com
[error] import com.typesafe.{Config,ConfigFactory}
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:9:17: not found: type Config
[error] val appConfig: Config = ConfigFactory.load("application.conf")
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:9:26: not found: value ConfigFactory
[error] val appConfig: Config = ConfigFactory.load("application.conf")
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:11:19: not found: type Config
[error] val initial_conf:Config = appconf.getConfig("config.database")
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:11:28: not found: value appconf
[error] val initial_conf:Config = appconf.getConfig("config.database")
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:19:56: not found: value sparkConf
[error] val spark: SparkSession = SparkSession.builder.config(sparkConf).enableHiveSupport.getOrCreate
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:28:21: overloaded method value apply with alternatives:
[error] (options: scala.collection.Map[String,String])com.mongodb.spark.config.ReadConfig.Self <and>
[error] (sparkConf: org.apache.spark.SparkConf)com.mongodb.spark.config.ReadConfig.Self <and>
[error] (sqlContext: org.apache.spark.sql.SQLContext)com.mongodb.spark.config.ReadConfig.Self <and>
[error] (sparkSession: org.apache.spark.sql.SparkSession)com.mongodb.spark.config.ReadConfig.Self <and>
[error] (sparkContext: org.apache.spark.SparkContext)com.mongodb.spark.config.ReadConfig.Self
[error] cannot be applied to (scala.collection.immutable.Map[String,Any])
[error] val customReader = ReadConfig(readMap)
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:29:36: value mongo is not a member of org.apache.spark.sql.DataFrameReader
[error] val newDF: DataFrame = spark.read.mongo(customReader)
[error] ^
[error] /Path/3/src/main/scala/SimpleApp.scala:30:2: not found: value resultDF
[error] resultDF.write.mode("append").mongo()
[error] ^
[error] 9 errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 12 s, completed Jun 14, 2020 6:55:43 PM
You can pass the configurations as inputs to your application in HOCON.
You can try the following HOCON configuration snippet for mulitple read and write configuration.
config{
database {
"spark_mongodb_input_uri": "mongodb://connection/string/here",
"spark_mongodb_user":"your_user_name",
"spark_mongodb_pass":"your_password",
"spark_mongodb_input_database": "Some_Db_Name",
"spark_mongodb_input_collection": "Some_Col_Name",
"spark_mongodb_input_readPreference_name": "primaryPreferred",
"spark_mongodb_output_database": "Some_Output_Db_Name",
"spark_mongodb_output_collection": "Some_Output_Col_Name"
}
newreaderone {
"database": "sf",
"collection": "matchrecord",
"readPreference.name": "secondaryPreferred"
}
newwriterone {
"uri":"mongodb://uri of same or new mongo cluster/instance"
"database": "db_name",
"collection": "col_name",
"replaceDocument": "false",//If set to True, updates an existing document
"readPreference.name": "secondaryPreferred",
"maxBatchSize": "128"
}
}
the above configuration has been tested and can be read easily with Typesafe Config library.
Update:
Enter the above configuration in a file call application.conf.
Use the following line of code to read the file
Step 1:
Reading the configuration file
import com.typesafe.{Config,ConfigFactory}
val appConfig: Config = ConfigFactory.load("/path/to/application.conf")
Step 2:
To initialize spark to read and write to MongoDB we use the config under the database section as follows:
import scala.collection.JavaConverters._
val initial_conf:Config = appconf.getConfig("config.database")
val confMap: Map[String,String] = initial_conf.entrySet()
.iterator.asScala
.map(e => e.getKey.replaceAll("_",".") -> e.getValue.unwrapped.toString).toMap
Step 3: Create SparkSession
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame,SparkSession}
val sparkConfig: SparkConf=new SparkConf()
sparkConfig.setAll(confMap)
val spark: SparkSession = SparkSession.builder.config(sparkConf).enableHiveSupport.getOrCreate
Step 4:
Read DataFrame from MongoDB
import com.mongodb.spark._
val data: DataFrame = MongoSpark.load(spark)
The above step reads the collection specified in the database section of the configuration
Step 5:
Reading a new collection:
import com.mongodb.spark.config._
val nreader = appConfig.getConfig("config.newreaderone")
val readMap: Map[String,Any] = nreader.entrySet()
.iterator.asScala
.map(e => e.getKey -> e.getValue.unwrapped)
.toMap
val customReader = ReadConfig(readMap)
val newDF: DataFrame = spark.read.mongo(customReader)
Step 6:
Writing to MongoDB Collection
resultDF.write.mode("append").mongo()
Above code writes to the collection speified under the database section of the configuration
ii) Writing to collection other than the one specified in SparkConf
import com.mongodb.spark.config._
val nwriter = appConfig.getConfig("config.newwriterone")
val writerMap: Map[String,Any] = nreader.entrySet()
.iterator.asScala
.map(e => e.getKey -> e.getValue.unwrapped).toMap
val writeConf = WriteConfig(writerMap)
MongoSpark.save(resultDF, writeConf)
Update:
The whole code looks as folows, look at the two ways I save the dataframe into MongoDb in the end
import com.typesafe.{Config,ConfigFactory}
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame,SparkSession}
import scala.collection.JavaConverters._
import com.mongodb.spark._
import com.mongodb.spark.config._
object ReadWriteMongo{
def main(args: Array[String]): Unit = {
val appConfig: Config = ConfigFactory.load("application.conf")
val initial_conf:Config = appconf.getConfig("config.database")
val confMap: Map[String,String] = initial_conf.entrySet()
.iterator.asScala
.map(e => e.getKey.replaceAll("_",".") -> e.getValue.unwrapped.toString).toMap
val sparkConfig: SparkConf=new SparkConf()
sparkConfig.setAll(confMap)
val spark: SparkSession = SparkSession.builder.config(sparkConf).enableHiveSupport.getOrCreate
val data: DataFrame = MongoSpark.load(spark)
val nreader = appConfig.getConfig("config.newreaderone")
val readMap: Map[String,Any] = nreader.entrySet()
.iterator.asScala
.map(e => e.getKey -> e.getValue.unwrapped)
.toMap
val customReader = ReadConfig(readMap)
/*
Read Data from MongoDB
*/
val newDF: DataFrame = spark.read.mongo(customReader)
/*
* After you performing processing on the newDF above and save
* the result in a new Dataframe called "resultDF".
* You can save the DF as follows
*/
resultDF.write.mode("append").mongo()
/*
*Alternatively You can save a Dataframe also by passing a WriteConfig as follows
*/
val nwriter = appConfig.getConfig("config.newwriterone")
val writerMap: Map[String,Any] = nreader.entrySet()
.iterator.asScala
.map(e => e.getKey -> e.getValue.unwrapped).toMap
val writeConf = WriteConfig(writerMap)
MongoSpark.save(resultDF, writeConf)
}
}
The folder structure should be as follows:
src/
src/main/scala/com/test/ReadWriteMongo.scala
src/main/resources/application.conf
Update: build.sbt
val sparkVersion = "2.4.1"
scalaVersion := "2.11.12"
scalacOptions ++= Seq(
"-deprecation",
"-feature",
"-Xfuture",
"-encoding",
"UTF-8",
"-unchecked",
"-language:postfixOps"
)
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.4.0",
"org.mongodb.spark" %% "mongo-spark-connector" % sparkVersion,
"org.apache.spark" %% "spark-core" % sparkVersion % Provided,
"org.apache.spark" %% "spark-sql" % sparkVersion % Provided
)
mainClass in assembly := Some("com.test.SimpleApp.scala")
assembly / test := {}
assemblyJarName in assembly := s"${name.value}-${version.value}.jar"
assemblyMergeStrategy in assembly := {
case m if m.toLowerCase.endsWith("manifest.mf") => MergeStrategy.discard
case m if m.toLowerCase.matches("meta-inf.*\\.sf$") => MergeStrategy.discard
case "reference.conf" => MergeStrategy.concat
case x: String if x.contains("UnusedStubClass.class") => MergeStrategy.first
case _ => MergeStrategy.first
}
I'm newby with sbt and scala. Just want to make jar file to run in on server, but when I try to compile jar file I get error. Program code is very simple, only one class (can't post it here, stackoverflow doesn't allow). When I run it in Intellij everything is fine. But sbt assembly fires this error:
[info] Merging files...
[error] scala.MatchError: akka\stream\OverflowStrategies$.class (of class java.lang.String)
[error] at $a019333dc409d47a4d92$.$anonfun$$sbtdef$2(D:\workspace_scala\TestSbt2\build.sbt:25)
[error] at sbtassembly.Assembly$.$anonfun$applyStrategies$6(Assembly.scala:115)
[error] at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
[error] at scala.collection.Iterator.foreach(Iterator.scala:929)
[error] at scala.collection.Iterator.foreach$(Iterator.scala:929)
[error] at scala.collection.AbstractIterator.foreach(Iterator.scala:1417)
[error] at scala.collection.IterableLike.foreach(IterableLike.scala:71)
[error] at scala.collection.IterableLike.foreach$(IterableLike.scala:70)
[error] at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
[error] at scala.collection.TraversableLike.map(TraversableLike.scala:234)
[error] at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
[error] at scala.collection.AbstractTraversable.map(Traversable.scala:104)
[error] at sbtassembly.Assembly$.applyStrategies(Assembly.scala:114)
[error] at sbtassembly.Assembly$.x$1$lzycompute$1(Assembly.scala:26)
[error] at sbtassembly.Assembly$.x$1$1(Assembly.scala:24)
[error] at sbtassembly.Assembly$.stratMapping$lzycompute$1(Assembly.scala:24)
[error] at sbtassembly.Assembly$.stratMapping$1(Assembly.scala:24)
[error] at sbtassembly.Assembly$.inputs$lzycompute$1(Assembly.scala:68)
[error] at sbtassembly.Assembly$.inputs$1(Assembly.scala:58)
[error] at sbtassembly.Assembly$.apply(Assembly.scala:85)
[error] at sbtassembly.Assembly$.$anonfun$assemblyTask$1(Assembly.scala:249)
[error] at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:39)
[error] at sbt.std.Transform$$anon$4.work(System.scala:66)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:262)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] at sbt.Execute.work(Execute.scala:271)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:262)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:174)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:36)
[error] at java.util.concurrent.FutureTask.run(Unknown Source)
[error] at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
[error] at java.util.concurrent.FutureTask.run(Unknown Source)
[error] at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
[error] at java.lang.Thread.run(Unknown Source)
[error] (assembly) scala.MatchError: akka\stream\OverflowStrategies$.class (of class java.lang.String)
[error] Total time: 1 s, completed Jun 20, 2018 1:20:02 PM
built.sbt
name := "TestSbt2"
version := "0.1"
scalaVersion := "2.12.4"
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.5.13"
libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.13"
libraryDependencies += "com.typesafe.akka" %% "akka-http" % "10.1.0"
assemblyMergeStrategy in assembly := {
case PathList("reference.conf") => MergeStrategy.concat
}
project/assembly.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")
Program code:
import akka.actor._
import akka.http.scaladsl._
import akka.http.scaladsl.model.ws.{Message, TextMessage}
import akka.http.scaladsl.server.Directives._
import akka.stream._
import akka.stream.scaladsl._
import scala.io.StdIn
object Server2 {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
def echoFlow: Flow[Message, Message, Any] =
Flow[Message].map {
case tm: TextMessage.Strict => TextMessage.Strict("Test " + tm.text)
case _ => TextMessage("Message type unsupported")
}
val websocketRoute =
path("chat") {
handleWebSocketMessages(echoFlow)
}
val bindingFuture = Http().bindAndHandle(websocketRoute, "127.0.0.1", 8080)
// the rest of the sample code will go here
println("- Started server at 127.0.0.1:8080, press enter to kill server")
StdIn.readLine()
system.terminate()
}
}
Not really sure what's going on, but if you add a default case to your assemblyMergeStrategy definition, it should work just fine.
For example:
assemblyMergeStrategy in assembly := {
case "reference.conf" => MergeStrategy.concat
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
Little edit:
Actually on the repo it says
assemblyMergeStrategy in assembly expects a function. You can't do assemblyMergeStrategy in assembly := MergeStrategy.first
The fact that it says "MatchError", it's found in the build.sbt file and your sbt file says
assemblyMergeStrategy in assembly := {
case PathList("reference.conf") => MergeStrategy.concat
}
tells me, that you want to use a fallback case.
Add this as a second case in the same match (after your case PathList)
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
(copied from GitHub-sbt-assembly)
Thanks people!
This helped:
mainClass in assembly := Some("chat.Server2")
assemblyMergeStrategy in assembly := {
case "reference.conf" => MergeStrategy.concat
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
I want to deploy and submit a spark program using sbt but its throwing error.
Code:
package in.goai.spark
import org.apache.spark.{SparkContext, SparkConf}
object SparkMeApp {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("First Spark")
val sc = new SparkContext(conf)
val fileName = args(0)
val lines = sc.textFile(fileName).cache
val c = lines.count
println(s"There are $c lines in $fileName")
}
}
build.sbt
name := "First Spark"
version := "1.0"
organization := "in.goai"
scalaVersion := "2.11.8"
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.6.1"
resolvers += Resolver.mavenLocal
Under first/project directory
build.properties
bt.version=0.13.9
When I am trying to run sbt package its throwing error given below.
[root#hadoop first]# sbt package
[info] Loading project definition from /home/training/workspace_spark/first/project
[info] Set current project to First Spark (in build file:/home/training/workspace_spark/first/)
[info] Compiling 1 Scala source to /home/training/workspace_spark/first/target/scala-2.11/classes...
[error] /home/training/workspace_spark/first/src/main/scala/LineCount.scala:3: object apache is not a member of package org
[error] import org.apache.spark.{SparkContext, SparkConf}
[error] ^
[error] /home/training/workspace_spark/first/src/main/scala/LineCount.scala:9: not found: type SparkConf
[error] val conf = new SparkConf().setAppName("First Spark")
[error] ^
[error] /home/training/workspace_spark/first/src/main/scala/LineCount.scala:11: not found: type SparkContext
[error] val sc = new SparkContext(conf)
[error] ^
[error] three errors found
[error] (compile:compile) Compilation failed
[error] Total time: 4 s, completed May 10, 2018 4:05:10 PM
I have tried with extends to App too but no change.
Please remove resolvers += Resolver.mavenLocal from build.sbt. Since spark-core is available on Maven, we don't need to use local resolvers.
After that, you can try sbt clean package.
I have multiple subprojects in my sbt, one being a server (base upon playframework) the other being the clientside (scala.js) and the third one being the communication between the two in form of protobuf (scalapb).
Now, this is my build.sbt:
lazy val generalSettings = Seq(
organization := "tld.awesomeness",
version := "0.0.1",
scalaVersion := "2.12.1"
)
val CrossDependencies = new
{
val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" % "test"
val scalactic = "org.scalactic" %% "scalactic" % "3.0.1"
val scalaTags = "com.lihaoyi" %% "scalatags" % "0.6.2"
}
lazy val proto = (project in file("modules/proto"))
.settings(generalSettings: _*)
.settings(
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
),
// If you need scalapb/scalapb.proto or anything from google/protobuf/*.proto
libraryDependencies ++= Seq(
"com.trueaccord.scalapb" %% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf",
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion,
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf"
)
)
lazy val play = (project in file("modules/play"))
.enablePlugins(PlayScala)
.settings(generalSettings: _*)
.settings(
name := "play",
libraryDependencies ++= Seq(
CrossDependencies.scalaTest,
CrossDependencies.scalactic,
CrossDependencies.scalaTags,
"com.typesafe.play" %% "play-json" % "2.6.0-M1"),
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline),
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
)
.aggregate(slick)
.dependsOn(slick)
.aggregate(flyway)
.dependsOn(flyway)
.aggregate(proto)
.dependsOn(proto)
lazy val client = (project in file("modules/client"))
.enablePlugins(ScalaJSPlugin, ScalaJSWeb)
.settings(generalSettings: _*)
.settings(
name := "client",
libraryDependencies += CrossDependencies.scalaTags,
persistLauncher := true
)
.aggregate(proto)
.dependsOn(proto)
// Loads the jvm project at sbt startup
onLoad in Global := (Command.process("project play", _: State)) compose (onLoad in Global).value
fork in run := true
and this is the plugins.sbt:
// Scala.JS
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.14")
addSbtPlugin("com.vmunier" % "sbt-web-scalajs" % "1.0.2")
// Play
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.0-SNAPSHOT")
// Proto
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.3" exclude ("com.trueaccord.scalapb", "protoc-bridge_2.10"))
libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin-shaded" % "0.5.47"
This is one proto file:
syntax = "proto3";
package tld.awesomeness.proto;
message Test {
int32 id = 1;
string email = 2;
}
After compilation I get Test.class
Now in the client I try to:
private def doSend(ws: WebSocket): Unit =
{
val msg = Test().withId(1337)
val a: ArrayBuffer = new ArrayBuffer(msg.toByteArray.length)
msg.toByteArray
ws.send(a)
}
(The websocket itself worked all just fine when I sent strings through it!)
Now I get this huge stacktrace:
[info] Fast optimizing /home/sorona/awesomeness/modules/client/target/scala-2.12/client-fastopt.js
[error] Referring to non-existent class tld.awesomeness.proto.Test.Test$
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent class tld.awesomeness.proto.Test.Test
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.toByteArray()[scala.Byte
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.withId(scala.Int)tld.awesomeness.proto.Test.Test
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test$.apply$default$2()java.lang.String
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test$.apply$default$1()scala.Int
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
[error] Referring to non-existent method tld.awesomeness.proto.Test.Test.<init>(scala.Int,java.lang.String)
[error] called from tld.awesomeness.ScalaJSTest$.doSend(org.scalajs.dom.raw.WebSocket)scala.Unit
[error] called from tld.awesomeness.ScalaJSTest$.tld$awesomeness$ScalaJSTest$$$anonfun$call$1(org.scalajs.dom.raw.Event,org.scalajs.dom.raw.WebSocket)org.scalajs.dom.raw.Event
[error] called from tld.awesomeness.ScalaJSTest$.call()scala.Unit
[error] called from tld.awesomeness.Main$.main()scala.Unit
[error] called from scala.scalajs.js.JSApp.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.$$js$exported$meth$main()java.lang.Object
[error] called from tld.awesomeness.Main$.main
[error] exported to JavaScript with #JSExport
[error] involving instantiated classes:
[error] tld.awesomeness.ScalaJSTest$
[error] tld.awesomeness.Main$
java.lang.RuntimeException: There were linking errors
at scala.sys.package$.error(package.scala:27)
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:133)
at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:86)
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun$4.apply(LinkerFrontend.scala:54)
at org.scalajs.core.tools.linker.frontend.LinkerFrontend$$anonfun$4.apply(LinkerFrontend.scala:54)
at org.scalajs.core.tools.logging.Logger$class.time(Logger.scala:28)
at org.scalajs.sbtplugin.Loggers$SbtLoggerWrapper.time(Loggers.scala:7)
at org.scalajs.core.tools.linker.frontend.LinkerFrontend.link(LinkerFrontend.scala:53)
at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply$mcV$sp(Linker.scala:50)
at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply(Linker.scala:49)
at org.scalajs.core.tools.linker.Linker$$anonfun$link$1.apply(Linker.scala:49)
at org.scalajs.core.tools.linker.Linker.guard(Linker.scala:67)
at org.scalajs.core.tools.linker.Linker.link(Linker.scala:49)
at org.scalajs.core.tools.linker.ClearableLinker$$anonfun$link$1.apply(ClearableLinker.scala:51)
at org.scalajs.core.tools.linker.ClearableLinker$$anonfun$link$1.apply(ClearableLinker.scala:51)
at org.scalajs.core.tools.linker.ClearableLinker.linkerOp(ClearableLinker.scala:62)
at org.scalajs.core.tools.linker.ClearableLinker.link(ClearableLinker.scala:51)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6$$anonfun$apply$7.apply(ScalaJSPluginInternal.scala:251)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6$$anonfun$apply$7.apply(ScalaJSPluginInternal.scala:239)
at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253)
at sbt.FileFunction$$anonfun$cached$1.apply(Tracked.scala:253)
at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:267)
at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3$$anonfun$apply$4.apply(Tracked.scala:263)
at sbt.Difference.apply(Tracked.scala:224)
at sbt.Difference.apply(Tracked.scala:206)
at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:263)
at sbt.FileFunction$$anonfun$cached$2$$anonfun$apply$3.apply(Tracked.scala:262)
at sbt.Difference.apply(Tracked.scala:224)
at sbt.Difference.apply(Tracked.scala:200)
at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:262)
at sbt.FileFunction$$anonfun$cached$2.apply(Tracked.scala:260)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6.apply(ScalaJSPluginInternal.scala:256)
at org.scalajs.sbtplugin.ScalaJSPluginInternal$$anonfun$org$scalajs$sbtplugin$ScalaJSPluginInternal$$scalaJSStageSettings$4$$anonfun$apply$6.apply(ScalaJSPluginInternal.scala:237)
at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40)
at sbt.std.Transform$$anon$4.work(System.scala:63)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:228)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
at sbt.Execute.work(Execute.scala:237)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:228)
at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159)
at sbt.CompletionService$$anon$2.call(CompletionService.scala:28)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
[error] (client/compile:fastOptJS) There were linking errors
My ide finds everything but obviously I am doing something wrong. I already had a look at https://github.com/thesamet/scalapbjs-test but to no avail.
Problem appears with that line val msg = Test().withId(1337)
edit: after comment I changed build.sbt:
lazy val proto = (crossProject in file("modules/proto"))
.settings(generalSettings: _*)
.settings(
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)).
jvmSettings(
libraryDependencies += "com.trueaccord.scalapb" %% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf",
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)
).
jsSettings(
libraryDependencies ++= Seq(
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion,
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf"
),
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
)
)
lazy val protoJs = proto.js
lazy val protoJVM = proto.jvm
lazy val play = (project in file("modules/play"))
.enablePlugins(PlayScala)
.settings(generalSettings: _*)
.settings(
name := "play",
libraryDependencies ++= Seq(
CrossDependencies.scalaTest,
CrossDependencies.scalactic,
CrossDependencies.scalaTags,
"com.typesafe.play" %% "play-json" % "2.6.0-M1"),
scalaJSProjects := Seq(client),
pipelineStages in Assets := Seq(scalaJSPipeline),
compile in Compile := ((compile in Compile) dependsOn scalaJSPipeline).value
)
.aggregate(slick)
.dependsOn(slick)
.aggregate(flyway)
.dependsOn(flyway)
.aggregate(protoJVM)
.dependsOn(protoJVM)
lazy val client = (project in file("modules/client"))
.enablePlugins(ScalaJSPlugin, ScalaJSWeb)
.settings(generalSettings: _*)
.settings(
name := "client",
libraryDependencies += CrossDependencies.scalaTags,
persistLauncher := true
)
.aggregate(protoJs)
.dependsOn(protoJs)
now now neither play nor client can resolve the proto-class :(
(Also I am aware of the redundant PB.targets in Compile..., I just thought that sharing might not work there, so I added it to both distinct settings again)
With pure CrossProject you need to specify the actual path ScalaPB should look for proto files (the value it guesses is wrong). Here is a minimal example:
lazy val proto = (crossProject.crossType(CrossType.Pure) in file("proto"))
.settings(
PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
),
// The trick is in this line:
PB.protoSources in Compile := Seq(file("proto/src/main/protobuf")),
libraryDependencies ++= Seq(
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion,
"com.trueaccord.scalapb" %%% "scalapb-runtime" % com.trueaccord.scalapb.compiler.Version.scalapbVersion % "protobuf"
)
)
I'm using jOOQ. Solving an issue with jooq-sbt-plugin config (here) resulted in a classpath issue which I think is separate from the original one. I managed to get the configuration to work but trying to get it play with Oracle drivers seems impossible.
The issue here is that the plugin seems run its own java process and hence the required classpath (with odbc14.jar in it) is never passed on. Is there any way to get the plugin work? I couldn't figure out how to inject to the plugin's classpath.
The only workaround I can come up with is by defining a task instead (described here: https://gist.github.com/chris-martin/5140754).
Any help is greatly appreciated. Thanks.
2013-09-10 Update
Here's the config:
import sbt._
import Keys._
import JOOQPlugin._
object SampleBuild extends Build {
lazy val all = Project(id = "all", base = file("."), settings = defaultSettings) aggregate(
one, two
)
lazy val one = Project(
id = "one",
base = file("one"),
settings = defaultSettings ++ Seq(
libraryDependencies ++= Dependencies.one
)
)
lazy val two = Project(
id = "two",
base = file("two"),
settings = defaultSettings ++ jooqSettings ++ customJooqSettings ++ Seq(
libraryDependencies ++= Dependencies.two
)
) dependsOn (one)
override lazy val settings = super.settings ++ buildSettings
lazy val buildSettings = Seq(
organization := "org.sample",
version := "0.1-SNAPSHOT",
scalaVersion := "2.10.2"
)
lazy val defaultSettings = Defaults.defaultSettings ++ Seq(
scalacOptions in Compile ++= scalacParams,
externalResolvers in Compile := Resolvers.commonResolvers,
shellPrompt := ShellPrompt.buildShellPrompt,
resolvers ++= Resolvers.commonResolvers
)
lazy val customJooqSettings = Seq(
jooqOptions := jooqBvpOptions,
jooqOutputDirectory := new java.io.File("../src/appdb/src/main/java")
)
lazy val jooqBvpOptions = Seq(
"jdbc.driver" -> "oracle.jdbc.OracleDriver",
"jdbc.url" -> "jdbc:oracle:thin:#//<some server>",
"jdbc.user" -> "<some user>",
"jdbc.password" -> "<some pwd>",
"generator.database.name" -> "org.jooq.util.oracle.OracleDatabase",
"generator.database.inputSchema" -> "<some schema>",
"generator.database.includes" -> "table1|table2|table3",
"generator.target.packageName" -> "org.example.generated")
}
object Resolvers { /* ... */ }
object Dependencies { /* ... */ }
object ShellPrompt { /* ... */ }
And here's the error:
[info] Initialising properties : /jooq-config2705409947508036761.xml
[error] Cannot read /jooq-config2705409947508036761.xml. Error : oracle.jdbc.OracleDriver
[error] java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
[error] at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
[error] at java.security.AccessController.doPrivileged(Native Method)
[error] at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
[error] at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
[error] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
[error] at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
[error] at java.lang.Class.forName0(Native Method)
[error] at java.lang.Class.forName(Class.java:171)
[error] at org.jooq.util.GenerationTool.main(GenerationTool.java:269)
[error] at org.jooq.util.GenerationTool.main(GenerationTool.java:123)
[error] Usage : GenerationTool <configuration-file>
[trace] Stack trace suppressed: run last appdb-tool/jooq:codegen for the full output.
[error] (appdb-tool/jooq:codegen) Failed with return code: 255
[error] Total time: 1 s, completed Sep 10, 2013 1:45:24 PM
jooq-sbt-plugin's readme says:
Add your database driver to your list of libraryDependencies with "jooq" scope:
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.22" % "jooq"
You left out Dependencies.two in the above excerpt, but maybe you're missing that.