Gradle init project for Scala application - scala

I want to create a skeleton console app for Scala i.e. a single entry class with a main function that prints "Hello world".
I was able to create a Scala library init project by executing:
gradle init --type scala-library
however there seems to be no scala-application, running:
gradle init --type scala-application
The requested build setup type 'scala-application' is not supported. Supported types: 'basic', 'groovy-application', 'groovy-library', 'java-application', 'java-library', 'pom', 'scala-library'.
Is there no Scala console app template for Gradle?

No, there is no scala application template, however it is easy to make your generated "scala-library" project into a scala application in two steps:
Create your main class and method under a package under src/main/scala
Add two lines to your gradle.build, to add the 'application' plugin and specify your main class.
For example, you add src/main/scala/com/example/myapp/Main.scala:
package com.example.myapp
object Main {
def main(args: Array[String]): Unit = {
println("Hello")
}
}
Then to your gradle.build you add:
apply plugin: 'application'
mainClassName='com.example.myapp.Main'

On top of what you have for Java you pretty much only need to add apply plugin: 'scala' and change Main to be:
object Main extends App {
println('Hello, World!')
}
I ended up doing just that.
Additionally, if you want joint compilation (and have compiler understand Java and Scala in the same place) you can add the below snippet (one block per source set: main, test, jmh, etc.):
sourceSets.main {
java.srcDirs = []
scala.srcDirs = ['src/main/scala', 'src/main/java']
scala.include '**/*.*'
}
sourceSets.test {
java.srcDirs = []
scala.srcDirs = ['src/test/scala', 'src/test/java']
scala.include '**/*.*'
}

As of Gradle 6.7 the scala-application build type exists now.

Related

How to create new commands that you can run after running the sbt command Scala

I'm trying to run certain tasks and startup servers after running sbt. I want to be able to run commands in terminal to do this. How can I define them? Are plugins the right way to do this:
I see some code like this:
object DoThing extends AutoPlugin {
object autoImport {
val vpnCheck = taskKey[Boolean]("Check for a VPN connection.")
}
import autoImport._
override lazy val projectSettings = Seq(
vpnCheck := {
doVpnCheck()
}
)
What is the projectSettings method doing? Are plugins the way?
From the plugins page:
A plugin is a way to use external code in a build definition. A plugin can be a library used to implement a task (you might use Knockoff to write a markdown processing task). A plugin can define a sequence of sbt settings that are automatically added to all projects or that are explicitly declared for selected projects. For example, a plugin might add a proguard task and associated (overridable) settings. Finally, a plugin can define new commands (via the commands setting).
But I can't seem to figure this out.
For your scenario, maybe you can just a create Task in sbt file to do this, like:
val hello = taskKey[Unit]("hello world")
hello := {
println("hello")
}
and if you run it automatically in startup time, you can create .sbtrc file in project directory, and it like:
alias boot = ;reload ;hello ;iflast shell

Kotlin setup via gradle on eclipse

Struggling to get Kotlin running on eclipse.
I've started new graddle project. Added dependencies as prescribed on kotlin's site.
Build passes without errors.
I've created 'main.kt' file under src/java/main with:
fun main(args: Array<String>) {
println("foo")
}
BUT, I have two problems:
1. anything from kotlin e.g. println highlighted as 'unresolved reference'.
2. I can't run a program - Error: Could not find or load main class MainKt (rightclick on main.kr run as 'kotlin application')
If I create 'new kotlin project' everything works.
my graddle build script:
plugins {
id "org.jetbrains.kotlin.jvm" version "1.1.2-2"
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
//api 'org.apache.commons:commons-math3:3.6.1'
implementation 'com.google.guava:guava:21.0'
testImplementation 'junit:junit:4.12'
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.2-2"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
compile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"
}
sourceSets {
main.java.srcDirs = ['src/main/java']
main.kotlin.srcDirs = ['src/main/java', 'src/main/kotlin']
main.resources.srcDirs = ['src/main/resources']
}
What did I do wrong?
I've zero Java knowledge if that helps, so probably I've made some trivial error.
UPDATE:
Installed a Spring plugin and generated a new web app via it including gradle.
But Kotlin behaves unpredictably there too.
At first I was not able to run it as run as Kotlin application and it errored with main could not be found, BUT sometimes it run and crashed immediately. It started to launch and crash after I've deleted and edited classes, tried creating it under other package, removing and adding Kotlin (I can't reproduce sequence to make it work again).
Fun part that gradle boot build launches everything and all works it somehow finds Kotlin's main.
Probably some issue with Kotlin plugin itself (it's load probably depends on certain events that doesn't always fire)
Add the following to your configuration:
apply plugin: 'eclipse'
eclipse {
classpath {
containers 'org.jetbrains.kotlin.core.KOTLIN_CONTAINER'
}
}
See https://gitlab.com/frnck/kotlin-gradle-eclipse for a working configuration.
I'd like to add to frnck answer that this is only part of the solution. I also had to add these lines:
eclipse.project {
buildCommand 'org.jetbrains.kotlin.ui.kotlinBuilder'
natures 'org.jetbrains.kotlin.core.kotlinNature'
natures 'org.eclipse.jdt.core.javanature'
linkedResource name: 'kotlin_bin', type: '2', locationUri: 'org.jetbrains.kotlin.core.filesystem:/aio/kotlin_bin'
}
For Eclipse 2018-12 and kotlin 1.3 the solution was a combination of other answers plus some additional settings file:
eclipse {
classpath {
//Adds the kotlin container to the classpath
containers 'org.jetbrains.kotlin.core.KOTLIN_CONTAINER'
//Fixes the right output path
defaultOutputDir = file('bin')
//Make all src folders output in the same output folder (default)
file {
whenMerged {
// use default Output for all source-folders. see also defaultOutputDir per project
entries.each { source ->
// only Source-folders in the project starting with '/' are project-references
if (source.kind == 'src' && !source.path.startsWith('/')) {
source.output = null
}
}
}
}
}
project{
buildCommand 'org.jetbrains.kotlin.ui.kotlinBuilder'
//Fixes the natures
natures 'org.jetbrains.kotlin.core.kotlinNature'
natures 'org.eclipse.jdt.core.javanature'
//Links the kotlin_bin folder (generated class files)
linkedResource name: 'kotlin_bin', type: '2', locationUri: "org.jetbrains.kotlin.core.filesystem:/${project.name}/kotlin_bin".toString()
file{
whenMerged{
def kotlinPrefs = file('.settings/org.jetbrains.kotlin.core.prefs')
def jdkHome = System.properties.'java.home'
if(!(jdkHome)){
throw new GradleException('No JDK home available for setting up Eclipse Kotlin plugin, setup env "java.home" or update this script.')
}
kotlinPrefs.write """\
codeStyle/codeStyleId=KOTLIN_OFFICIAL
codeStyle/globalsOverridden=true
compilerPlugins/jpa/active=true
compilerPlugins/no-arg/active=true
compilerPlugins/spring/active=true
eclipse.preferences.version=1
globalsOverridden=true
jdkHome=$jdkHome
""".stripIndent()
}
}
}
}
I would like to add to Felipe Nascimento's answer that the location of the .settings folder does not yet exist. It works when the line below is inserted into that answer.
def kotlinPrefs = file("../${project.name}/.settings/org.jetbrains.kotlin.core.prefs".toString())
I have found that the JAVA_HOME environment variable that is set when your run this task ;
gradle cleanEclipse eclipse
is the one that is included in the Eclipse BuildPath

Compile scala code mix with java code

I need to compile a scala code which calls a java code from it.
What I did:
1]I have a scala main file check.scala
package com.code
class check {
var Rectvalue = Array.ofDim[Int](5)
val str = Array.ofDim[String](1)
def nativeacces(arg: String, loop: Integer) {
val test = new testing()
test.process(arg, Rectvalue,str)
}
}
2.For creating instance val test = new testing() ,i added two .class(sample.class,testJNI.class) file from java source code inside the folder(package) com/code.
3.When I compile the scala code using
scalac check.scala
It generates the class file for the scala file.
What I have to do:
1.Instead of .class(sample.class,testJNI.class) file added inside the package ,i need to add jar file.
2.I tried, created jar file for the .class file and compile the Scala, it shows the error:
scala:6: error: not found: type testing
val test = new testing()
3.I need to link the .jar file and compile the scala main file
You can reference classes/directories/JARs via classpath option:
scalac -classpath your.jar check.scala
Related question: Adding .jar's to classpath (Scala).
If you want a proper build use SBT, put your JAR in lib directory in the root of project and it will figure out what to do for you. Here is Hello World of SBT.

Scala/JOGL error in Eclipse: Missing Dependencies while loading X (GLCanvas etc.)

I am trying to use JOGL with Scala in Eclipse, but being a JOGL/Scala neophyte, have run into some dependency errors which I cannot make any heads or tails of. Googling hasn't returned much of anything useful.
I have set up a Java JOGL project as per
Setting_up_a_JogAmp_project_in_your_favorite_IDE.
Compiling the following Java class in a Java project that depends on the above project
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
public class Game {
public static void main(String[] args) {
GLProfile glp = GLProfile.getDefault();
GLCapabilities caps = new GLCapabilities(glp);
GLCanvas canvas = new GLCanvas(caps);
System.out.println("Hello World");
}
}
works, and outputs Hello World as expected.
However, making a Scala project and trying to use the JOGL project as follows
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.awt.GLCanvas;
object Game {
def main (args: Array[String]): Unit = {
val glp = GLProfile.getDefault();
val caps = new GLCapabilities(glp);
val canvas : GLCanvas = new GLCanvas(caps);
System.out.println("Hello World");
}
}
won't even compile, as Eclipse informs me of the following errors:
error while loading CapabilitiesImmutable, Missing dependency 'class com.jogamp.common.type.WriteCloneable', required by G:\Eclipse\workspace\JOGL\jogl-all.jar(javax/media/nativewindow/CapabilitiesImmutable.class) Scala JOGL Unknown Scala Problem
error while loading GLCanvas, Missing dependency 'class com.jogamp.common.util.locks.RecursiveLock', required by G:\Eclipse\workspace\JOGL\jogl-all.jar(javax/media/opengl/awt/GLCanvas.class) Scala JOGL Unknown Scala Problem
error while loading GLContext, Missing dependency 'class
com.jogamp.common.util.locks.RecursiveLock', required by G:\Eclipse\workspace\JOGL\jogl-all.jar(javax/media/opengl/GLContext.class) Scala JOGL Unknown Scala Problem
Removing the lines pertaining to GLCapabilities and GLCanvas, giving
object Game {
def main (args: Array[String]): Unit = {
val glp = GLProfile.getDefault();
System.out.println("Hello World");
}
}
does compile and print Hello World.
My questions are - Why doesn't the Scala code work, and what can I do to fix it? Am I doing some crazy voodoo mixing up JOGL and Scala code that I shouldn't be doing? Did I forget to add some dependencies?
Version Information
Eclipse: (Version: Juno Release Build id: 20120614-1722)
Scala IDE for Eclipse: (Version: 2.1.0.nightly-2_09-201208290312-cc63a95)
(Provider: scala-ide.org)
JOGL as part of JOGAMP Release 2.0-rc10
Edit:
Ok, adding the gluegen-rt.jar and jogl.jar libraries to the build path in the Scala project itself solves this issue (I can't believe I didn't think of doing that first .. ). I'm still not exactly sure what I was doing wrong though.
Just for reference, in one of my JOGL SBT projects, I needed to add:
gluegen-rt.jar
gluegen-rt-natives-.jar
jogl-all-2.0-rc9.jar
jogl-all-2.0-rc9-natives-.jar
to the list of dependencies in order for this to work. My guess is that you have to include these on the build path in Eclipse.
These are available from this repository: http://jogamp.org/deployment/maven

Generate .jar from scala

I'm developing an application on Eclipse with Scala and a would like to create a .jar. I have found tuto to do that, but it use the package scala.tools.nsc and I don't know where I can found this thing.
I have tried too, to generate the .class and then with the command jar cmf .... to generate the .jar but when I launch the .jar an error occur. (NoClassFound)
With sbt I have tried too, but when I compile my project that work with eclipse a lot of error appear.
Somebody can me explain how I can simply create a .jar with Eclipse or another tools.
Eclipse has a build-in option to generate runnable jars, but it is well hidden. Also it does not recognize Scala's main() signatures, so you will have to create a Java class with a main() method.
Create a Java class with a main() method which simply forwards the call to your Scala code.
Then right click on your newly created Java class and select: Run As -> Java Application.
This will create a runnable configuration which will later be used as a part of your runnable jar.
Now you are ready to dig out the runnable jar option from the Eclipse's menu:
File -> Export -> Java -> Runnable JAR file
In the presented dialog select the Launch Configuration you have created earlier (in step2), name your jar (myapp.jar), select your dependency export options and click finish.
The jar will be created in the Eclipse's workspace by default.
Run the jar using the line: scala myapp.jar
Your question about missing images: Eclipse requires a manual refresh when files are added or removed. Right click on your project and select Refresh.
This concludes the tutorial on the highly intuitive Eclipse interface.
Note: Instructions for Eclipse version 3.6.2.
Jars
When you create a jar out of your classes, possibly the dependencies are not included in that jar. When running that jar, you need to put the jars containing the dependencies on the classpath (with the -cp switch to java). Most important dependency is the scala-library jar. Of course knowing what is not found by NoClassDefFound would help.
Sbt
When building with sbt, maybe it is missing dependencies that you have manually added to the Eclipse project? (Note: I did not use sbt).
Maven
I found the clearest and most painless way is to go with maven alone, or possibly maven + Intellij Idea (community edition is free) + Scala Plugin. Works very smooth.
For maven, you need to adapt the available scala archetype a bit since the libraries it refers to are not the most recent version, but apart from that it is very fine.
Here is a pom.xml I'm using: https://gist.github.com/1096870
Use the standard maven folder structure (source root is src/main/scala) and then mvn package creates the jar fine.
Use the below steps for time being .But this is not the full time solution.Better to go for sbt build jar for Spark-Scala combination.
Temporary solution using java class ,calling the scala main class.
MainClass.java
public class MainClass {
public static void main(String[] args) {
SampleApp app=new SampleApp();
app.main(args); }
}
SampleApp.scala
class SampleApp {
def main(args: Array[String]) {
println("First Scala SampleApp")}
}
Export it as a jar by using normal java jar export by choosing the MainClass main method.
name the jar file as Sample.jar
Run it in the Cluster using below command.
/spark/bin/spark-submit --class com.scala.MainClass SampleScala.jar
The output you can get as:
First Scala SampleApp
% cat a.scala
package foo
object Whee {
def main(args: Array[String]): Unit = {
println("I'm in a jar")
}
}
% scalac29 -d whee.jar a.scala
% scala29 -cp whee.jar foo.Whee
I'm in a jar
%
To build off of what #Kumar Basapuram wrote:
Make a java class called "Wrapper.java".
package animals;
public class Wrapper {
public static void main(String[] args) {
SampleApp app=new SampleApp();
app.main(args);
}
}
Link this main method to the main method in the "SampleApp.scala" class.
package animals
class SampleApp {
def main(args: Array[String]){
var c = new Cow("Bessie", 100)
println(c.speak)
var h = new Horse("CJ", 50)
println(h.speak)
var s = new Sheep("Little Lamb", 25)
println(s.speak)
println(s.weigh)
println(h.weigh)
println(c.weigh)
}
}
Project with Java and Scala Classes Picture
Right Click on the Project ScalaPracticeCreation.
Click Export...
Click Runnable JAR file under the Java folder
Exporting Scala Class into a jar Executable Picture
Click Next >
Select Wrapper - ScalaPracticeCreations
Select Export destination to a place on your computer
Select "Extract required libraries into generated JAR" under the "Library
handling:" option
Click Finish
Run the file through the Eclipse IDE and it works.
Run it through the Command Prompt and it does not work.
Command Prompt Picture
To fix this remove the println methods from the "SampleApp.scala".
package animals
class SampleApp {
def main(args: Array[String]) {
var c = new Cow("Bessie", 100)
var h = new Horse("CJ", 50)
var s = new Sheep("Little Lamb", 25)
c.weigh().toString()
}
}
add "System.out.println(app.main(args));" to replace "app.main(args);" in the Wrapper.java class
package animals;
public class Wrapper {
public static void main(String[] args) {
SampleApp app=new SampleApp();
System.out.println(app.main(args));
}
}
Now reexport the program after running it.
success in the command prompt Picture
Now it works.
Here are the extra filler .scala classes. Note that the Demo.scala class is irrelevant.
Weight.scala:
package animals
abstract class Weight(size: Int) {
def weigh = "My size is " + size
}
Animal.scala:
package animals
abstract class Animal(name: String, weight: Int) extends Weight(weight){
def speak = name + " says " + sound
def sound: String
override def weigh() = "My name is " + name + " and I weigh: " + weight
}
Cow.scala:
package animals
class Cow (name: String, weight: Int) extends Animal(name,weight){
override def sound() = "mooooo"
}
Horse.scala:
package animals
class Horse (name: String, weight: Int) extends Animal(name,weight){
override def sound() = "neigh"
}
Sheep.scala:
package animals
class Sheep (name: String, weight: Int) extends Animal(name,weight) {
override def sound() = "baaaa"
}
Note that this may not be the best solution although it is a functional solution. Scala sbt may be a better solution: Scala sbt or this Scala sbt-assembly.