trouble publishing my first artifact on gradle - gradle

I am having trouble pushing my first build to gradle to a remote server on nexus. The build was successful but when i use ./gradlew publish no jar files are pushed to the repo.
below is my build code
plugins {
id 'java'
id 'org.springframework.boot' version '2.2.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
}
group 'com.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
artifact("build/libs/my-app-$version"+".jar") {
extension 'jar'
}}
}
}
repositories {
maven {
name 'nexus'
url "http://159.65.23.158:8081/repository/maven-snapshots/"
credentials {
username project.repoUser
password project.repoPassword
}
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '5.2'
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
When I entered the ./gradlew publish it performs the same as the ./gradlew build command. I have checked the nexus repo and no files have been pushed to my repo. I am doing a bootcamp by Nana Janashia and I have followed step by step and cannot figure where i am going wrong?

It looks like the publishing task does not depend on the jar task, so no jar has been produced to get picked up from the libs folder. You can confirm this by running ./gradlew publish --dry-run to see what tasks are running.
To fix this, I suggest you pass the appropriate jar task to the artifact method instead of the raw path to the jar, viz:
publishing {
publications {
maven(MavenPublication) {
artifact(tasks.named(sourceSets.main.jarTaskName)) {
extension 'jar'
}
}
}
}
Passing the task gives Gradle the information it needs to run the right tasks in the right order.

Related

How to get dependency version form parent project in Gradle

I have a Gradle project and I want to create a submodule but I am getting an FAILURE when building the project.
The error message is
Execution failed for task ':child-project:compileJava'
> Could not resolve all files for configuration 'child-project:compileClasspath'.
> Could not find org.springframework.boot:spring-boot-starter:.
Required by:
project :parent-project
This is the parent project build.gradle file:
plugins {
id 'org.springframework.boot' version '2.3.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
allprojects {
apply plugin: 'java'
group = 'com.test'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
repositories {
//local nexus
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'
//other dependencies
}
This is the child project build.gradle:
plugins {
id 'java'
}
group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11
dependencies {
compile 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
Please help, thanks in advance.
In order to be able to specify Spring Boot dependencies without versions, you need to apply the Spring Boot plugin to all modules. Right now you only have it in the parent project, but not the child.
Because applying the plugin will also, by default, disable the normal jar task can create a bootJar instead, you need to change this for libraries:
// Child build file
plugins {
// Note that there are no versions on the plugins in the child project as this is defined by the ones in the parent
id 'org.springframework.boot'
id 'io.spring.dependency-management'
}
bootJar {
enabled = false
}
jar {
enabled = true
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
}
Alternatively, you could also scrap the io.spring.dependency-management plugin (and the org.springframework.boot plugin in the child project), and instead import the Spring Boot BOM as a platform:
// Child build file (alternative)
dependencies {
// Use 'platform' for making the versions in the BOM a recommendation only, and 'enforcedPlatform' for making them a requirement.
// Note that you need the version of the BOM, so I recommend putting it in a property.
implementation enforcedPlatform("org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE")
// Here you can leave out the version
implementation 'org.springframework.boot:spring-boot-starter'
}
I usually go for the latter alternative as this allows me to use normal Gradle semantics. But it is mostly just preference.
(And just a small note to your build script: the compile configuration is deprecated. It is used in the line compile 'org.springframework.boot:spring-boot-starter'. You probably just copy/pasted it from somewhere, but you should replace it with implementation.)

gradle does not fetch dependencies after upgrade from 5.1.1 to 6.4.1

I have several services that uses gradle 5.1.1 with java 8.
As we want to upgrade to Java 13, we first need to upgrade to gradle 6after doing so, some dependencies are not fetched.
Those dependencies are listed with compile() under a dependency which is our jar library and still built with gradle 5.1.1
our libraries are stored in a S3 bucket and we use shadowjar to generate the end jar.
so, for example:
I have project A which I want to upgrdae.
Project A has project B as a dependency (compile)
Project B has google guava as a dependency (also with compile)
Now, project A, that under gradle 5.1.1 had fetched guava with no problems, alerting me that it is missing guava after upgrading to gradle 6.
I use local computer installed gradle (not wrapper).
Here are the important build.gradle parts:
buildscript {
repositories {
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
}
ext.ver = [
'springboot': '2.2.0.RELEASE',
'slf4j' : '1.7.12'
]
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${ver.springboot}"
classpath 'io.spring.gradle:dependency-management-plugin:1.0.7.BUILD-SNAPSHOT'
classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
classpath 'com.amazonaws:aws-java-sdk-core:1.11.5'
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'maven'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'maven-publish'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
compileJava {
sourceCompatibility = JavaVersion.VERSION_1_8
}
configurations {
compile.exclude module: 'spring-boot-starter-logging'
testCompile.exclude module: 'spring-boot-starter-logging'
runtime.exclude module: 'spring-boot-starter-logging'
compile.exclude group: 'ch.qos.logback'
}
configurations.all {
resolutionStrategy.cacheDynamicVersionsFor 10, 'seconds'
resolutionStrategy.cacheChangingModulesFor 10, 'seconds'
}
dependencyManagement {
applyMavenExclusions = false
}
repositories {
mavenLocal()
maven {
url "s3://bucket"
credentials(AwsCredentials) {
accessKey = awsCredentials.AWSAccessKeyId
secretKey = awsCredentials.AWSSecretKey
}
metadataSources {
artifact()
}
}
mavenCentral()
}
dependencies {
compile("com.test:projectB:1.0.0")
...
}
import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer
shadowJar {
classifier = ''
baseName = 'project-A'
manifest {
attributes 'Main-Class': 'com.test.projectA.Starter'
}
mergeServiceFiles()
append 'META-INF/spring.handlers'
append 'META-INF/spring.schemas'
append 'META-INF/spring.tooling'
transform(PropertiesFileTransformer) {
paths = ['META-INF/spring.factories']
mergeStrategy = "append"
}
}
Could this be because project B was not built with new gradle?
unfortunately, I cannot create a real reproducer as those libraries are real code of the company I work at.
Thanks and Regards,
Ido
The metadataSources declaration of the s3 bucket Maven repository is most likely the root cause why transitive dependencies of projectB are not resolved. The documentation is quite a bit vague here, but I suspect artifact() looks for the actual jar file only and not for the POM file, hence transitive dependency resolution is not performed. You should be able to see this behavior when running the build with switches --info and --refresh-dependencies.
Thankfully, this is quite easy to fix. Add mavenPom() and Gradle will try to resolve the POM first and with that, dependency resolution should be back to normal.
And while you're at it, you might want to read the upgrading from Gradle 5 guide and get rid of the compile configuration in favor of implementation. You should be able to see a warning similar to this when running the build with --warning-mode all:
The compile configuration has been deprecated for dependency declaration. This will fail with an error in Gradle 7.0. Please use the implementation or api configuration instead. Consult the upgrading guide for further information: https://docs.gradle.org/6.4.1/userguide/upgrading_version_5.html#dependencies_should_no_longer_be_declared_using_the_compile_and_runtime_configurations

Skip building jar in Gradle groovy scripts project

I have a gradle groovy project where I only have groovy scripts that are not in a source dir, but a separate dir. Additionally I have groovy junit tests that test the scripts invoking them using groovy shell.
I have a gradle build that runs the tests, then zips the scripts into separate zip files and uploads them into maven repo. The problem is, that gradle also creates and uploads a jar file. Since there are no files in source dirs, the jar contains only a generated manifest file.
In reality I don't need the jar at all.Is it possible to configure gradle to not create a jar file for a groovy project?
I upload the artifacts using uploadArchives task.
My full gradle config:
group 'groupName'
version '1.0-SNAPSHOT'
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'maven'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
}
task scriptsZip(type: Zip) {
from 'scripts'
}
artifacts {
archives file: scriptsZip.archivePath, type: 'zip', classifier: 'scripts', builtBy: scriptsZip
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "file://C:\\testRepo")
}
}
}
You can modify the jar task with an onlyIf condition, to skip building the jar when some condition is met (or not met)
jar {
onlyIf { /*some condition*/ }
}
In your case, it might make sense to check if there are any source files in your main sourceset:
jar {
onlyIf { !sourceSets.main.allSource.files.isEmpty() }
}

How to force artifact/module name with Gradle build

Please note: even though this question specifically mentions Bamboo CI and the Gradle ShadowJar plugin, I believe this is a basic Gradle config question at heart, and believe it can be answered by any battle-weary Gradle Guru.
I have a Groovy app that is built with Gradle, where build.gradle is:
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'eclipse'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
group = 'com.me.myapp'
mainClassName = "com.me.myapp.MyAppDriver"
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0'
}
}
dependencies {
// Omitted for brevity
}
jar {
manifest {
attributes 'Main-Class': mainClassName
}
}
repositories {
mavenLocal()
mavenCentral()
}
shadowJar {
classifier = ''
mergeServiceFiles {
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
}
}
artifacts {
archives(file("${buildDir}/libs/myapp-${version}.jar")) {
name "myapp"
classifier ""
builtBy shadowJar
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
And where gradle.properties is:
group=com.me.myapp
version=1.0.0
As you can see, I'm using ShadowJar to produce a self-contained "fat JAR" for my app. When I run gradle clean build shadowJar on my local machine, Gradle produces a build/libs/myapp-1.0.0.jar artifact/archive. However, when this same command is ran from our CI server (Bamboo), Gradle produces a build/libs/MYAPP-KEY-1.0.0.jar artifact/archive, where MYAPP-KEY is the Bamboo "build key" (essentially, a unique key/label identifying the build on the server). If you're clueless as to what I'm talking about, I don't think that really matters. What is important to understand is that Bamboo will check out the source code for myapp to a folder named MYAPP-KEY on the CI server. So locally myapp/ is the root of my project, but on CI MYAPP-KEY is the root of my project.
The main point is that I am not explicitly defining something in my Gradle config, and so it seems that Gradle is using the name of the project root to produce the name of the built JAR. What is this "something" and how/where do I define it? The desired end objective is to produce a build/libs/myapp-1.0.0.jar both locally and on CI.
please, look at https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html
you can specify base name or full archive name of jar
add it to your jar section

Gradle maven-publish for Spring-Boot project throws error: Cannot find parent: org.springframework.boot:spring-boot-starter-parent for project

I am new to Gradle so any help with this error will be highly appreciated.
I am building a REST based service using Spring-boot. I want to publish the JAR file to the local maven repository so that my web application can use it. After trying many things, I finally settled for maven-publish plugin. Here is my build.gradle file
//Needed for spring-boot
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE")
}
}
apply plugin: 'eclipse'
// Apply the groovy plugin to add support for Groovy
apply plugin: 'groovy'
//apply Spring-boot plugin
apply plugin: 'spring-boot'
apply plugin: 'maven-publish'
// In this section you declare where to find the dependencies of your project
repositories {
mavenLocal()
// Use 'jcenter' for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
}
group = "com.proto"
publishing {
publications {
maven(MavenPublication) {
groupId "${project.group}"
artifactId "${project.name}"
version "${project.jar.version}"
artifact sourceJar { classifier "sources" }
from components.java
pom.withXml {
asNode().appendNode('parent')
.appendNode('groupId', 'org.springframework.boot').parent()
.appendNode('artifactId', 'spring-boot-starter-parent').parent()
.appendNode('version', '1.1.8.RELEASE')
asNode().appendNode('repositories').appendNode('repository')
.appendNode('id', 'spring-releases').parent()
.appendNode('url', 'http://repo.spring.io/libs-release')
}
}
}
}
task sourceJar(type: Jar) {
from sourceSets.main.allJava
}
jar {
baseName = 'my-api'
version = '0.0.1'
}
task('execJar', type:Jar, dependsOn: 'jar') {
baseName = 'my-api'
version = '0.0.1'
classifier = 'exec'
from sourceSets.main.output
}
bootRepackage {
withJarTask = tasks['execJar']
}
// In this section you declare the dependencies for your production and test code
dependencies {
// We use the latest groovy 2.x version for building this library
compile 'org.codehaus.groovy:groovy-all:2.3.6'
compile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
// tag::jetty[]
compile("org.springframework.boot:spring-boot-starter-web")
// {
// exclude module: "spring-boot-starter-tomcat"
// }
// compile("org.springframework.boot:spring-boot-starter-jetty")
// end::jetty[]
// tag::actuator[]
compile("org.springframework.boot:spring-boot-starter-actuator")
// We use the awesome Spock testing and specification framework
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
testCompile 'junit:junit:4.11'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('cglib:cglib:3.1')
}
// tag::wrapper[]
task wrapper(type: Wrapper) {
gradleVersion = '2.1'
}
My problem is that, when I run:
gradle publishToMavenLocal
I get the following error:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':publishMavenPublicationToMavenLocal'.
> Failed to publish publication 'maven' to repository 'MavenLocal'
> Unable to initialize POM pom-default.xml: Cannot find parent: org.springframework.boot:spring-boot-starter-parent for project: com.proto:proto-api:jar:0.0.1 for project com.proto:proto-api:jar:0.0.1
My gradle environment details:
------------------------------------------------------------
Gradle 2.1
------------------------------------------------------------
Build time: 2014-09-08 10:40:39 UTC
Build number: none
Revision: e6cf70745ac11fa943e19294d19a2c527a669a53
Groovy: 2.3.6
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.7.0_72 (Oracle Corporation 24.72-b04)
OS: Linux 3.13.0-39-generic amd64
What am I missing?
Thank you in advance for your help.
Ok, I have fixed the issue.
I am behind our corporate firewall, and had configured proxy correctly for gradle in ~/.gradle/gradle.properties file. But, I missed setting proxies for maven in ~/.m2/settings.xml file.
I configured our internal nexus repository to handle this issue but setting proxies block should work as well. Click here for maven settings.xml documentation
Same as #aardee, I am sitting behind our corporate firewall but it seems that my proxy settings (settings.xml) for maven local did not change anything. Fortunately we have our own maven repository that can proxy out and so I just replaced the repository in the generated pom and made sure that our company maven repository knows the relevant spring repos.
pom.withXml {
asNode().appendNode('parent')
.appendNode('groupId', 'org.springframework.boot').parent()
.appendNode('artifactId', 'spring-boot-starter-parent').parent()
.appendNode('version', '1.1.8.RELEASE')
asNode().appendNode('repositories').appendNode('repository')
.appendNode('id', 'spring-releases').parent()
.appendNode('url', 'http://my.mavenRepo.com/releases}
Replace http://my.mavenRepo.com/releases with your own maven repository.

Resources