How can I create a simple scala.js cross project with client, server and api modules? - intellij-idea

I would like to create a very simple Scala.js application with three modules under a project root like this:
project
-server
-client
-api
This is a cross project because I would like the source in the api module to be compiled by both Scala and Scala.js. I understand that this might nescessitate the need for two api modules (which share the same source code), jvm type and js type.
Source in the server module should only be compiled by Scala and source in the client module should only be compiled by Scala.js. The server module needs to depend on the api module (jvm type) whereas the client module needs to depend on the api module (js type).
Could someone please post the most basic build.sbt that shows how this can be achieved?
EDIT:
It looks like this is the way to do it:
lazy val commonSettings = Seq(
scalaVersion := "2.12.1"
)
lazy val projectRoot = project.in(file(".")).
aggregate(client, server).
settings(
name := "projectRoot"
)
lazy val server = project.in(file("server")).
settings(
commonSettings
).
dependsOn(apiJvm)
lazy val client = project.in(file("client")).
settings(
commonSettings
).
enablePlugins(ScalaJSPlugin).
dependsOn(apiJs)
lazy val api = crossProject.in(file(".")).
settings(
commonSettings
).
jvmSettings(
// Add JVM-specific settings here
).
jsSettings(
// Add JS-specific settings here
)
lazy val apiJvm = api.jvm.in(file("apiJVM"))
lazy val apiJs = api.js.in(file("apiJS"))
The only problem with this is the shared source goes into a folder called shared with a different module name in IntelliJ. It's a shame it isn't in an api folder with a module name of api. Presumably I shouldn't put any code in the apiJS and apiJVM modules that get created? They are only there to be used as dependencies?

Related

Avro generated class: Cannot access class 'Builder'. Check your module classpath for missing or conflicting dependencies

Running
val myAvroObject = MyAvroObject.newBuilder()
results in a compilation error:
Cannot access class 'MyAvroObject.Builder'. Check your module classpath for missing or conflicting dependencies
I am able to access other MyAvroObject variables. More precisely, methods such as
val schema = MyAvroObject.getClassSchema()
val decoder = MyAvroObject.getDecoder()
compiles fine. What makes it even stranger is that I can access newBuilder() in my test/ folder, but not in my src/ folder.
Why do I get a compile error when using newBuilder()? Is the namespace of the avro-schema used to generate MyAvroObject of importance?
Check your module classpath generally means, that your dependencies (which you didn't provide) are messed up. One of them should read implementation instead of testImplementation, in order to have the method available in the main source-set, instead of only the test source-set - but this may well have to do with the input classes, the output location of generated classes, or annotations alike #VisibleForTesting (just see what it even generates). Command gradlew can also list the dependencies per configuration. The builder seems to be called org.apache.avro.SchemaBuilder... there's only avro-1.11.0.jar & avro-tools-1.11.0.jar. With the "builder" design pattern, .newBuilder() tries to return inner class Builder.
had the same problem today and was able to solve it by adding the following additional source folder
<sourceDir>${project.basedir}/target/generated-sources/avro</sourceDir>
to the kotlin-maven-plugin.

Load resource file (json) in kotlin js

Given this code, where should I place the file.json to be able to be found in the runtime?
// path: src/main/kotlin/Server.kt
fun main() {
val serviceAccount = require("file.json")
}
I tried place it under src/main/resources/ without luck. I also use Gradle to compile kotlin to js with kotlin2js plugin.
Assuming the Kotlin compiler puts the created JS file (say server.js) into the default location at build/classes/kotlin/main and the resource file (file.json) into build/resources/main.
And you are running server.js by executing node build/classes/kotlin/main/server.js
According to the NodeJS documentation:
Local modules and JSON files can be imported using a relative path (e.g. ./, ./foo, ./bar/baz, ../foo) that will be resolved against the directory named by __dirname (if defined) or the current working directory.
(https://nodejs.org/api/modules.html#modules_require_id)
In our case __dirname is build/classes/kotlin/main
So the correct require statement is:
val serviceAccount = js("require('../../../resources/main/file.json')")
or if require is defined as a Kotlin function like in the question
val serviceAccount = require("../../../resources/main/file.json")
You may just use js("require('./file.json')") if you do not have import for the require function in Kotlin. The result will be dynamic, so you may cast it to Map.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.js/js.html

Kotlin Script Engine throws "unresolved reference", even if the package and class is valid

When using Kotlin's Script Engine, trying to import packages or use any class throws an "unresolved reference"
javax.script.ScriptException: error: unresolved reference: mrpowergamerbr
fun loritta(context: com.mrpowergamerbr.loritta.commands.CommandContext) {
^
This doesn't happen when running the class within IntelliJ IDEA, however it does happen when running the class on production.
While this YouTrack issue is related to fat JARs, this also can happen if you aren't using fat JARs (loading all the libraries via the startup classpath option or the Class-Path manifest option)
To fix this, or you can all your dependencies on your startup script like this:
-Dkotlin.script.classpath=jar1:jar2:jar3:jar4
Example:
java -Dkotlin.script.classpath=libs/dependency1.jar:libs/dependency2.jar:yourjar.jar -jar yourjar.jar
Or, if you prefer, set the property via code, using your Class-Path manifest option.
val path = this::class.java.protectionDomain.codeSource.location.path
val jar = JarFile(path)
val mf = jar.manifest
val mattr = mf.mainAttributes
// Yes, you SHOULD USE Attributes.Name.CLASS_PATH! Don't try using "Class-Path", it won't work!
val manifestClassPath = mattr[Attributes.Name.CLASS_PATH] as String
// The format within the Class-Path attribute is different than the one expected by the property, so let's fix it!
// By the way, don't forget to append your original JAR at the end of the string!
val propClassPath = manifestClassPath.replace(" ", ":") + ":Loritta-0.0.1-SNAPSHOT.jar"
// Now we set it to our own classpath
System.setProperty("kotlin.script.classpath", propClassPath)
While I didn't test this yet, in another unrelated answer it seems you can also supply your own classpath if you initialize the KotlinJsr223JvmLocalScriptEngine object yourself (as seen here)

Scala with spark - "javax.servlet.ServletRegistration"'s signer information does not match signer information of other classes in the same package

I have simple scala application with spark dependencies. I am just trying to create spark context using the follwing code.
def main(args: Array[String]) {
var sparkConfig : SparkConf = new SparkConf() ;
sparkConfig.setAppName("ProxySQL").setMaster("local");
var sc = new SparkContext(sparkConfig)
}
When i try to run this code inside main - it throws security execption at new SparkContext(sparkConfig) with the following message .
Exception in thread "main" java.lang.SecurityException: class "javax.servlet.ServletRegistration"'s signer information does not match signer information of other classes in the same package .
At problem tab of Eclipse, it shows one warning
Description Path Resource Location Type
More than one scala library found in the build path (D:/workspaces/scala/scalaEclipse/eclipse/plugins/org.scala-ide.scala210.jars_4.0.0.201503031935/target/jars/scala-library.jar, C:/Users/prems.bist/.m2/repository/org/scala-lang/scala-library/2.10.4/scala-library-2.10.4.jar).This is not an optimal configuration, try to limit to one Scala library in the build path. SQLWrapper Unknown Scala Classpath Problem
I have scala installation of 2.10.4 at windows machine.
Scala compiler version set at eclipse is 2.10.5 . What is causing this security exception? Is this the incompatiblity version issues or what exaclty else? How would i solve it?
The problem was more or less related with conflicting dependencies.
The following task resolve my issue.
Go to Project
Build Path -> Order and Export tab -> Change the order of
javax.servlet jar
either to bottom or top.
This Resolved the problem.
Well,as I follow the suggestion:Go to Project Build Path -> Order and Export tab -> Change the order of javax.servlet jar either to bottom or top.
I find my buidpath libiaries was changed and it seems mussy(too many small libs),maybe this was caused by maven.
So I try to remove all of them and reimport the libs and chose Project -> Maven ->Update Project !
Now ,it goes well.
The name of your object with the main method shoul be the same as the setAppName("ProxySQL"), also you can exttend it with app and do not use main method, but this is only if you want I find it easy.
package spark.sample
import org.apache.spark.{ SparkContext, SparkConf }
/**
* Created by anquegi on 18/05/15.
*/
object ProxySQL {
def main(args: Array[String]) {
var sparkConfig: SparkConf = new SparkConf();
sparkConfig.setAppName("ProxySQL").setMaster("local");
var sc = new SparkContext(sparkConfig)
}
}
I normally use and object like for using Spark
package spark.sample
import org.apache.spark.{ SparkContext, SparkConf }
/**
* Created by anquegi on 18/05/15.
*/
object ProxySQL extends App {
val sparkConfig: SparkConf = new SparkConf();
sparkConfig.setAppName("ProxySQL").setMaster("local[4]");
val sc = new SparkContext(sparkConfig)
}
I prefer to use val instead of var
You can also setMaster with .setMaster("local[4]"), and not work only with one
It means you did not exclude the Servlet APIs from some dependency in your app, and one of them is bringing it in every time. Look at the dependency tree and exclude whatever brings in javax.servlet.
It should be already available in Spark, and the particular javax.servlet JAR from Oracle has signing info that you have to strip out, or simply exclude the whole thing.
some of the libraries were mention here

Using Forms after migrating from playframework 2.0 to 2.1 RC2 (java)

I have updated my controllers with to use play.data.Form.form() method instead of Controller.form(). When I try to run my application I get errors like:
error: method render in class create_user cannot be applied to given types;
return ok(create_user.render("", Form.form(CreateUserInfo.class), creator.get()));
required: String, play.api.data.Form, User
found: String, play.data.Form, User
It looks like the my templates expect to get play.api.data.Form instead of play.data.Form. Is there suppost to be any implicit conversion or should I update my templates to use play.data.Form?
If I'm using play.data.Form in my templates I am missing out on some of the features of play.api.data.Form, like the ability to request parameters through the apply method ( ex: createUserForm("username") )
The solution was provided by Guillaume Bort at the playframework google group.
I forgot to add javaCore as a dependency for my application after updating Build.scala. You have to explicitly add javaCore as a dependency in 2.1.
val appDependencies = Seq(
javaCore
)
And remember to start using play.Project instead of PlayProject:
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
)