Creating API using scala Akka, code is running in IDE but when jar is created not able to run the code: usind scala 2.11.12 and Below is build.sbt
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.11.12"
lazy val root = (project in file("."))
.settings(
name := "JNPM_SCALA_DATA_API",
// Ensure that the IDE-specific settings like 'idePackagePrefix' are necessary or correctly configured.
idePackagePrefix := Some("org.jio.jnpm"),
// Adding resolver within project settings
resolvers += "Typesafe Repo" at "https://repo.typesafe.com/typesafe/releases/",
// Library dependencies
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % "10.0.15", // Updated to stable version
"com.typesafe.akka" %% "akka-actor" % "2.4.20",
"com.typesafe.akka" %% "akka-stream" % "2.4.20",
"com.typesafe.akka" %% "akka-http-spray-json" % "10.0.15" // JSON library for Akka HTTP
),
// Assembly settings
// assembly / assemblyMergeStrategy := {
// case PathList("META-INF", xs @ _*) => MergeStrategy.discard
// case "application.conf" => MergeStrategy.concat
// case _ => MergeStrategy.first
// }
// )
assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case "application.conf" => MergeStrategy.concat
case _ => MergeStrategy.first
}
)
Below is application.conf:
akka {
loglevel = "INFO"
actor {
default-dispatcher {
type = "Dispatcher"
executor = "fork-join-executor"
fork-join-executor {
parallelism-min = 2
parallelism-factor = 2.0
parallelism-max = 10
}
}
}
stream {
materializer {
initial-input-buffer-size = 16
max-input-buffer-size = 128
}
}
}
Main method :
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Route
import models.{JsonSupport, ReportPayload}
import scala.concurrent.ExecutionContextExecutor
import akka.stream.ActorMaterializerSettings
import akka.http.scaladsl.server.RouteResult.route2HandlerFlow
import com.typesafe.config.ConfigFactory
object WebServer extends JsonSupport{
def main(args: Array[String]): Unit = {
implicit val system: ActorSystem = ActorSystem("akkaHttpServer", ConfigFactory.load())
println("Dispatcher Config: " + system.settings.config.getConfig("akka.actor.default-dispatcher"))
val materializerSettings = ActorMaterializerSettings(system).withDispatcher("akka.actor.default-dispatcher") //default-dispatcher
implicit val materializer: ActorMaterializer = ActorMaterializer(materializerSettings)(system)
implicit val executionContext: ExecutionContextExecutor = system.dispatcher
val route: Route = concat(
get {
path("hello") {
complete(HttpResponse(OK, entity = "Hello from Akka HTTP!"))
}
},
post {
path("echo") {
entity(as[String]) { body =>
complete(HttpResponse(OK, entity = body)) // Echoes back the posted content
}
}
},
post {
path("jnpm" / "pm" / "data" / "network_element") {
entity(as[ReportPayload]) { reportPayload =>
// Log received report details (simple console output for demonstration).
println(s"Received report for user: ${reportPayload.user_id}")
// Responds with a confirmation message.
complete(StatusCodes.OK, s"Report for ${reportPayload.report_name} received and is being processed.")
}
}
}
)
import akka.http.scaladsl.server.RouteResult._
val bindingFuture = Http().bindAndHandle(route, "0.0.0.0", 8088)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
scala.io.StdIn.readLine() // Blocks here to keep the app running until the ENTER key is pressed.
bindingFuture
.flatMap(_.unbind()) // Disconnects the server from the port.
.onComplete(_ => system.terminate()) // Shuts down the actor system to clean up resources.
}
}
Getting below error :
Loading config from properties {java.runtime.name=Java(TM) SE Runtime Environment, sun.boot.library.path=C:\Program Files (x86)\Java\jre-1.8\bin, java.vm.version=25.371-b11, java.vm.vendor=Oracle Corporation, java.vendor.url=http://java.oracle.com/, path.separator=;, java.vm.name=Java HotSpot(TM) Client VM, file.encoding.pkg=sun.io, user.script=, user.country=IN, sun.java.launcher=SUN_STANDARD, sun.os.patch.level=, java.vm.specification.name=Java Virtual Machine Specification, user.dir=C:\SCALA_SPARK\JNPM_SCALA_DATA_API\target\scala-2.11, java.runtime.version=1.8.0_371-b11, java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment, java.endorsed.dirs=C:\Program Files (x86)\Java\jre-1.8\lib\endorsed, os.arch=x86, java.io.tmpdir=C:\Users\VIVEKA~1.DES\AppData\Local\Temp\, line.separator=
, java.vm.specification.vendor=Oracle Corporation, user.variant=, os.name=Windows 11, sun.jnu.encoding=Cp1252, java.library.path=C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\WindowsPowerShell\Scripts;C:\Windows\CCM;C:\Windows\CCM;C:\Windows\CCM;C:\Program Files (x86)\Enterprise Vault\EVClient\x64\;C:\Windows\CCM;C:\Windows\CCM;C:\Windows\CCM;C:\Users\Vivekanand.Desai\AppData\Local\Programs\Python\Python310\Scripts\;C:\Users\Vivekanand.Desai\AppData\Local\Programs\Python\Python310\;C:\Users\Vivekanand.Desai\AppData\Local\Programs\Python\Launcher\;C:\Users\Vivekanand.Desai\AppData\Local\Microsoft\WindowsApps;C:\apps\hadoop\bin;C:\apps\spark-3.5.0-bin-hadoop3\spark-3.5.0-bin-hadoop3\bin;C:\apps\spark-3.5.0-bin-hadoop3\spark-3.5.0-bin-hadoop3\sbin;C:\Java\jre-8u202-windows-x64\jre1.8.0_202\bin;;., java.specification.name=Java Platform API Specification, java.class.version=52.0, sun.management.compiler=HotSpot Client Compiler, os.version=10.0, user.home=C:\Users\Vivekanand.Desai, user.timezone=, java.awt.printerjob=sun.awt.windows.WPrinterJob, file.encoding=Cp1252, java.specification.version=1.8, user.name=Vivekanand.Desai, java.class.path=JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar, java.vm.specification.version=1.8, sun.arch.data.model=32, java.home=C:\Program Files (x86)\Java\jre-1.8, sun.java.command=JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar, java.specification.vendor=Oracle Corporation, user.language=en, awt.toolkit=sun.awt.windows.WToolkit, config.trace=loads, java.vm.info=mixed mode, java.version=1.8.0_371, java.ext.dirs=C:\Program Files (x86)\Java\jre-1.8\lib\ext;C:\Windows\Sun\Java\lib\ext, sun.boot.class.path=C:\Program Files (x86)\Java\jre-1.8\lib\resources.jar;C:\Program Files (x86)\Java\jre-1.8\lib\rt.jar;C:\Program Files (x86)\Java\jre-1.8\lib\jsse.jar;C:\Program Files (x86)\Java\jre-1.8\lib\jce.jar;C:\Program Files (x86)\Java\jre-1.8\lib\charsets.jar;C:\Program Files (x86)\Java\jre-1.8\lib\jfr.jar;C:\Program Files (x86)\Java\jre-1.8\classes, sun.stderr.encoding=cp437, java.vendor=Oracle Corporation, java.specification.maintenance.version=4, file.separator=\, java.vendor.url.bug=http://bugreport.sun.com/bugreport/, sun.cpu.endian=little, sun.io.unicode.encoding=UnicodeLittle, sun.stdout.encoding=cp437, sun.desktop=windows, sun.cpu.isalist=}
Loading config from resource 'application.conf' URL jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/application.conf from class loader sun.misc.Launcher$AppClassLoader@647e05
Loading config from a URL: jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/application.conf
URL sets Content-Type: 'content/unknown'
'content/unknown' isn't a known content type
Loading config from class loader sun.misc.Launcher$AppClassLoader@647e05 but there were no resources called application.json
exception loading application.json: java.io.IOException: resource not found on classpath: application.json
Loading config from class loader sun.misc.Launcher$AppClassLoader@647e05 but there were no resources called application.properties
exception loading application.properties: java.io.IOException: resource not found on classpath: application.properties
Loading config from resource 'reference.conf' URL jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/reference.conf from class loader sun.misc.Launcher$AppClassLoader@647e05
Loading config from a URL: jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/reference.conf
URL sets Content-Type: 'content/unknown'
'content/unknown' isn't a known content type
Looking for 'version.conf' relative to ParseableResourceURL(jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/reference.conf)
Looking for 'version.json' relative to ParseableResourceURL(jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/reference.conf)
Looking for 'version.properties' relative to ParseableResourceURL(jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/reference.conf)
Loading config from resource 'version.conf' URL jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/version.conf from class loader sun.misc.Launcher$AppClassLoader@647e05
Loading config from a URL: jar:file:/C:/SCALA_SPARK/JNPM_SCALA_DATA_API/target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar!/version.conf
URL sets Content-Type: 'content/unknown'
'content/unknown' isn't a known content type
Loading config from class loader sun.misc.Launcher$AppClassLoader@647e05 but there were no resources called version.json
exception loading version.json: java.io.IOException: resource not found on classpath: version.json
Loading config from class loader sun.misc.Launcher$AppClassLoader@647e05 but there were no resources called version.properties
exception loading version.properties: java.io.IOException: resource not found on classpath: version.properties
Loading config from a String resizer.enabled=on
Dispatcher Config: Config(SimpleConfigObject({"executor":"fork-join-executor","fork-join-executor":{"parallelism-factor":2,"parallelism-max":10,"parallelism-min":2},"type":"Dispatcher"}))
Exception in thread "main" com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'dispatcher'
at com.typesafe.config.impl.SimpleConfig.findKeyOrNull(SimpleConfig.java:152)
at com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:170)
at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:184)
at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:189)
at com.typesafe.config.impl.SimpleConfig.getString(SimpleConfig.java:246)
at akka.stream.ActorMaterializerSettings$.apply(ActorMaterializer.scala:267)
at akka.stream.ActorMaterializerSettings$.apply(ActorMaterializer.scala:258)
at org.jio.jnpm.WebServer$.main(WebServer.scala:31)
at org.jio.jnpm.WebServer.main(WebServer.scala)
Code run fine in IDE but not using jar file. It is looking for keyword dispatcher not sure where its is looking
Your assembly strategy is bad:
assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case "application.conf" => MergeStrategy.concat
case _ => MergeStrategy.first
}
Remove this assembly / assemblyMergeStrategy
section in build.sbt
(then the default assembly strategy will be applied) and then
sbt clean
sbt assembly
java -jar ./target/scala-2.11/JNPM_SCALA_DATA_API-assembly-0.1.0-SNAPSHOT.jar
should work.
The default sbt-assembly
strategy is
val defaultMergeStrategy: String => MergeStrategy = {
case x if Assembly.isConfigFile(x) =>
MergeStrategy.concat
case PathList(ps @ _*) if Assembly.isReadme(ps.last) || Assembly.isLicenseFile(ps.last) =>
MergeStrategy.rename
case PathList("META-INF", xs @ _*) =>
(xs map {_.toLowerCase}) match {
case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) =>
MergeStrategy.discard
case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") =>
MergeStrategy.discard
case "plexus" :: xs =>
MergeStrategy.discard
case "services" :: xs =>
MergeStrategy.filterDistinctLines
case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
MergeStrategy.filterDistinctLines
case _ => MergeStrategy.deduplicate
}
case _ => MergeStrategy.deduplicate
}
https://github.com/sbt/sbt-assembly/blob/develop/README.md#merge-strategy
For debugging you can use the strategy
assembly / assemblyMergeStrategy := (_ => MergeStrategy.singleOrError)
to see all duplicates:
[error] SingleOrError found multiple files with the same target path:
[error] Jar name = akka-actor_2.11-2.4.20.jar, jar org = com.typesafe.akka, entry target = reference.conf
[error] Jar name = akka-http-core_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = reference.conf
[error] Jar name = akka-http_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = reference.conf
[error] Jar name = akka-stream_2.11-2.4.20.jar, jar org = com.typesafe.akka, entry target = reference.conf
[error] Jar name = ssl-config-core_2.11-0.2.1.jar, jar org = com.typesafe, entry target = reference.conf
[error] SingleOrError found multiple files with the same target path:
[error] Jar name = akka-actor_2.11-2.4.20.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = akka-http-core_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = akka-http-spray-json_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = akka-http_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = akka-parsing_2.11-10.0.15.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = akka-stream_2.11-2.4.20.jar, jar org = com.typesafe.akka, entry target = META-INF/MANIFEST.MF
[error] Jar name = config-1.3.0.jar, jar org = com.typesafe, entry target = META-INF/MANIFEST.MF
[error] Jar name = ssl-config-core_2.11-0.2.1.jar, jar org = com.typesafe, entry target = META-INF/MANIFEST.MF
[error] Jar name = spray-json_2.11-1.3.4.jar, jar org = io.spray, entry target = META-INF/MANIFEST.MF
[error] Jar name = reactive-streams-1.0.0.jar, jar org = org.reactivestreams, entry target = META-INF/MANIFEST.MF
[error] Jar name = scala-java8-compat_2.11-0.7.0.jar, jar org = org.scala-lang.modules, entry target = META-INF/MANIFEST.MF
[error] Jar name = scala-parser-combinators_2.11-1.0.4.jar, jar org = org.scala-lang.modules, entry target = META-INF/MANIFEST.MF
[error] Jar name = scala-library-2.11.12.jar, jar org = org.scala-lang, entry target = META-INF/MANIFEST.MF
So your duplicates are several reference.conf
and META-INF/MANIFEST.MF
files. Apparently, using MergeStrategy.first
for reference.conf
you removed dispatcher
somewhere. That was the reason of error.
When the above default strategy is not enough it's better to express custom strategy partially reusing the default one:
assembly / assemblyMergeStrategy := {
case ... => ... // additional cases
case x =>
// default strategy
val oldStrategy = (assembly / assemblyMergeStrategy).value
oldStrategy(x)
}
The minimal strategy closest to yours is
assembly / assemblyMergeStrategy := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case "reference.conf" => MergeStrategy.concat
case _ => MergeStrategy.singleOrError
}
Using custom strategies inaccurately (for example using MergeStrategy.discard
, MergeStrategy.first
/MergeStrategy.last
not selectively) can lead to many (sometimes weird) issues:
SBT assembly output 0xEFBFBD instead of 0xCAFEBABE in class file
Drools fat jar nullpointer KieServices