How to call a scala method from build.gradle file - scala

I have just started working on the scala and gradle. I want to know how we can call any scala method from the gradle build file. Can somebody please help me?
From comment: I want to run multiple files present in a directory. So in order to get all the files in the directory, I have written a method in scala. That method I am trying to call from build.gradle file

Gradle allows to specify dependencies of build script itself inside buildscript{ dependencies { ... } } (not to be confused with project dependencies inside ordinary dependencies { ... }).
For example here I added Shapeless dependency and used an HList in build.gradle
build.gradle
buildscript{
dependencies {
classpath group: 'com.chuusai', name: 'shapeless_2.13', version: '2.4.0-M1'
}
}
plugins {
id 'java'
id 'scala'
id 'application'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
// compile group: ...
}
application {
mainClassName = 'App'
}
import shapeless.*
task hello {
doLast {
HList l = new $colon$colon(1, new $colon$colon("a", new HNil$()))
println l
}
}
Terminal
$ ./gradlew hello
Output
> Task :hello
1 :: a :: HNil
BUILD SUCCESSFUL in 457ms
1 actionable task: 1 executed
So you can compile your Scala sources, package classes into jar, publish it locally and specify your local dependency in
buildscript{
dependencies {
classpath group: 'yourOrganization', name: 'yourArtifact', version: 'yourVersion'
}
}
and then call methods from your Scala code in build.gradle.

Related

Gradle-Scala Project Error - Could not load Main Class

I have created a gradle/scala project in intellij.
This is my project structure
build
gradle
- wrapper
META-INF
out
src
- main
-resources
-scala
- test
-resources
-scala
build.gradle
gradlew
gradlew.bat
settings.gradle
These are the contents of my build.gradle file
plugins {
id 'scala'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenLocal()
maven {
url = uri('<artifactory location>')
}
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'org.example.Hello'
)
}
}
sourceCompatibility = '12'
dependencies {
implementation 'org.scala-lang:scala-library:2.12.14'
testImplementation 'org.scalatest:scalatest_2.12:3.0.5'
testRuntimeOnly 'org.scala-lang.modules:scala-xml_2.12:1.1.1'
}
test {
useJUnitPlatform()
}
Main Class Content
package org.example
object Hello extends App {
println("hello!")
}
When I try to build the jar and execute it , it gives an error
Could not find or load main class org.example.Hello . What might be the mistake here?
I was able to resolve the issue by adding the following in the settings.gradle
rootProject.name = 'gradle-scala'
include('gradle-scala')
Basically , the include tag is used to specify the directory where the code resides .
I see out directory, can you check the gradle settings
ensure below are ticked

gradle scalatest stay at "Discovery starting."

I have project that uses gradle, scala, scalatest and the gradle-scalatest-plugin.
I have several tests and they are compiled. But when the run part of them is executed, the gradle is stuck on "Dicovery starting." infinitely.
So I used gradle --debug test to see what is happening. But besides the status information about memory of jvm and lock acquiring, there is no information why it is stuck.
build.gradle File:
buildscript {
ext.scala_version = "2.12"
ext.akka_version = "2.5"
ext.monocle_version = "1.5.0"
ext.circe_version = "0.8+"
repositories {
mavenCentral()
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.diffplug.gradle:goomph:3.9.0"
}
}
plugins {
id "java"
id "scala"
id "com.github.maiflai.scalatest" version "0.19"
id "com.athaydes.osgi-run" version "1.5.4"
id "org.dm.bundle" version "0.10.0"
// For interoperability with Other Company Eclipse P2 Repository
id "com.diffplug.gradle.p2.asmaven" version "3.9.0"
}
group "project.scalatest"
version 0.1
repositories {
mavenCentral()
jcenter()
}
sourceSets {
test {
java {
srcDirs = ['test/main/java']
}
scala {
srcDirs = ['test/main/scala']
}
}
}
runOsgi {
bundles += project
}
bundle {
instruction '-dsannotations', '*'
}
test {
}
// Adding the Other Company Eclipse P2 project Core Repo as dependency
p2AsMaven {
group 'project', {
repo 'https://other-company.de/p2/'
iu 'de.other-company.project.core'
}
}
dependencies {
//compile fileTree(dir: 'libs', include: ['*.jar', '*.java'])
compile "org.osgi:org.osgi.core:6.0+"
compile "org.osgi:org.osgi.service.log:1.3+"
compile "org.osgi:org.osgi.service.component:1.3+"
compile "org.osgi:org.osgi.service.component.annotations:1.3+"
compile "project:de.other-company.project.core:+"
// Include the program repository code as dependency
//compile fileTree(dir: "../repository")
compile "org.scala-lang:scala-library:$scala_version+"
compile "com.typesafe.akka:akka-osgi_$scala_version:$akka_version+"
compile "io.circe:circe-core_$scala_version:$circe_version"
compile "io.circe:circe-generic_$scala_version:$circe_version"
compile "io.circe:circe-parser_$scala_version:$circe_version"
compile "io.circe:circe-optics_$scala_version:$circe_version"
compile "com.github.julien-truffaut:monocle-core_$scala_version:$monocle_version"
compile "com.github.julien-truffaut:monocle-macro_$scala_version:$monocle_version"
compile "org.slf4j:slf4j-api:1.7.+"
compile "org.slf4j:slf4j-simple:1.7.+"
compile "org.slf4j:osgi-over-slf4j:1.7.+"
testCompile "com.typesafe.akka:akka-testkit_$scala_version:$akka_version+"
testCompile "org.scalatest:scalatest_$scala_version:3.2+"
testCompile "org.scalactic:scalactic_$scala_version:3.2+"
testCompile "org.scalacheck:scalacheck_$scala_version:1.13+"
testCompile "org.mockito:mockito-core:2.+"
testRuntime "org.pegdown:pegdown:1.4+"
osgiRuntime "org.apache.felix:org.apache.felix.configadmin:1.8+"
osgiRuntime "org.apache.felix:org.apache.felix.scr:2.0+"
osgiRuntime "org.apache.felix:org.apache.felix.log:1.0+"
}
So I found the solution myself :)
I did some crappy solution to find and use files in the test.
After a research how to do it properly getClass.getResource("...") the problem went away.

W.r.t. Pass options to JPAAnnotationProcessor from Gradle

I am using Gradle version 2.14, I have made changes in build.gradle to exclude packages from JPAAnnotationProcessor as mentioned in question.
My build.gradle configuration for same as follows:
configurations {
querydslapt
}
dependencies{
compile group: 'com.querydsl', name: 'querydsl-core', version: '4.1.4'
compile group: 'com.querydsl', name: 'querydsl-apt', version: '4.1.4'
compile group: 'com.querydsl', name: 'querydsl-jpa', version: '4.1.4'
}
task generateQueryDSL(type: JavaCompile, group: 'build', description: 'Generates the QueryDSL query types') {
source =sourceSets.main.java
classpath = configurations.compile + configurations.querydslapt
options.compilerArgs = [
"-proc:only",
"-processor", "com.querydsl.apt.jpa.JPAAnnotationProcessor",
"-Aquerydsl.excludedPackages=com.projectx.data.domain.poc.lombok"
]
destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}
compileJava {
dependsOn generateQueryDSL
source generateQueryDSL.destinationDir
}
compileGeneratedJava {
dependsOn generateQueryDSL
options.warnings = false
classpath += sourceSets.main.runtimeClasspath
}
But when I am building application I getting warning as warning: The following options were not recognized by any processor: '[querydsl.excludedPackages]'
And specified packages are not excluded from preprocessing.
Found a solution!
After adding querydsl.entityAccessors=true to aptOptions warning still present, but excluding packages works!
In your case, you should try add -Aquerydsl.entityAccessors=true to options.compilerArgs =[]
hope it helps
UPDATED
Just noticed that you use lombook in your project.
Found this one ( How to make QueryDSL and Lombok work together ) Hope it could be helpful for you!

Gradle execute Groovy script in GroovyShell with Eclipse Luna

I am getting a ClassNotFoundException: org.apache.ivy.core.report.ResolveReport when executing a gradle task, which uses Grapes to resolve dependencies.
I am using Eclipse Luna 4.4.0 with a Gradle/Groovy Project having this build.gradle:
apply plugin: 'groovy'
apply plugin:'application'
mainClassName = "de.my.app.package.Main"
version = 0.5
repositories { mavenCentral() }
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.3'
compile group: 'org.apache.ivy', name:'ivy', version:'2.2.0'
compile 'commons-io:commons-io:2.4'
compile 'commons-codec:commons-codec:1.2'
}
task myTask << {
def groovyShell = new GroovyShell()
groovyShell.run(file('/src/scripts/groovy/de/my/app/package/scripts/SomeScript.groovy'))
}
classes.finalizedBy(myTask)
My Java Build Path inside Project->Properties looks like this:
This is SomeScript.groovy inside the Folder /src/scripts/groovy/de/my/app/package/scripts:
package de.my.app.package.scripts
#Grapes(
#Grab(group='org.eclipse.birt.runtime.3_7_1', module='org.apache.commons.codec', version='1.3.0')
)
#Grapes(
#Grab(group='commons-io', module='commons-io', version='2.4')
)
import org.apache.commons.codec.binary.Hex
println Hex.toString()
Weird thing is that executing SomeScript.groovy from cmd with groovy SomeScript.groovy does not give the error. So i am guessing it is some Eclipse config I have missed.
How can SomeScript.groovy be executed by the Gradle run from the build.gradle without causing a ClassNotFoundException: org.apache.ivy.core.report.ResolveReport?
I have found a solution for my problem. I needed this build.gradle file:
apply plugin: 'groovy'
apply plugin:'application'
mainClassName = "de.my.app.package.Main"
version = 0.5
repositories { mavenCentral() }
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.3'
compile group: 'org.apache.ivy', name:'ivy', version:'2.2.0'
compile 'commons-io:commons-io:2.4'
compile 'commons-codec:commons-codec:1.2'
}
task myTask (type: Exec) {
def groovyHome = System.getenv("GROOVY_HOME")
def someScriptPath= new String(project.projectDir.toString()).toString() + "\\src\\scripts\\groovy\\de\\my\\app\\package\\main\\SomeScript.groovy"
commandLine "${groovyHome}\\bin\\groovy.bat", someScriptPath
}
classes.finalizedBy(myTask)
So I abandoned the approach of using the class GroovyShell, because I could not configure the classPath for it correctly.
My Script executes now before every run. Problem is solved.

how to copy the dependencies libraries JARs in gradle

I got a runnable jar with this build.gradle
apply plugin: 'java'
apply plugin: 'application'
manifest.mainAttributes("Main-Class" : "com.test.HelloWorld")
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
but it run failed, because the dependencies jars can't find.
and then I add this code:
task copyToLib(type: Copy) {
into "$buildDir/output/libs"
from configurations.runtime
}
but nothing change. I can't find the folder output/libs.
how can I copy the dependencies libs jars to a specified folder or path?
Add:
build.dependsOn(copyToLib)
When gradle build runs, Gradle builds tasks and whatever tasks depend on it (declared by dependsOn). Without setting build.dependsOn(copyToLib), Gradle will not associate the copy task with the build task.
So:
apply plugin: 'java'
apply plugin: 'application'
manifest.mainAttributes('Main-Class': 'com.test.HelloWorld')
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
task copyToLib(type: Copy) {
into "${buildDir}/output/libs"
from configurations.runtime
}
build.dependsOn(copyToLib)
I find the application plugin way too cumbersome and too verbose in its output. Here's how I finally got a setup I was happy with, i.e., create a distribution zip file with dependency jars in subdirectory /lib and add all dependencies to Class-Path entry in the manifest file:
apply plugin: 'java'
apply plugin: 'java-library-distribution'
repositories {
mavenCentral()
}
dependencies {
compile 'org.apache.commons:commons-lang3:3.3.2'
}
// Task "distZip" added by plugin "java-library-distribution":
distZip.shouldRunAfter(build)
jar {
// Keep jar clean:
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'
manifest {
attributes 'Main-Class': 'com.somepackage.MainClass',
'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
}
// How-to add class path:
// http://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
// https://gist.github.com/simon04/6865179
}
Hosted as a gist here.
The result can be found in build/distributions and the unzipped contents look like this:
lib/commons-lang3-3.3.2.jar
MyJarFile.jar
Contents of MyJarFile.jar#META-INF/MANIFEST.mf:
Manifest-Version: 1.0
Main-Class: com.somepackage.MainClass
Class-Path: lib/commons-lang3-3.3.2.jar
Since Gradle 6.0 it is:
tasks {
val deps by registering(Copy::class) {
from(configurations.runtimeClasspath)
into("build/deps")
}
}
The problem with all the previous answers is that they only collect dependencies from one configuration. To get ALL of the dependencies, you should use this:
task saveDependencies(type: Copy){
configurations.each {
if (it.isCanBeResolved())
from it into "gradle_dependencies"
}
from buildscript.configurations.classpath into "gradle_dependencies"
}
The application plugin requires you to set the main class name like this:
mainClassName = "com.test.HelloWorld"
You will need to add that to your build script. Keep in mind that if you try to run your application with the java command you will also need to set the classpath with -cp.
The application plugin simplifies this process by providing the task distZip. If you run that task you a full distribution is created for you under build/distributions. The distribution contains start scripts and all dependencies. The generated start scripts already set the classpath for you so you don't have to deal with it anymore.
The java plugin can pack a jar with dependencies and there's no need for the application plugin. A task like the following would do:
task buildWithDeps(type: Jar) {
manifest {
attributes "Main-Class": "com.test.HelloWorld"
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
As of at least Gradle 5.6.4 you'll want to do something closer to this.
dependencies {
implementation 'my.group1:my-module1:0.0.1'
implementation 'my.group2:my-module2:0.0.1'
}
jar {
from {
configurations.compileClasspath.filter { it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
}
}
For Gradle 7.4 with Groovy:
configurations {
externalLib.extendsFrom(implementation)
}
task copyLibs(type: Copy){
from configurations.externalLib{
into '<dest-dir-name>'
exclude('<if any jars need to be excluded>')
}
}