Generate and consume gradle dependency without POM - java

I am trying to generate the .jar of my Gradle project but when it is generated using Maven publishing it is also generating a .pom file.
The problem is that I have another project that when it implements this dependency before it only looked for .jar and now it looks for .pom in all the others, what I want to do is that the project stops generating a .pom using the "publishing" task or that when implement it stop looking for the .pom files for the others to work.
Here is the code to generate the .jar in Artifactory project A with the one in project B that uses A and looks for the .pom:
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'com.proteccion.myproject'
artifactId = 'myproject-base'
version = '1.0.1'
from components.java
}
}
repositories {
maven {
name = 'artifactory'
url 'https://url/artifactory/MyProject'
credentials {
username System.getenv("ARTIFACTORY_USER")
password System.getenv("ARTIFACTORY_PWD")
}
}
}
}
repositories {
jcenter()
maven {
url 'https://url/artifactory/MyProject'
credentials {
username System.getenv("ARTIFACTORY_USER")
password System.getenv("ARTIFACTORY_PWD")
}
}
}
Perhaps with a Gradle equivalent of this segment:
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'com.proteccion.myproject'
artifactId = 'myproject-base'
version = '1.0.1'
from components.java
}
}

Finally this worked for me:
metadataSources {
artifact()
}
Forces to search only for the jar file.
The complete configuration:
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'com.company.myproject'
artifactId = 'myproject-base'
version = '1.0.1'
from components.java
}
}
repositories {
maven {
name = 'artifactory'
url 'https://url/artifactory/MyProject'
credentials {
username System.getenv("ARTIFACTORY_USER")
password System.getenv("ARTIFACTORY_PWD")
}
}
}
}
repositories {
jcenter()
maven {
url 'https://url/artifactory/MyProject'
credentials {
username System.getenv("ARTIFACTORY_USER")
password System.getenv("ARTIFACTORY_PWD")
}
metadataSources {
artifact()
}
}
}
Documentation (Example 18):
https://docs.gradle.org/current/userguide/dependency_management.html

Example 17. Maven repository that supports artifacts without metadata
repositories {
maven {
url "http://repo.mycompany.com/repo"
metadataSources {
mavenPom()
artifact()
}
}
}

Related

is it possible to publish gradle module metadata to oss.sontatype.org?

I'm trying to publish a jar to oss.sontatype.org using id 'maven-publish' (gradle 6.8.1).
Problem is that by default gradle publishes its module metadata and sonatype.org does not seem to like that. What happens is that sonatype does not list the jar artifact anymore. All I see (in the sontype ui) is:
myproject-SNAPSHOT-javadoc.jar
myproject-SNAPSHOT-source.jar
myproject-SNAPSHOT.module
The jar is missing although I can see in the gradle log that it uploads the jar.
If I disable the gradle metadata
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
I see the expected files:
myproject-SNAPSHOT-javadoc.jar
myproject-SNAPSHOT-source.jar
myproject-SNAPSHOT.jar
I wonder if it is possible to publish gradle module metadata to oss.sonatype.org?
Here is my publishing configuration on github and inline:
// does not work on oss.sonatype.org
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
publishing {
publications {
OpenApiProcessor (MavenPublication) {
groupId project.group
artifactId project.name
version project.version
from components.java
artifact sourcesJar
artifact javadocJar
pom {
name = project.projectTitle
description = project.projectDesc
url = project.projectUrl
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = "repo"
}
}
developers {
developer {
id = 'hauner'
name = 'Martin Hauner'
}
}
scm {
url = "https://github.com/${project.projectGithubRepo}".toString ()
}
}
}
}
repositories {
maven {
def releaseRepository = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
def snapshotRepository = uri("https://oss.sonatype.org/content/repositories/snapshots")
url = project.isReleaseVersion ? releaseRepository : snapshotRepository
credentials {
username = publishUser
password = publishKey
}
}
}
}
tasks.withType(Sign) {
onlyIf { project.isReleaseVersion }
}
signing {
useInMemoryPgpKeys(signKey, signPwd)
signing {
sign publishing.publications.OpenApiProcessor
}
}

How to publish a JAR with no source?

I've a multimodule Kotlin Gradle project:
data-cassandra
-- cassandra-autoconfigure
-- cassandra-starter
cassandra-autoconfigure has source code, the other two don't. cassandra-starter's purpose in life is to bring in cassandra-autoconfigure as api(project(":cassandra-autoconfigure")); this is a standard convention in Spring Boot. cassandra-starter has some test code, but nothing in src/main/kotlin.
Problem is, when I try to publish these projects, it's failing.
Artifact cassandra-starter-1.0.0-SNAPSHOT.jar wasn't produced by this build.
This is true and I can see > Task :cassandra-starter:jar SKIPPED. How do I force Gradle to build the jar with only META-INF in it?
data-cassandra/build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
java
kotlin("jvm") apply false
`maven-publish`
}
allprojects {
group = "mycompany.data"
version = "1.0.0-SNAPSHOT"
repositories {
mavenCentral()
}
}
subprojects {
apply(plugin = "kotlin")
apply(plugin = "maven-publish")
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf(
"-Xjsr305=strict"
)
jvmTarget = "11"
}
}
plugins.withType<JavaPlugin> {
extensions.configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
val springBootVersion: String by project
dependencies {
implementation(platform("org.springframework.boot:spring-boot-dependencies:$springBootVersion"))
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
exclude(group = "com.vaadin.external.google", module = "android-json")
}
}
}
val isSnapshot = project.version.toString().toLowerCase().endsWith("snapshot")
val artifactoryUrl = property("artifactoryUrl") as String
extensions.configure<PublishingExtension> {
publications {
create<MavenPublication>("maven") {
from(components["java"])
}
repositories {
maven {
url = uri(artifactoryUrl + if (isSnapshot) "/libs-snapshot-local" else "/libs-release-local")
credentials {
username = property("artifactoryUsername") as String
password = property("artifactoryPassword") as String
}
if (!artifactoryUrl.startsWith("https")) {
isAllowInsecureProtocol = true
}
}
}
}
}
}
tasks.withType<PublishToMavenRepository> {
doFirst {
println("Publishing ${publication.groupId}:${publication.artifactId}:${publication.version} to ${repository.url}")
}
}
cassandra-autoconfigure/build.gradle.kts
plugins {
kotlin("jvm")
kotlin("plugin.spring")
}
val springDataVersion: String by project
dependencies {
implementation(platform("org.springframework.data:spring-data-releasetrain:$springDataVersion"))
api("org.springframework.boot:spring-boot-starter-data-cassandra-reactive")
}
cassandra-starter/build.gradle.kts
plugins {
id("org.springframework.boot")
kotlin("jvm")
kotlin("plugin.spring")
}
val cassandraUnitVersion: String by project
dependencies {
api(project(":cassandra-autoconfigure"))
testImplementation("org.cassandraunit:cassandra-unit:$cassandraUnitVersion") {
exclude(group = "org.hibernate", module = "hibernate-validator")
}
}
tasks.bootJar {
enabled = false
}
Answering my own question, from Spring Boot docs:
By default, when the bootJar or bootWar tasks are configured, the jar
or war tasks are disabled. A project can be configured to build both
an executable archive and a normal archive at the same time by
enabling the jar or war task:
cassandra-starter/build.gradle.kts
tasks.jar {
enabled = true
}
fixes the issue.

Magic with publishing section in artifactoryPublish configuration

I faced some magic behaviour in build.gradle configuration.
I'm trying to enable artifactoryPublish for project with subprojects.
I have the following structure
root
--subproj1
--subproj2
--common
gradle version 6.0.1
Case 1
on root level i have build gradle file with the following section
subprojects {
apply from: "$rootDir/gradle/artifactory.gradle"
}
in artifactory.gradle
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
artifactory {
contextUrl = artifactoryUrl
publish {
repository {
repoKey = 'mvn-snapshot-local'
password = artifactoryPassword
username = artifactoryUser
}
defaults {
publications('mavenJava')
publishArtifacts = true
publishPom = true
}
}
}
when i run artifactoryPublish it complete successfully but publish nothing
Case 2
when i move publishing section from file to top level like this
subprojects {
apply from: "$rootDir/gradle/artifactory.gradle"
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
}
everithing works fine, build successfull and publish.
Question
What is the difference in this 2 configurations, why it's not working in the 1 case?
I think would look more accurate if i keep all publishing related sections in one place rather then in different, but i can't by some reason.
It seems like the problem was that I missed plugin configuration:
pluginManagement {
gradle.ext.artifactoryPassword = artifactory_password ?: "nokey"
gradle.ext.artifactoryUser = artifactory_user ?: "nokey"
repositories {
mavenLocal()
maven {
url "${artifactoryUrl}/mvn-gradle-plugins"
credentials {
username = gradle.ext.artifactoryUser
password = gradle.ext.artifactoryPassword
}
}
maven {
url "${artifactoryUrl}/mvn-libs-release"
credentials {
username = gradle.ext.artifactoryUser
password = gradle.ext.artifactoryPassword
}
}
}
}
The repositories were configured in repositories section:
repositories {
if(version.toString().endsWith('SNAPSHOT')) {
maven {
url "$artifactoryUrl/mvn-libs-snapshot"
credentials {
username artifactoryUser
password artifactoryPassword
}
}
}
maven {
url "$artifactoryUrl/mvn-libs-release"
credentials {
username artifactoryUser
password artifactoryPassword
}
}
maven {
credentials {
password = artifactoryPassword
username = artifactoryUser
}
url "$artifactoryUrl/mvn-external"
}
mavenLocal()
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
But it hasn't worked until I added plugin management section and updated versions of artifactory and recon plugins.

How to extract buildscript from build.gradle

I have following buildscript section in my build.gradle:
buildscript {
ext {
nexusUrl = project.hasProperty("myNexusUrl") ? myNexusUrl : "http://10.199.0.99:8081/repository/maven-public/"
}
repositories {
maven { url nexusUrl }
}
dependencies {
classpath group: 'mygroup', name: 'MyGradleLibrary', version: '1.0.1'
}
}
How can I extract this code to external file, so that it doesn't break the build?
Create a plugin from your library and publish it to that Nexus. Then, add this lines in your settings.gradle:
pluginManagement {
repositories {
maven {
url "…"
}
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'mygroup.gradle-library') {
useModule('mygroup.gradle-library:1.0.1')
}
}
}
}
Here you state that you want to substitute mygroup.gradle-library plugin with mygroup.gradle-library:1.0.1 dependency.
Then just add a plugin in your build.gradle:
plugins {
id 'mygroup.gradle-library'
}
Now you have you dependency on the build classpath without buildscript block.
EDIT
In order to apply this to all your projects, put these lines in init script ~/.gradle/init.gradle ($GRADLE_USER_HOME/init.gradle):
settingsEvaluated {
pluginManagement {
repositories {
maven {
url "…"
}
gradlePluginPortal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'mygroup.gradle-library') {
useModule('mygroup.gradle-library:1.0.1')
}
}
}
}
}
After that plugin blocks should work. However, it will work only for you but not for your teammates, unless they do the same.
If you don't like plugins you can still do "global" configuration via init scripts like demonstrated. Read more about the available APIs.

How to add static files to jar using Gradle build in Spring Boot + Angular 2 project

I have a Spring Boot + Angular 2 project. I want to deploy it to Heroku.
I'm able to run the npm build then copy the generated files over to the public folder (src/resources/public) manually, then run the backend build.
What I want to do is to set up a gradle build that will do all of that at once.
What I have so far is a gradle build that will build the front end, build the backend, however it does not copy the static files before generating the jar. Since the jar does not contain said static files, it won't work on Heroku.
Here's the project folder structure:
root
backend
src/main/java
src/main/resources
frontend
--> angular files go here
build/libs -> where the JAR file goes
The gradle build file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// spring
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE')
classpath('org.springframework:springloaded:1.2.6.RELEASE')
}
}
plugins {
id "com.moowork.node" version "1.2.0"
}
// gradle wrapper
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
// configure gradle-node-plugin
node {
version = '8.1.4'
npmVersion = '5.0.3'
download = true
workDir = file("${project.projectDir}/node")
nodeModulesDir = file("${project.projectDir}/")
}
// clean node/node_modules/dist
task npmClean(type: Delete) {
final def webDir = "${rootDir}/frontend"
delete "${webDir}/node"
delete "${webDir}/node_modules"
delete "${webDir}/dist"
delete "${webDir}/coverage"
delete "${rootDir}/backend/src/main/resources/public"
}
// clean task for npm
task copyFiles {
doLast {
copy {
from "${rootDir}/frontend/dist"
into "${rootDir}/backend/src/main/resources/public"
}
}
}
// build task for npm
task frontendBuild {}
frontendBuild.dependsOn(npm_install)
frontendBuild.dependsOn(npm_run_build)
npm_install {
args = ['--prefix', './frontend']
}
npm_run_build {
args = ['--prefix', './frontend']
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
sourceSets {
main {
java {
srcDirs = ['backend/src/main/java']
}
resources {
srcDirs = ['backend/src/main/resources']
}
}
}
copyFiles.dependsOn(frontendBuild);
compileJava.dependsOn(frontendBuild);
task backendBuild {}
backendBuild.dependsOn(compileJava)
backendBuild.dependsOn(jar)
jar.dependsOn(copyFiles)
repositories {
mavenCentral()
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
}
}
idea {
module {
inheritOutputDirs = false
outputDir = file("${buildDir}/classes/main/")
}
}
jar {
baseName = 'expense-splitter'
version = '0.0.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
configurations {
dev
}
dependencies {
// spring
compile('org.springframework.boot:spring-boot-starter-web:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:1.5.2.RELEASE')
compile('org.apache.commons:commons-lang3:3.3.2')
// to make hibernate handle java 8 date and time types correctly
// it's marked as deprecated but we need to keep it until
// spring boot jpa starts using hibernate 5.2
compile('org.hibernate:hibernate-java8:5.1.0.Final')
// json web tokens
compile ('io.jsonwebtoken:jjwt:0.7.0')
compile 'mysql:mysql-connector-java'
// google gson
compile('com.google.code.gson:gson:2.8.0')
// jackson - parsing of java 8 date and time types
compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7')
// spring dev tools
dev('org.springframework.boot:spring-boot-devtools:1.5.2.RELEASE')
// testing
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.2.RELEASE')
}
// run spring boot app
bootRun {
//addResources = true
classpath = sourceSets.main.runtimeClasspath + configurations.dev
jvmArgs = ["-Xdebug -agentlib:jdwp=transport=dt_socket,address=8080,server=y,suspend=n"]
}
// run all task
task runAll {}
runAll.dependsOn(bootRun)
Thanks in advance,
Try a different approach. Instead of manually copying the resources, tell Gradle that when it processes resources for the JAR, also take into consideration what is in frontend/dist/:
processResources {
from ('frontend/dist/') {
into 'public'
}
}
This should result in a JAR containing a public/ directory, with the contents of frontend/dist/ inside of it.
Gradle configuration for Spring Boot 1.5\2.x + Angular 2-6
Angular in sub-folder frontend
Frontend module
Crate build.gradle:
plugins {
id "com.moowork.node" version "1.2.0"
}
node {
version = '8.11.3'
npmVersion = '5.6.0'
download = true
workDir = file("${project.buildDir}/node")
nodeModulesDir = file("${project.projectDir}")
}
task build(type: NpmTask) {
args = ['run', 'build']
}
build.dependsOn(npm_install)
Note for Angular 6
Update outputPath value in angular.json to 'dist'
Backend module
Edit build.gradle for backend module:
Spring Boot 2.X:
bootJar {
archiveName = "yourapp.jar"
mainClassName = 'com.company.app.Application'
from('frontend/dist') {
into 'static'
}
}
Spring Boot 1.5.X:
jar {
archiveName = "yourapp.jar"
manifest {
attributes 'Main-Class': 'com.company.app.Application'
}
from('frontend/dist') {
into 'static'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Finally execute bootRepackage or bootJar task and check results in builds/libs
Assume that front end is located at the following folder: src/main/webapp/fe-ui/, the following solution for the Spring Boot version 2.1.1.RELEASE could be considered:
bootJar {
baseName = 'jar-name'
version = '0.1.0'
from('src/main/webapp/fe-ui/build') {
into 'public'
}
}
task installFeDependencies(type: NpmTask) {
args = ['install']
}
task buildFe(type: NpmTask) {
args = ['run', 'build']
dependsOn installFeDependencies
}
compileJava {
dependsOn buildFe
}
Running gradlew build will install, build front end as well as will invoke bootJar. The latter will package built front end bundle.

Categories