I am using https://github.com/julianpeeters/avrohugger sbt plugin to generate Scala case classes for Avro .avsc files. How can I use the same plugin in a Gradle project?
I created gradle plugin for generating Scala case classes from Avro schema and it internally uses avrohugger library.
So now it's enough to add this plugin to your project:
plugins {
id 'com.zlad.gradle.avrohugger' version '0.2.1'
}
When you want to compile Scala sources you need Scala library dependency too:
plugins {
id 'scala'
id 'com.zlad.gradle.avrohugger' version '0.2.1'
}
repositories {
mavenCentral()
}
dependencies {
compile 'org.scala-lang:scala-library:2.12.8'
}
Scala classes will be automatically generated during build before compileScala task. By default avro schema should be in src/main/avro and generated sources will be in build/generated-src/avro
You can call generateAvroScala to invoke Scala sources generation manually.
You can find all details and configuration options on gradle-avrohugger-plugin github page.
I ended up using the avrohugger-tools library in Gradle to autogenerate Scala case classes whenever my schemas were updated. Your mileage may vary, but this finally worked for me:
build.gradle.kts
import java.io.File
plugins {
scala
id("com.github.maiflai.scalatest") version "0.19"
}
version = "1.0"
configurations {
register("avrohugger-tools")
}
dependencies {
// Scala std-libs
implementation(Dependencies.Libs.Scala.library)
// AvroHugger tools JAR
"avrohugger-tools"("com.julianpeeters:avrohugger-tools_2.12:1.0.0-RC14")
// testing
testImplementation(gradleTestKit())
testImplementation("junit:junit:4.12")
testImplementation("org.scalatest:scalatest_2.12:3.0.5")
testRuntime("org.pegdown:pegdown:1.4.2")
}
fun normalizeFileSeparator(path: String) = path.replace('/', File.separatorChar)
val genAvro = task<JavaExec>("genAvro") {
val sourceAvroPath = normalizeFileSeparator("src/main/avro/")
val sourceAvroFiles = fileTree(mapOf(
"dir" to sourceAvroPath, "include" to listOf("**/*.avsc")
))
val targetPath = normalizeFileSeparator("src/gen/")
doFirst {
delete(targetPath)
}
classpath = configurations["avrohugger-tools"]
main = "avrohugger.tool.Main"
args(
"generate", "schema",
sourceAvroFiles.files.joinToString(separator=" "),
targetPath
)
inputs.files(sourceAvroFiles)
outputs.files(targetPath)
}
the<JavaPluginConvention>().sourceSets.getByName(
SourceSet.MAIN_SOURCE_SET_NAME
).java.srcDir("gen")
tasks.withType<ScalaCompile> {
dependsOn(genAvro)
}
inline fun <reified T : Task> TaskContainer.existing() = existing(T::class)
inline fun <reified T : Task> TaskContainer.register(name: String, configuration: Action<in T>) = register(name, T::class, configuration)
Note that I'm also building/test a Scala source tree in this package, so some of the Scala-specific pieces can be presumably elided.
Really hope this helps!
Related
I convert a project that was originally written in Scala into kotlin. It is a typical backend - frontend-design with the backend written in Scala and the Frontend in Angular (the code was written by a former co-worker who is no longer working in this project)
During the gradle-build, the e2e-tests are evaluated. For this purpose the backend is compiled in the following way:
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.scala.ScalaCompile
class ScalaCompilerPlugin implements Plugin<Project> {
void apply(Project project) {
project.configurations {
scalaCompilerPlugin
}
project.afterEvaluate {
project.tasks.withType(ScalaCompile) {
options.encoding = 'UTF-8'
if (scalaCompileOptions.additionalParameters == null) {
scalaCompileOptions.additionalParameters = []
}
scalaCompileOptions.additionalParameters <<
"-Xplugin:" + project.configurations.scalaCompilerPlugin.asPath
}
}
}
}
The 'scalaCompilerPlugin'-plugin is then added to the build.gradle-file in the backend.
plugins {
id 'scala'
id 'com.github.psxpaul.execfork' version '0.1.12'
}
apply plugin: ScalaCompilerPlugin
// ...
Since now the project is converted to Kotlin/Ktor I plan to use something like a KotlinCompiler-plugin for the same purpose, but in gradle 6.0.1, there seems to be no such plugin, and not being that firm with gradle I don't know how to add org.jetbrains.kotlin.gradle.tasks.KotlinCompile.
How can I achieve the same and start the backend during the gradle-build to run the e2e-tests during the test-runs? I am also open to suggestions to change this design.
Considering that Java 1.9 is now out for some time, i am still amazed how difficult it is to get a 1.9 project up and running with eclipse and buildship.
I now spend 2 days trying to get this flying and came very far but one issue is something i just get not off the ground:
"Right click on JUnit test case and 'Run as...'".
It always ends in a java.lang.module.FindException and i have to override the command line as described in Eclipse cannot find module even the module path is explicitly provided.
On top comes this whole "eclipse.classpath.file.whenMerged" stuff in the build.gradle file (my file see below).
Hence my question is two-fold:
Have i missed something that makes the jigsaw support with Gradle and buildship more easy?
What do I have to do to not patch the command line manually (as described in the link above)?
As I am currently evaluating the support of Eclipse/Gradle/Buildship for my team I need to have the second question fixed. Otherwise the developer in my team are going to get nuts. As such I am also contemplating to move away from Eclipse.
Side question: How good is the support in other IDE for modules and Gradle?
I am using
Eclipse 2020-12 (4.18.0.v20201202-1800)
Eclipse Plug-ins for Gradle 3.1.4.v20200326-1743
Java 12
Grade 6.7.1
Thank you
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java library project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/6.7.1/userguide/building_java_projects.html
*/
plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
id 'eclipse'
id 'application'
}
sourceCompatibility = targetCompatibility = '1.12'
repositories {
// Use JCenter for resolving dependencies.
jcenter()
}
dependencies {
// Use JUnit test framework.
testImplementation 'junit:junit:4.13'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'org.postgresql:postgresql:42.2.18'
}
java {
modularity.inferModulePath = true
}
application {
mainModule = 'com.myproduct.mod.lib' // name defined in module-info.java
mainClass = 'com.myproduct.mod.lib.Library'
}
eclipse {
classpath {
file {
whenMerged {
//Define a module as being either a library or a project dependency.
//Test sources are excluded because eclipse wants them on the classpath for some reason (1)
entries.findAll { (it instanceof org.gradle.plugins.ide.eclipse.model.Library || it instanceof org.gradle.plugins.ide.eclipse.model.ProjectDependency) && !it.entryAttributes.get('gradle_used_by_scope').equals('test') }.each {
it.entryAttributes['module'] = 'true'
}
//Test-scoped stuff should set the appropriate flag
entries.findAll { (it.properties.kind.equals('src') || it.properties.kind.equals('lib')) && it.entryAttributes.get('gradle_used_by_scope').equals('test') }.each {
it.entryAttributes['test'] = 'true'
}
entries.findAll { isConGradle(it) }.each {
it.entryAttributes['module'] = 'true'
}
}
}
}
}
boolean isConGradle(entry) {
entry.kind == 'con' && entry.path == 'org.eclipse.buildship.core.gradleclasspathcontainer'
}
I'm using gradle and eclipse plugin. I've got two projects A and B (B depends on A).
in build.gradle of B, dependency on A is declared as :
dependencies {
compile files(classes_output_dir_of_A)
}
I'm trying to have on eclipse the sources lookup when browsing in B project classes of A project.
I've seen on web some solutions like:
eclipse {
classpath {
file {
whenMerged {
def lib = entries.find [...]
lib.sourcePath = [...]
}
}
}
}
but this do not work for me since B relies on classes from A (instead of jar file)
Could you help me please?
I'm answering myself, in facts this solution works:
def a_project = entries.find { it.path.contains "A" }
I am trying to generate the QueryDSL Q classes for my Mongo entities using gradle in a Spring Boot project. The IDE I'm using is Intellij.
The code I'm using is adapted from this topic Generating JPA2 Metamodel from a Gradle build script:
sourceSets {
generated {
java {
srcDirs = ['src/generated/java']
}
}
}
configurations {
querydslapt
}
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", "org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor"
]
destinationDir = sourceSets.generated.java.srcDirs.iterator().next()
}
compileJava {
dependsOn generateQueryDSL
source generateQueryDSL.destinationDir
}
compileGeneratedJava {
dependsOn generateQueryDSL
options.warnings = false
classpath += sourceSets.main.runtimeClasspath
}
clean {
delete sourceSets.generated.java.srcDirs
}
idea {
module {
downloadJavadoc = true
downloadSources = true
generatedSourceDirs += file('src/generated/java')
}
}
The problem is that in the end in Intellij I have 3 modules. Main, test and generated. The test and generated modules are dependent on the main module. I would like also for the main module to be dependent on the generated module since I'm using the generated Q classes in my code.
All my attempts to solve this end up in a cyclic dependency error from Gradle.
Can someone give me some tips what I could try to solve this problem.
Thanks!
In my build.gradle file I have the following:
...
dependencies {
...
testCompile (group: 'org.uncommons', name: 'reportng', version: '1.1.2') { exclude group: 'org.testng', module: 'testng' }
...
}
...
reportng needs velocity-1.4.jar and velocity-dep-1.4.jar, and actually the above testCompile dependency causes these 2 JARs to be fetched and to be placed into the Eclipse's .classpath file, as "exported" (that is, their checkboxes in the "Order and Export" tab of Eclipse's "Java Build Path" dialog are checked).
The fact that these 2 JARs get set as exported is a problem. I need them to still be fetched but not to be exported.
From the Gradle doc I understand that this is done by using noExportConfigurations as per their example:
apply plugin: 'java'
apply plugin: 'eclipse'
configurations {
provided
someBoringConfig
}
eclipse {
classpath {
//if you don't want some classpath entries 'exported' in Eclipse
noExportConfigurations += configurations.provided
}
}
My problem is that I don't have a configurations {} section, and while I can certainly add one, I don't know what to put in it in order to exclude from export not the whole reportng but just two of the JARs that come with it.
You'll probably want something like:
configurations {
noExport
}
dependencies {
// replace with correct values
noExport "foo:velocity:1.4"
noExport "foo:velocity-dep:1.4"
}
eclipse {
classpath {
noExportConfigurations += configurations.noExport
}
}
PS: Please don't double-post here and on http://forums.gradle.org.
Apparently, in the year and a half that has gone by since Peter's answer, noExportConfigurations is deprecated and slated to be removed in Gradle 3.0. What's more, none of the solutions in the linked Gradle forum thread allow me to remove a dependency imported from a folder, like war/WEB-INF/lib, for instance.
So after much research, I stumbled upon an example here at the end of this build.gradle file in GitHub, which reorders entries in the classpath:
withXml { xml ->
def node = xml.asNode()
node.remove( node.find { it.#path == 'org.eclipse.jst.j2ee.internal.web.container' } )
node.appendNode( 'classpathentry', [ kind: 'con', path: 'org.eclipse.jst.j2ee.internal.web.container', exported: 'true'])
}
I modified the example so that it simply removes a JAR file using the regex capabilities of the Groovy Node. Note that the xml -> part is not needed, and that this entry is a child of the file closure:
withXml {
def node = it.asNode()
node.remove( node.find { it.#path ==~ /.*velocity-1\.4\.jar/ } )
node.remove( node.find { it.#path ==~ /.*velocity-dep-1\.4\.jar/ } )
}