I got some source code and was asked to build it. It was a Gradle project. So I changed to the project directory and ran:
$ gradle clean assemble
and the following error came up:
...
* What went wrong:
A problem occurred evaluating root project 'pcase'.
> Could not get unknown property 'postgresql.jdbc' for root project 'pcase' of type org.gradle.api.Project.
...
There is a settings.gradle file in the project folder too. It contains:
rootProject.name = 'pcase'
I took a look at build.gradle and found lots of occurrences like
${project['x']}
For example:
buildscript {
dependencies {
...
// FlywayDB, JOOQ.
classpath "org.postgresql:postgresql:${project['postgresql.jdbc']}"
classpath "org.flywaydb:flyway-gradle-plugin:${project['flywaydb.plugin.version']}"
classpath "nu.studer:gradle-jooq-plugin:${project['jooq.plugin.version']}"
...
What could be ${project['x']}? Looks like associative array in bash and the build script tries to get the value of the key 'x'.
But I didn't find the place in code where this array would be declared and initialized.
The question is: Is the project buildable or is it better to consult the company that worked at it before me?
From the information provided, the project is perfectly buildable, to some certain extend. First of all, project['a.b.c'] is Groovy syntax to access properties from the project object. They're referred to as project properties.
They can be set via
Project properties via command line: gradle -Ppostgresql.jdbc=x.y.z
System properties via command line: gradle -Dorg.gradle.project.postgresql.jdbc=x.y.z
System properties via gradle.properties: org.gradle.project.postgresql.jdbc=x.y.z
All 3 properties (postgresql.jdbc, flywaydb.plugin.version, jooq.plugin.version) denote the version numbers of the particular build script dependencies. However, which versions to use best is beyond my knowledge. I would certainly consult the respective project websites, Maven artifact search or simply ask the company.
org.postgresql:postgresql is the database JDBC driver and certainly depends on the database version.
org.flywaydb:flyway-gradle-plugin is for database migrations. Try with the latest version.
I wasn't able to find gradle-jooq-plugin on Maven central. It's most likely available on the Gradle Plugin Portal.
Related
(for reference I am using: IntelliJ as my IDE, Kotlin as the language, and Gradle Kotlin for build)
The package is successfully published to the GitLab Project's Package Registry, it is listed as a Maven. I can download and access the .pom/.jar/.module file in the GitLab Package Registry, additionally the link to the gitlab repo .pom file (as in the error message below) when clicked will download the .pom for the package (this has me super confused). However when I want to use it as a dependency in a different project it cannot be resolved. I am using an Access Token for authentication of this project. This is the error I am getting when I attempt to build / sync my gradle project:
Execution failed for task ':compileKotlin'.
> Error while evaluating property 'filteredArgumentsMap' of task ':compileKotlin'
> Could not resolve all files for configuration ':compileClasspath'.
> Could not find <group>:<projectName>:<version>.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/example/<projectName>/<version>/<projectName>-<version>.pom
- https://gitlab.com/api/v4/projects/<packageID>/packages/maven/com/example/<projectName>/<version>/<projectName>-<version>.pom
Required by:
project :
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
(The group, projectName and version are all filled in with the those things for the project)
I did read the documentation provided as a possible solution as well as a large number of other sources with potential fixes or ways of setting it up, however I cannot seem to find how to solve or correctly import and use my maven repo. Other sources that I have already checked out / tried to use are:
https://www.jetbrains.com/help/space/publish-artifacts-from-a-gradle-project.html#publish-maven-artifacts-using-the-gradle-command-line-tool
https://gitlab-docs.creationline.com/ee/user/packages/maven_repository/
This is what I have in my gradle.build.kts of the package which is attempting to import / use the dependency (again of course packageName, group, version etc are filled in)
val gitLabAccessToken: String by project
repositories {
mavenCentral()
maven {
url = uri("https://gitlab.com/api/v4/projects/<projectID>/packages/maven")
name = "GitLab"
credentials(HttpHeaderCredentials::class) {
name = "Deploy Token"
value = gitLabAccessToken
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
I'm certain I am missing something silly and small, if there is anything more that is needed to get this working so that I can import and use it I will be happy to provide.
I knew it was something stupid, thank you #aSemy, It was that I had missed the dash between Deploy and Token (Deploy Token -> Deploy-Token) and that fixed it. I cannot believe I wasted hours over a dash.
The Solution to this Problem is adding the dash between Deploy and Token.
User #aSemy noticed this when I did not.
I have a gradle project with 1 submodule, defined in the following file structure (+- refers to a directory):
+- <root>
build.gradle.kts
+- graph-commons
+- core
build.gradle.kts
The only submodule was included using the following kotlin script:
val graphCommons = project(File("./graph-commons/core"))
includeBuild(graphCommons)
When I execute ./gradlew clean assembly, I got the following error:
FAILURE: Build failed with an exception.
* Where:
Settings file '/home/peng/git/shapesafe/settings.gradle.kts' line: 2
* What went wrong:
Project with path './graph-commons/core' could not be found.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 492ms
FAILURE: Build failed with an exception.
* Where:
Settings file '/home/peng/git/shapesafe/settings.gradle.kts' line: 2
* What went wrong:
Project with path './graph-commons/core' could not be found.
What went wrong? Why the valid path "./graph-commons/core" cannot be identified by gradle?
The project is uploaded and tested on github:
https://github.com/tribbloid/shapesafe/runs/4280805005?check_suite_focus=true
Gradle does not work this way. A project path refers to a gradle project path, not to a file path. See https://docs.gradle.org/current/userguide/multi_project_builds.html#multi_project_builds
Edit: As mentioned in the comments, the project(File) method that is available in the settings.gradle.kts is a special method allowing to receive a ProjectDescriptor whose directory points to the given file. The project must be present already e.g. by including it via include(String...) first.
I first thought you tried to use the DependencyHandler#project(Map) method in some way, which is the usual way to refer to project dependencies. Gradle separates between dependencies and multi-project setup. In the settings.gradle.kts you usually setup the project structure while you declare dependencies in each build.gradle.kts. When using includeBuild you merely depend on the build of another completely separate project. When you then want to declare a dependency to a project from that included build you usually use the project's artifact coordinates to do so. This way the build still works when removing the includeBuild declaration.
If you want to use composite builds see here for basic usage: https://docs.gradle.org/current/samples/sample_composite_builds_basics.html
You will have to coordinate the artifact publishing and corresponding dependencies to make it work like a normal multi-project. Something like this:
graph-commons
|build.gradle.kts -> group = "org.scala-lang"; version = "1.0";
|settings.gradle.kts -> include(":graph-commons-core")
|graph-commons-core
||build.gradle.kts
shapesafe
|settings.gradle.kts -> includeBuild("../graph-commons")
|core
||build.gradle.kts -> dependencies { implementation("org.scala-lang:graph-commons-core:1.0") }
How can I add properties in Gradle which are similar to Maven's properties?
The use case is this: I want to have a file which declares all versions for repo dependencies so they are unified in a single place for a multi module project
compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
In Maven you can have properties like this:
<properties>
<jstlVersion>1.2</jstlVersion>
</properties>
Is it ok to use Gradle's external properties? Or just add them to the gradle.properties file?
Project properties defined in the root build file are available to subprojects. So if you have this in your root build.gradle file:
ext.commonsLangVersion = "2.4"
then you can use that in the dependencies {} block of a subproject like so:
dependencies {
implementation "commons-lang:commons-lang:${commonsLangVersion}"
}
You can also define such properties in the root gradle.properties file instead of the root build file. You use them in the same way.
If you really feel the need to put the versions in a separate file, you can do so. Simply add the following line to the root build file:
apply from: "dependencies.gradle"
Within the dependencies.gradle file, you can define the extra project properties as if they were in the root build file directly:
ext.commonsLangVersion = "2.4"
Note Normally, the values set in the build script take precedence over the values in gradle.properties. But if you set a value in the root build script as above, then any matching value in gradle.properties will override it in subprojects.
This behaviour is somewhat confusing and unique. For behaviour that is consistent with Gradle single-project builds you would need to use the following in the root build script:
allprojects {
apply from: "dependencies.gradle"
}
As a general rule of thumb, any given property should be declared/defined in either the build script or gradle.properties. If users want to override a particular property value, they can do so in $USER_HOME/.gradle/gradle.properties.
[EDIT I have updated the above note to clarify the actual behaviour]
One final thing: Gradle also allows you to control the versions of transitive dependencies via dependency constraints. You can also import Maven BOMs if you're using Gradle 4.6 or newer.
Found this as a possible solution, though I don't really like that uses relative path to the properties file.
Point 7 from here:
https://proandroiddev.com/make-your-build-gradle-great-again-c84cc172a654#8029
I have a Spring Boot Gradle project setup in Spring Tools Suite (3.7.2 RELEASE) with the following source folders:
- src/integration-test/java
- src/integration-test/resources
- src/main/java
- src/main/resources
- src/test/java
- src/test/resources`
Whenever I run the application or unit tests from within STS, I see that STS is using the resources found under src/integration-test/resources.
I see a duplicate resource warning in STS for files which exist in all 3 resource source folders. For example, I have an application.properties in all 3 source folders and I see following:
The resource is a duplicate of src/integration-test/resources/application.properties and was not copied to the output folder
If I run the application as a JAR or unit tests/integration tests from the command line (via gradle build), everything seems to use the correct resources. This makes me believe it is a problem with how STS/Eclipse is handling gradle.
Does anybody know of how I can configure STS to use the correct resource source folders when using gradle?
I think my problem may be related to (or the same as?) Spring Boot incorrectly loads test configuration when running from eclipse+gradle, https://issuetracker.springsource.com/browse/STS-3882, https://issues.gradle.org/browse/GRADLE-1777
I also tried the solution found here, but that seems to only fix Maven builds:
Spring Tool Suite finds spring-boot integration test configuration and does not start main application
I think my problem may be related to...
Yes, it is related but in my opinion not the same. That problem is caused by the runtime classpath being incorrect. This problem is an error coming from the eclipse project builder so it is a compile-time issue.
The problems are closely related though. Depending on your point of view, you could say they are the same (incorrect mixing of test and compile-time classpaths).
Here, specifically, the problem is that the eclipse builder tries to copy all the resources it finds in source folders to the project's single output folder. Each source folder has a 'application.properties'. The builder warns that it could not copy some of them because one would overwrite the other.
I think there may be a solution for this problem. But it is a solution that really should come from Gradle + ( BuildShip | STS Gradle Tooling) than from you.
It is possible in Eclipse to configure each source-folder individually to target a specific outputfolder. Maven + M2E are doing this correcty, but Gradle + (BuildsShip | STS Gradle Tooling) combdos do not.
For example this is what maven puts into the eclipse .classpath file when it configures a test resources folder:
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
Notice how it explicitly sets the output folder for that entry (to something different from the project's default output folder).
You may be able to address the problem yourself by modifying the .classpath for a gradle project in a similar way. Either by doing it manually or from your build.gradle.
I'm not sure this is worth it however as you will then likely still get hit by the runtime classpath issue (since these folders will still be added to your runtime classpath, your runtime classpath will end-up with two appication.properties resources, one which will 'shadow' the other. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=482315)
I would say, the right thing to do is add a comment to the issue I linked, and hope they fix it soon as there is only so much you can do yourself by hacking the build.gradle file to modify the .classpath (this can not solve the runtime classpath issue, but in order to solve the runtime classpath issue, they would have to configure source folders to target individual output folder similar to what m2e does).
I would add this as a comment to #Kris's answer but it's too long.
I have solved the runtime classpath issue by adding the code below to my build.gradle file. The code generates an Eclipse launch configuration for the Spring Boot application class and includes only the runtime classpath (i.e. no test JARs).
My project uses the Gradle 'eclipse' plugin to generate the Eclipse project files (which I then import into Eclipse). Running the eclipseClasspath Gradle target will generate the launch file in the project's root directory.
def mainClassName = "com.example.MyApplication"
task eclipseApplicationLaunch {
group "IDE"
description "Generate an Eclipse launch configuration file for the Spring Boot application class"
}
eclipseApplicationLaunch << {
def writer = new FileWriter("${mainClassName.substring(mainClassName.lastIndexOf(".")+1)}.launch")
def xml = new groovy.xml.MarkupBuilder(writer)
xml.doubleQuotes = true
xml.launchConfiguration(type: "org.eclipse.jdt.launching.localJavaApplication") {
listAttribute(key:"org.eclipse.debug.core.MAPPED_RESOURCE_PATHS") {
listEntry(value:"/${project.name}/src/main/java/${mainClassName.replace(".","/")}.java")
}
listAttribute(key:"org.eclipse.debug.core.MAPPED_RESOURCE_TYPES") {
listEntry(value:"1")
}
listAttribute(key:"org.eclipse.jdt.launching.CLASSPATH") {
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry containerPath=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/\" javaProject=\"${project.name}\" path=\"1\" type=\"4\"/>\r\n")
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry path=\"3\" projectName=\"${project.name}\" type=\"1\"/>\r\n")
configurations.runtime.resolvedConfiguration.resolvedArtifacts.each { artifact ->
def filePath = artifact.file.canonicalPath.replace("\\","/")
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry externalArchive=\"${filePath}\" path=\"3\" type=\"2\"/>\r\n")
}
}
booleanAttribute(key:"org.eclipse.jdt.launching.DEFAULT_CLASSPATH", value:"false")
stringAttribute(key:"org.eclipse.jdt.launching.MAIN_TYPE", value:"${mainClassName}")
stringAttribute(key:"org.eclipse.jdt.launching.PROGRAM_ARGUMENTS", value:"--spring.profiles.active=local --spring.config.location=conf/")
stringAttribute(key:"org.eclipse.jdt.launching.PROJECT_ATTR", value:"${project.name}")
stringAttribute(key:"org.eclipse.jdt.launching.VM_ARGUMENTS", value:"-Djava.net.preferIPv4Stack=true")
}
writer.close()
}
eclipseClasspath.dependsOn eclipseApplicationLaunch
I haven't modified the Eclipse .classpath file as per Kris' suggestion. Instead, I have added #Profile("test") to my test application class and #ActiveProfiles("test") to my test classes.
I'd like to create a subproject that acts as sole anchor for dependencies, ie. it includes no source code. Users can simply depend on the artifact created by the subproject in order to get all the required dependencies. So i've created foo-bar/build.gradle:
dependencies {
compile project(":foo-barz")
compile project(":foo-batz")
}
jar {
enabled = false
}
That seems to work as expected, until signing comes into the build process. I've then get an error message
:foo-bar:signArchives FAILED
What went wrong: Execution failed for task ':foo-bar:signArchives' >
java.io.FileNotFoundException:
/data/flo/code/foo/foo-bar/build/libs/foo-bar-4.0.1.jar (No such file
or directory)
How can I tell the signing plugin that it needs to sign just the pom file for this subproject?
I'd say either do not apply the java plugin, then you also don't need to disable the jar task, or also disable the signArchives task like you disabled the jar task.
I've came up with just creating an empty file with
foo-bar/src/main/java/org/foo/bar/FooBarDummy.java
so that all tasks are happy and an empty jar is created, signed and deployed. Thaks to Peter Niederwieser, Vampire and Daryl Teo for their input. I've found no elegant an easy solution to avoid that Dummy.java workaround.
This question was based on implementing smack-java7