How to make Gradle flatDir read nested folders? - java

I'm using the Gradle local flatDir repository in the following way:
repositories {
flatDir {
dirs 'D:/path/to/local/directory'
}
}
but it only searches for the first layer of files. I wonder if there is an option of telling Gradle to locate the dependencies all over the repository, so I would be able to organize my jars by groups and still make Gradle read them all without specifying the groups.

Have you considered using the Maven directory conventions instead of flatDir?
Eg store jars like
myLocalRepo/com/foo/bar/1.0/bar-1.0.jar
myLocalRepo/com/foo/baz/2.0/baz-2.0.jar
Then in build.gradle
repositories {
maven {
uri file('myLocalRepo')
}
}
dependencies {
compile 'com.foo:bar:1.0'
compile 'com.foo:baz:2.0'
}

Related

Does Gradle flatDir enable jar builds?

I'm using Gradle flatDir local repository and I wonder if I would be able to use a compiled jar of my program, without needing to manually generate POM. Will Gradle still build and use the dependencies in this situation?
repositories {
flatDir {
dirs 'D:/path/to/local/directory'
}
}
Yes, Gradle can find jars in the local directory
if you have D:/path/to/local/directory/myjar-1.0.jar, you could use it like this...
repositories {
flatDir {
name 'localrepo'
dirs 'D:/path/to/local/directory'
}
}
...
implementation name:'myjar', version: '1.0'
I'd recommend using a local path to the project, like $rootDir/libs. Note, for a multi-module gradle project don't use
dirs "libs"
because it will look for libs in each module, not in the parent directory.
Instead it's probably better to put all the jars in $rootDir/libs and use this:
dirs new java.io.File(rootDir, "libs")

using gradle plugin from flatDir source

How to amend Gradle plugins {} management repository for custom plugins? is not duplicated in this post, because it does not cover use of flatDir.
Question
How do I use a Gradle plugin defined in a local JAR, using the new plugin {} semantics, instead of the deprecated apply() semantics?
Current Status
Not having any resolution, after posting the question and searching at considerable length, I filed an issue, wondering whether this use, which ought to be common and straightforward, is unsupported, either by design or oversight, within Gradle's revised plugin semantics.
Unfortunately, my report was closed, with no useful information provided.
I requested clarification in a new issue, but am still waiting.
I am frustrated, having expected that the community would be interested in at least discussing this problem.
If you can contribute information, please do so.
First Update
Following the clarification about the new style for configuring plugin sources, I updated my settings.gradle file to open with the following block. However, I regret that I see no improvement by this change alone. (For the plugin id field referenced in the build.gradle file, I have tried both the global ID published in the JAR metadata, and the basename of the JAR fie. Both fail equally.)
pluginManagement {
repositories {
gradlePluginPortal()
jcenter()
flatDir {
dirs 'lib`'
}
}
}
The documentation explains how to use custom repositories, but appears to overlook the case of a trivial flat directory.
Second Update
I get some improvement if I add a version number to the JAR file and to the corresponding statement in the plugins {} block. In this case, the message becomes:
Plugin [id: 'plugin-id', version: '1.0.0'] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Plugin Repositories (could not resolve plugin artifact 'plugin-id:plugin-id.gradle.plugin:1.0.0')
Searched in the following repositories:
Gradle Central Plugin Repository
BintrayJCenter
flatDir(/absolute/path/to/lib)
In this case, the directory is added to the list of sources searched.
It is strange that the .gradle.plugin suffix is being appended to my ID in the printed artifact. It is also strange that adding the version number to what is being searched for affects the list of places being searched.
So my project still cannot build. I appreciate any further help.
Original Background
I placed a JAR file containing a custom plugin definition in the lib directory of a project. With the build.gradle build file as below, the build runs successfully.
buildscript {
repositories {
flatDir {
dirs 'lib'
}
}
}
apply plugin: 'plugin-id'
However, the apply() semantics are deprecated, favoring a plugins {} block, so I tried updating the build file as below.
plugins {
id 'plugin-id'
}
repositories {
flatDir {
dirs 'lib'
}
}
I understand that the plugins {} contents can draw from the repositories {} definitions.
However, the change creates a failure:
* What went wrong:
Plugin [id: 'plugin-id'] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Plugin Repositories (plugin dependency must include a version number for this source)
Keeping the plugin {} block but moving the repositories {} block back into a leading buildscript {} block does not resolve the error. That is, the error persists even if I revert to the earlier version only replacing the apply() statement with the plugin {} block.
Finally, it has no effect to add to the repositories {} block a dependencies { classpath: ':jarname' } block, which some sources suggest is necessary, though I don't know why it would be.
This works. Tested with gradle 6.3.
build.gradle:
plugins {
id 'plugin-id'
}
settings.gradle:
pluginManagement {
buildscript {
repositories {
flatDir {
dirs '/plugin-folder/build/libs'
}
}
dependencies {
classpath ':plugin-jar:0.0.1'
}
}
}
Update: I just found out today that it is possible to have your plugin jar resolved without using the dependencies block above. In that case you should name your plugin jar as [plugin-id].gradle.plugin[-version].jar. Note that the [-version] part is optional and plugin-id.gradle.plugin.jar will also work.
NB: Flat dir repositories are discouraged and local maven repo folder should be used instead. Especially in the case when you want to override locally an artifact which exists on a remote repo. See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver. It seems impossible to fully move away from maven in favour of gradle, considering that installing local artifacts in a maven repo folder is not supported by gradle itself.

Including Java library built with Gradle throws NoClassDefFoundError

I am writing a Java library and I would like to build the library with Gradle and then test it from a local test project.
I would prefer using Gradle 3.3 for my objective.
The library should be built for Java5 and higher.
So far my build.gradle looks like this:
plugins {
id 'jvm-component'
id 'java-lang'
}
repositories {
mavenCentral()
}
model {
components {
main(JvmLibrarySpec) {
sources {
java {
dependencies {
module 'commons-codec:commons-codec:1.10'
module 'org.apache.httpcomponents:httpcore:4.4.6'
module 'org.apache.httpcomponents:httpclient:4.5.3'
}
}
}
api {
exports 'io.simplepush'
}
targetPlatform 'java5'
}
}
}
The source code of the library is located in src/main/java/io/simplepush/Notification.java and depends on the dependencies stated in the build.gradle file.
Building the library with ./gradlew build works fine and generates build/jars/main/jar/main.jar.
However when I run a test project from IntelliJ (after including main.jar into the test project), I get the following runtime error:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity.
It seems like the test project does not know about the runtime dependencies needed by my library.
I am not sure on what is the correct way to tell the test project about the dependencies of my library.
I do not want a fat jar which includes all dependencies.
Listing all dependencies in the test project itself is also not an option.
Preferably I want the library itself to tell the test project about which dependencies it needs.
The library jar which you have created does not contain any dependency information which the IDE/Gradle can then resolve to be able to compile/run the test project. I see that you are using the maven central repository so what you need to do is to publish your library to your local maven repository and in the test project just add a dependency information (no just plain jar file).
So in both library and test project build.gradle add a maven local repository config.
repositories {
mavenLocal()
mavenCentral()
}
And now you need to publish the library to local repository. As you are using the gradle 3.3 you can use the Maven Publishing.
So in the library build.gradle add a maven publishing information.
publishing {
publications {
maven(MavenPublication) {
groupId 'io.simplepush'
artifactId 'project1-sample'
version '1.1'
from components.java
}
}
}
Gradle “maven-publish” plugin makes this easy to publish to local repository automatically creating a PublishToMavenLocal task.
So you can just run
gradle publishToMavenLocal
Which will publish your library with all the dependency information into local maven repository.
And then you just need to add a library information to you test projects build.gradle
dependencies {
// other dependencies .....
module 'io.simplepush:project1-sample:1.1'
}
I solved it by changing several things.
Thanks to #Babl for pointing me in the right direction.
My new library build.gradle looks like this:
plugins {
id 'java'
id 'maven-publish'
}
sourceCompatibility = 1.5
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'commons-codec:commons-codec:1.10'
compile 'org.apache.httpcomponents:httpcore:4.4.6'
compile 'org.apache.httpcomponents:httpclient:4.5.3'
}
publishing {
publications {
maven(MavenPublication) {
groupId 'io.simplepush'
artifactId 'project1-sample'
version '1.1'
from components.java
}
}
}
Now I can push the library to the local maven repository with ./gradlew publishToMavenLocal.
The build.gradle of the test project uses the application plugin and defines a main class (which is Hello in my case). Then I can run ./gradlew installDist to generate an executable file (see Application plugin docs) which puts all dependencies in the classpath and runs just fine.
group 'com.test'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'application'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'io.simplepush:project1-sample:1.1'
}
mainClassName = "Hello"
This specify what repositories to check to fetch the dependencies from
repositories {
mavenCentral()
}
Therefore, anything that is in the dependecies{} will be fetched from those above.
If the test project is not coupled with the library project, (#RaGe example) new test project needs to know where to take the dependency from - you need to publish it, using preferred method.
After that, your new test project needs to specify the library with the preferred configuration (compile...runtime etc) in the build.gradle dependencies{}
After that depending on IDE you need to refresh the classpath and download the dependency from the specified before repository, the transitive dependencies specified in the library dependency (in this case) will get fetched from test projects repositories{}
Library build.gradle
repositories {
mavenCentral()
}
dependencies {
module 'commons-codec:commons-codec:1.10'
module 'org.apache.httpcomponents:httpcore:4.4.6'
module 'org.apache.httpcomponents:httpclient:4.5.3'
}
test project build.gradle
repositories {
mavenCentral() repository to fetch transitives
mavenLocal() or any other repo that you published the library to
}
dependencies {
pref-conf librarygroup:name:version
}
You can use idea or eclipse plugin in gradle for gradle idea or gradle eclipseClasspath tasks to refresh it with your freshly added dependencies.
With this solution, you should not need to pack the transitive dependencies within the library,
PS. I am just confused after you said you want executable jar.

Neokree Navigation drawer: Gradle DSL method not found: 'compile()'

I am trying to Set up a Navigation Drawer by Neokree https://github.com/neokree/MaterialNavigationDrawer on Android Studio with no success.
After adding this to my gradle -> build.gradle file
repositories {
mavenCentral()
}
dependencies {
compile 'it.neokree:MaterialNavigationDrawer:1.3.3'
}
And then i get this Error Saying "Gradle project Sync Failed" and this below
Error:(27, 0) Gradle DSL method not found: 'compile()'
Possible causes: The project 'MaterialNavigationDrawer' may be using a version of Gradle that does not contain the method.
Gradle settings The build file may be missing a Gradle plugin.
Apply Gradle plugin.
This is my gradle folder -> Build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
}
repositories {
mavenCentral()
}
dependencies {
compile 'it.neokree:MaterialNavigationDrawer:1.3.3'
}
I know am doing something wrong for sure, and I can't seem to figure it out.
There is a great library called MaterialDrawer. You can integrate this library in less than 5 minutes in your project (read its README.md and Wiki - a lot of informations is available there!).
Good luck!

Confused about dependencies in local respository(gradle)

I trying to compile and package up my java application but I am facing issues when trying to specify my local repository in which I have my jars that will be used as dependencies. I have stored all the jars I need for my application in '/home/test/lib'. What I have as my build.gradle file is as follows:
apply plugin:'application'
apply plugin:'java'
apply plugin:'idea'
def repositoryPath = '/home/test/lib'
repositories {
repositoryPath
}
dependencies {
"org.springframework:spring-orm:3.0.2.RELEASE"
"org.springframework:spring-context-support:3.0.2.RELEASE"
'commons-dbcp:commons-dbcp:1.4'
'org.apache.ibatis:ibatis-sqlmap:2.3.4.726'
'commons-dbutils:commons-dbutils:1.3'
'joda-time:joda-time:1.6'
'commons-lang:commons-lang:2.5'
'com.google.collections:google-collections:1.0'
}
jar {
baseName = 'testJar'
}
mainClassName = "com.some.test.testRunner"
When I run gradle build, I am getting "package * does not exist" errors.
My assumption is that gradle is not finding the requisite external jars in my lib folder. Can somebody point out what I may be doing wrong here.
Thanks
some remarks about your build file. I assume you have a flat directory in '/home/test/lib' that contains your third party libs? If this is the case you can use a flatDir repository, that is declared with the following syntax:
def repositoryPath = '/home/test/lib'
repositories {
flatDir {
dirs repositoryPath
}
}
If /home/test/lib is a ivy repository, you can do:
repositories {
ivy {
url repositoryPath
}
}
This is explained in detail in the Gradle user guide.
in your 'dependencies' section you missed to declare the scope of your dependencies (compile, runtime, etc):
dependencies {
compile "org.springframework:spring-orm:3.0.2.RELEASE"
compile "org.springframework:spring-context-support:3.0.2.RELEASE"
compile 'commons-dbcp:commons-dbcp:1.4'
compile 'org.apache.ibatis:ibatis-sqlmap:2.3.4.726'
compile 'commons-dbutils:commons-dbutils:1.3'
compile 'joda-time:joda-time:1.6'
compile 'commons-lang:commons-lang:2.5'
compile 'com.google.collections:google-collections:1.0'
}
if you use a flatdir repository, the group of your dependency definition is often omitted:
dependencies {
compile ":spring-orm:3.0.2.RELEASE"
...
}
Have a look at the gradle user guide for detailed information about dependency handling with gradle: http://gradle.org/docs/current/userguide/userguide_single.html#artifact_dependencies_tutorial
regards,
René

Categories