Creating correct Maven dependencies from Gradle - java

After some hours of search and research I came up with a working example for writing the correct Maven dependencies into the generated pom.xml when using Gradle 1.11 and maven-publish plugin.
The first problem I faced was the provided dependency that always was written as runtime into the pom.xml
The second problem was the dynamic version, that I use for minor version changes. Maven and Gradle have different notations and the maven-publish simply writes the Gradle kind of notation into the pom.xml
Here is my example:
apply plugin: 'java'
apply plugin: 'maven-publish'
group = 'de.pentos'
version = '0.4.4'
sourceCompatibility = 1.7
repositories {
mavenCentral()
mavenLocal()
}
configurations {
provided
compile.extendsFrom provided
}
dependencies {
provided("org.projectlombok:lombok:1.+")
provided("javax.servlet:javax.servlet-api:3.1.0")
compile("org.slf4j:slf4j-api:1.7+")
compile("com.fasterxml.jackson.core:jackson-databind:2.3.+")
compile("joda-time:joda-time:2.3+")
compile("org.springframework:spring-webmvc:3.2+")
compile("org.springframework.security:spring-security-web:3.1+")
testCompile("junit:junit:4.11")
}
jar { baseName = "${project.group}.${project.name}" }
publishing {
publications {
jar(MavenPublication) {
from components.java
artifactId "${project.name}"
artifact sourceJar { classifier "sources" }
pom.withXml {
final Node root = asNode()
final versionPattern = ~/(?:(.+)\.)?(.+?)\.?\+/
configurations.compile.allDependencies.each {
final name = it.name
final group = it.group
final m = versionPattern.matcher(it.version)
if (m.matches()) {
final base = m[0][1]
final rest = m[0][2].toInteger()
final version = '[' + (base ? base + '.' : '') + (rest) + ',' + (base ? base + '.' : '') + (rest + 1) + ')'
root.dependencies.first().findAll{
it.groupId.first().value()[0] == group && it.artifactId.first().value()[0] == name
}.each {
it.version.first().value = version
}
}
}
configurations.provided.allDependencies.each {
final name = it.name
final group = it.group
root.dependencies.first().findAll{
it.groupId.first().value()[0] == group && it.artifactId.first().value()[0] == name
}.each {
it.scope.first().value = 'provided'
}
}
}
}
}
}
tasks.withType(Compile) { options.encoding = 'UTF-8' }
task sourceJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
So what is my Question?
I had some trouble with a lot examples that simply compared
..findAll {
it.groupId == group
}
This hadn't worked for me and I had to find out by lot of testing how to get the findAll to work.
So is my version to detailed? Can it be written with less code?
Can I extract the functionality for dependency management into a more system wide script, that can be reused from all other projects, that need this dependency management? How?
During compileJava I get the warning :compileJavawarning: [options] bootstrap class path not set in conjunction with -source 1.7
What does this mean, and how can I fix that.

I had some trouble with a lot examples that simply compared [...]
it.groupId is not a String. You'll need something like it.groupId.value(), or perhaps it.groupId[0].value().
Can I extract the functionality for dependency management into a more system wide script, that can be reused from all other projects, that need this dependency management? How?
You can write a plugin class, and ship it to builds as a Jar. For details, see the Gradle User Guide.
During compileJava I get the warning :compileJavawarning: [options] bootstrap class path not set in conjunction with -source 1.7
What does this mean, and how can I fix that.
This question has been asked and answered many times already. See Stack Overflow or http://forums.gradle.org.
PS: Instead of rewriting Ivy to Maven version range syntax, it should be possible to use Maven syntax from the start (i.e. in the build script).

Related

Failed to apply plugin [id 'forge']

This is a continuation of this question My initial issue has been solved, but a new one came after.
Following the tutorial mentioned in it, having solved a few errors, I now get an error when I try to run .\gradlew tasks:
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\Users\benji\MinecraftWorkspace\forge-1.7.10-10.13.4.1614-1.7.10-src\build.gradle' line: 18
* What went wrong:
A problem occurred evaluating root project 'forge-1.7.10-10.13.4.1614-1.7.10-src'.
> Failed to apply plugin [id 'forge']
> You must set the Minecraft Version!
> java.lang.NullPointerException (no error message)
How do I set the Minecraft version? (1.7.10 in this instance)
Edit to include build.gradle:
buildscript {
repositories {
mavenCentral()
maven {
name = "forge"
url = "http://files.minecraftforge.net/maven"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
}
}
apply plugin: 'forge'
version = "1.0"
group= "com.yourname.modid" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "modid"
minecraft {
version = "1.7.10-10.13.4.1614-1.7.10"
runDir = "eclipse"
}
dependencies {
// you may put jars on which you depend on in ./libs
// or you may define them like so..
//compile "some.group:artifact:version:classifier"
//compile "some.group:artifact:version"
// real examples
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
//compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
// for more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
}
processResources
{
// this will ensure that this task is redone when the versions change.
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
// replace version and mcversion
expand 'version':project.version, 'mcversion':project.minecraft.version
}
// copy everything else, thats not the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
Good day.
For minecraft version 1.7.10.
I was with the same problem, searching the forum in Japanese.
this link Forum
You have to modify the repositories and dependencies of the build.gradle and change the gradle-wrapper.properties to version 5.6.4.
As indicated in this link ForgeGradle-1.2
Contains an example to modify your build.gradle example
build.gradle
buildscript {
repositories {
mavenCentral()
maven { url = "https://jcenter.bintray.com/" }
maven {
name = "forge"
url = "https://files.minecraftforge.net/maven"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath ('com.anatawa12.forge:ForgeGradle:1.2-1.0.+') {
changing = true
}
}
gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
I made it work
Sorry, my English is very basic. I'm using a translator.
pls update the plugin to latest one . For reference check this link and link.
also try deleting the .gradle folder in your User Home and run it again.
I solved this by installing the 'Recommended' version of Forge 1.7.10 instead of the 'Latest'. Simple fix really, although I've already hit another wall.

How to create JAR from specific classes and use it with Gradle?

I have few Java classes that I want to use on different projects.
I don't want to move these classes in a dedicated project for now.
So I want to build a JAR with these classes, and be able to use it in my other projects, all with Gradle.
So here my JAR task (sources) and I publish it as an artifact :
task utilitiesJar(type: Jar) {
baseName = 'utilities'
version = '0.0.1'
includeEmptyDirs = false
from sourceSets.main.allJava
include "**\\common\\exceptions\\**"
include "**\\common\\json\\**"
include "**\\common\\logging\\**"
}
publishing {
publications {
utilities(MavenPublication) {
artifact utilitiesJar
groupId group
artifactId utilitiesJar.baseName
version utilitiesJar.version
}
}
repositories {
maven {
url 'my_URL'
}
}
}
I get it back with an other project :
repositories {
mavenCentral()
maven {
url 'my_URL'
}
}
...
compile (...)
...
Seems like the JAR is correctly imported (I can see it in "External Libraries" of IntelliJ, with all its classes), but I can't use it.
Maybe because the .class files are missing ?
I'm beginner in Java, maybe I missed something.
How can I create a JAR with only some classes and then use it ?
Ok so as said in comments, I have to include the builded .class files, I can't use external .java classes like this.
So my solution :
def utilitiesName = '...'
def utilitiesVersion = '0.0.1'
task utilitiesJar(type: Jar, dependsOn: classes) {
baseName = utilitiesName
version = utilitiesVersion
includeEmptyDirs = false
from sourceSets.main.output
include ("**\\common\\exceptions\\**\\*", "**\\common\\json\\**\\*", "**\\common\\logging\\**\\*")
}
task utilitiesSourcesJar(type: Jar, dependsOn: classes) {
baseName = utilitiesName
version = utilitiesVersion
classifier = 'sources'
includeEmptyDirs = false
from sourceSets.main.allJava
include ("**\\common\\exceptions\\**\\*", "**\\common\\json\\**\\*", "**\\common\\logging\\**\\*")
}
publishing {
publications {
utilities(MavenPublication) {
artifact utilitiesJar
artifact utilitiesSourcesJar
groupId group
artifactId utilitiesName
version utilitiesVersion
}
}
repositories {
maven {
url 'myURL'
}
}
}
Now I can use it and see the classes in my IDE.
PS : doing in this way is pretty dirty. Create a sub-project / a module, it's just the way how to do it, that's finaly what I did.

Gradle - Multiple Jar from single project

Context: To create multiple executable jar's from a single project - multiple package gradle project
Issue: I refer to the solution provided in Link, this helps in generating the jar in build->libs folder, but when I try executing the jar nothing happens
Note: Even if I make the package name same as java file name, the generated jar does not execute.
Also I notice the file size of all the jar's generated is the same. Hope the issue faced is clear & await inputs as to where I am making a mistake.
My Project Structure (illustrative purpose):
ProjectA
-src
--main
---java
----pkg1
-----pkgCalculator
------Calculator.java
-----pkgScale
------Scale.java
----pkg2
-----pkgMusicPlayer
------MusicPlayer.java
-----pkgVideoPlayer
------VideoPlayer.java
---resources
----fxml
----css
--test
---java
---resources
Gradle file (relevant portion below, rest as per the link above ):
artifacts {
archives jarPackage("pkgCalculator", "1.0"),
jarPackage("pkgScale","1.0"),
jarPackage("pkgMusicPlayer","1.0"),
jarPackage("pkgVideoPlayer","1.0")
}
After discussion with #iCoder, first part of the issue has been solved: the jarPackage function could not be reused "as is", and had to be adapted to support generic class/package layout:
def jarPackage(String jarName, String className, artifactVersion) {
if (artifactVersion == "" || artifactVersion == null) {
artifactVersion = "1.0.0"
}
return tasks.create("jar${jarName}", Jar) {
baseName = jarName
version = artifactVersion
def String pkgName = className.substring(0, className.lastIndexOf("."))
def String pkgDir = pkgName.replaceAll("\\.", "/")
def String clazzName = className.substring( className.lastIndexOf(".") +1 )
from(sourceSets.main.output) {
include "$pkgDir//**"
}
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes "Implementation-Title": "$clazzName",
"Implementation-Version": "$version",
"Main-Class": "$pkgName.$clazzName"
}
}
}
artifacts {
archives jarPackage("calculator", "pkg1.pkcalculator.Calculator" , "1.0.0")
}
Another issue remains, not related to Gradle but to JDK 11 linkage problem: #iCoder you should open another question for that remaining problem, if not fixed yet.

How to set Gradle `options.bootClasspath` in an os independent manner?

Because my Java sources and targets must be JRE 1.6 compatible, I need to set options.bootClasspath to a path that contains the 1.6 versions of rt.jar and jce.jar. It must build on both Windows and Unix (Linux/Solaris). What is the proper way to do this? I now use the following approach in my top-level build.gradle, it works, but it seems far from elegant, especially the os-dependent separator : or ;:
import org.apache.tools.ant.taskdefs.condition.Os
subprojects {
apply plugin: 'java'
compileJava {
sourceCompatibility = 1.6
targetCompatibility = 1.6
def java6_home = System.getenv("JAVA_HOME_6")
def java6_lib = "C:/localdata/Program Files (x86)/Java/jdk1.6.0_45/jre/lib/"
if (java6_home != null) {
java6_lib = java6_home + "/jre/lib/"
}
def sep = ':'
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
sep = ';'
}
options.bootClasspath = java6_lib + "rt.jar" + sep + java6_lib + "jce.jar"
}
}
I am using the following code (assuming the JDK6_HOME points to the root of the JDK 1.6 installation):
tasks.withType(JavaCompile) {
doFirst {
if (sourceCompatibility == '1.6' && System.env.JDK6_HOME != null) {
options.fork = true
options.bootClasspath = "$System.env.JDK6_HOME/jre/lib/rt.jar"
options.bootClasspath += "$File.pathSeparator$System.env.JDK6_HOME/jre/lib/jsse.jar"
// use the line above as an example to add jce.jar
// and other specific JDK jars
}
}
}
This approach automatically detects the presence of the environment variable and automatically sets the bootClasspath for all modules that declare sourceCompatibility as 1.6.
The options.fork = true is required when you use bootClasspath.
The accepted answer can work, but if you're using some classes outside java.lang (e.g. javax.crypto.*) you may find you'll get various ClassNotFoundExceptionException's being raised as more JAR files need to be added to the bootClasspath.
To avoid this, I use the following which has the following advantages;
The options are only set if required
All the JAR files are added to the bootClasspath
The extensionDirs is also set (see http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#extdirs-option)
.
tasks.withType(JavaCompile) {
doFirst {
if (JavaVersion.toVersion(sourceCompatibility) == JavaVersion.VERSION_1_6
&& JavaVersion.current() != JavaVersion.VERSION_1_6
&& System.env.JDK6_HOME != null) {
options.fork = true
options.bootClasspath = fileTree(include: ['*.jar'], dir: "$System.env.JDK6_HOME/jre/lib/").join(File.pathSeparator)
options.extensionDirs = "$System.env.JDK6_HOME/jre/lib/ext/"
}
}
}
Since Gradle 4.3 you can use CompileOptions.bootstrapClasspath instead to remove the need for an OS-dependent separator.
A slight modification of the cool solution by Oleg Estekhin above, but doesn't require JDKX_HOME to be set (calculates it on the fly.) Also, modified for doing Java 1.7 builds:
tasks.withType(JavaCompile) {
doFirst {
if (sourceCompatibility == '1.7') {
def JDK7_HOME = "/usr/libexec/java_home -v 1.7".execute().text.trim()
options.bootClasspath = "$JDK7_HOME/jre/lib/rt.jar"
options.bootClasspath += "$File.pathSeparator$JDK7_HOME/jre/lib/jsse.jar"
// use the line above as an example to add jce.jar
// and other specific JDK jars
}
}
}
I tried to add many jars to my bootClassPath using the instructions above, but never resolved my build issue. I finally resolved the build by setting my JAVA_HOME to point to the IBM JDK 1.7 required by the WebSphere server and adding it to my path. My other projects require Oracle JDK 1.8 so I did not want to make this change permanent.
set JAVA_HOME="C:\Program Files (x86)\IBM\WebSphere\AppServer\java_1.7.1_64\"
set PATH=%JAVA_HOME%\bin;%PATH%
gradle clean war
gradle clean ear deployLocal

Gradle scala class already defined with combined Java compilation

I have the following scala compilation issue
scala -> depends upon java source
java source -> depends upon scala source
My scala code is in src/main/scala
My java code is in src/main/java
I cant change this code so I need to compile this with gradle and it currently compiles with JRuby just fine.
I have read the following posts on how to solve this issue:
http://forums.gradle.org/gradle/topics/how_to_compile_a_java_class_that_depends_on_a_scala_class_in_gradle
http://forums.gradle.org/gradle/topics/how_to_compile_a_java_class_that_depends_on_a_scala_class_in_gradle
I added this to my build:
ext {
baseName = 'd2'
description = 'Divisional IVR.'
combinedSources = "$buildDir/combined-sources"
}
apply plugin: 'scala'
compileScala.taskDependencies.values = compileScala.taskDependencies.values - 'compileJava'
compileJava.dependsOn compileScala
sourceSets.main.scala.srcDir "$combinedSources"
sourceSets.main.java.srcDirs = []
I tried to copy all the scala and java files to one location:
compileScala.dependsOn{
copyAllSourceFiles
}
task copyAllSourceFiles(type:Copy) {
description = 'Copy All Source Files.'
from('src/main/java') {}
from('/src/main/scala') {}
into combinedSources
includeEmptyDirs = false
}
But now I get an error:
[ant:scalac] Compiling 18 source files to C:\usr\git_workspaces\xivr\d2\target\classes\main
[ant:scalac] Compiling 18 scala and 196 java source files to C:\usr\git_workspaces\xivr\d2\target\classes\main
[ant:scalac] C:\usr\git_workspaces\xivr\d2\target\combined-sources\com\comcast\ivr\d2\actors\AlternateAniWithAccountActor.scala:9: error: AlternateAniWithAccountActor is already defined as class AlternateAniWithAccountActor
It almsot seems like scalaCompile sees $combinedSources and 'src/main/scala'
It almsot seems like scalaCompile sees $combinedSources and 'src/main/scala'
That's how you configured it: src/main/scala is the default, and you added "$combinedSources". To override the default, use sourceSets.main.scala.srcDirs = [combinedSources].
In any case, you don't have to (and shouldn't) copy sources around. Here is one solution that neither requires copying nor reconfiguring of task dependencies:
sourceSets.main.scala.srcDir "src/main/java"
sourceSets.main.java.srcDirs = []
Now, your Java and Scala code will get joint-compiled, and can depend on each other arbitrarily.
PS: Instead of "$combinedSources", use combinedSources.
gradle.properties
theVersion=2.1
theSourceCompatibility=1.7
theScalaVersion=2.10.3
build.gradle
apply {
plugin 'scala'
plugin 'java'
plugin 'idea'
}
ext {
scalaVersion = theScalaVersion
}
sourceCompatibility = theSourceCompatibility
tasks.withType(ScalaCompile) {
scalaCompileOptions.useAnt = false
}
dependencies {
compile "org.scala-lang:scala-library:$theScalaVersion"
compile "org.scala-lang:scala-compiler:$theScalaVersion"
}
sourceSets {
main.scala.srcDirs = ["src/main/scala", "src/main/java"]
main.java.srcDirs = []
}

Categories

Resources