In the gradle documentation (sec. 8.3) defined the java plugin classpath.
In Gradle dependencies are grouped into configurations. A
configuration is simply a named set of dependencies. We will refer to
them as dependency configurations. You can use them to declare the
external dependencies of your project. As we will see later, they are
also used to declare the publications of your project.
Is it the same as the Java classpath we define as export CLASSPATH = ...?
Adding comment as answer with an example
It is more than that. Think of it as a bucket which handles dependencies. From Java plugin, we get configurations like compile, runtime, testCompile etc which handles dependencies in respective manner. You can have your own configuration and use that configuration for any dependency. Now what you do with that configuration dictates how you handle the dependencies under that configuration.
For example, here is a sample configuration setup which extracts a zip archive and copies its content to a directory.
configurations {
extractZips // custom configuration
}
dependencies {
extractZips 'com.mycompany:my-dependency:0.1#zip'
}
// Task configured to copy contents from zip archive
task extractZip(type: Copy) {
from zipTree( configurations.extractZips.singleFile )
into "$projectDir/zips" // for example
}
Related
I added this artifact which is a war to my gradle project dependencies.
I need to extend some classes, and use a modified servlet contexts from it.
I was expecting the war to be imported as is then I would use gradle tasks to manipulate to include the jars to dependencies, copy static resources to correct classpath etc.
But gradle actually added a bunch of jars to dependency.
Im not sure if gradle scanned recursively all paths for jars and poms or probably just the jars under the WEB-INF/classes folder in the war.
I can assume probably not the poms repositories as stated here.
Im I correct is assuming the jars in the WEB-INF/lib folder in the deflated war were not imported? its hard to tell as there are a lot of shared dependencies between my project and the war in question
Then whats the best way to declare a dependency on a war in the maven repo/jcenter if I need to extend and modify as I described at the top?
UPDATE:
I am now trying to use answer below and this solution https://discuss.gradle.org/t/how-to-add-an-artifactory-war-as-a-gradle-dependency/19804/2
, This only worked after moving the directory with the copied jars outside the buildDir
my build.gradle
configurations {
warOnly
}
dependencies {
// not working implementation fileTree('$buildDir/explodedWar/WEB-INF/classes')
implementation fileTree('anotherDir/explodedWar/WEB-INF/classes')
// implementation fileTree('$buildDir/explodedWar/WEB-INF/lib')
implementation fileTree('anotherDir/explodedWar/WEB-INF/lib')
warOnly 'ca.uhn.hapi.fhir:hapi-fhir-jpaserver-starter:4.2.0#war'
}
tasks.register("explodeWar",Copy) {
from zipTree(configurations.warOnly.singleFile)
// into "${buildDir}/explodedWar"
into "anotherDir/explodedWar"
}
compileJava {
dependsOn explodeWar
}
By declaring a dependency on a WAR, Gradle will simply add it to the list of files for the matching configuration. So if you add a WAR in implementation, it will simply be on the compileClasspath and runtimeClasspath without any processing.
So for sure Gradle will not transform your WAR dependency in a dependency on the JARs it contains.
If you want to use a WAR to copy and modify some of its content before repackaging it, you can use an isolated and custom configuration to resolve it from a remote repositories. Then you will define a Gradle task that will take the files of that configuration as the input and do the required processing on the WAR. Note that the task could also be the starting point of a series of tasks manipulating the WAR to one output, then that output to another one, etc ...
configurations {
warOnly
}
dependencies {
warOnly "com.pany:some-war:1.0"
}
tasks.register("copyWar", Copy) { // Register a copy task to modify the WAR
from(zipTree(configurations.warOnly)) // I did not run this, so you may have to get to the single file instead
// Regular copy configuration to decide a destination, perform on the fly changes, etc ...
}
It took some trail and error but there is better way. When using the dependency:
providedCompile 'ca.uhn.hapi.fhir:hapi-fhir-testpage-overlay:6.0.1'
Gradle will download a war file and place it you your classpath. However providing a classifier will help here. The following dependency will get the jar file.
providedCompile (group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-testpage-overlay', version:'6.0.1', classifier: 'classes')
I am building a library, which has separate entry points (like server, gui), with different dependencies. Each entry point is in a separate sub project with its own dependencies.
In the root project, where I start the build from, I want to select the entry point, and only build with that dependencies. That is working.
But I want to instantiate a class (eg MainClass) of the root project from the library entry point and I cant add the root projects class path to the dependency. (Diagram)
Root projects build file looks like this now:
dependencies{
implementation project(':server')
}
It seems to me that it would be easier to understand and clearer if the entry point projects depended on the core API instead of vice versa.
You could have project structure like:
settings.gradle
core/
build.gradle
src/
server/
build.gradle
src/
gui
build.gradle
src/
server and gui project build.gradle files should contain:
dependencies {
implementation project(':core')
}
The project that uses the library could depend on Server and/or GUI projects and instantiate the necessary class (ServerEntry or GuiEntry) directly.
If you want to be able to switch between different entry point implementations without changing the code in the project that uses the entry point instance I'd suggest using a dependency injection framework (Spring, Guice, Dagger). Dependency injection would help to separate configuration (binding interfaces to classes) from the actual application.
I solved my problem with Composite build. I added includeBuild '../path-to-lib' in the settings.gradle, Than I created a subproject Project to the library with the proper package and class name. On run it throws an error, that the developer should create this class.
Its also important to add all the subprojects to the same group:
allprojects{
group = 'library-group'
}
In the host project, I can depend on the library:
dependencies{
implementation module('library-group:suproject')
}
Now Gradle automatically overwrites the Classes on the same route as the documentation suggest, and I can finally inject my host project into the lib, and compile it as a whole.
We're currently deploying our Flink applications as a fat-jar using the maven-shade-plugin. Problem is, each application jar ends up being approximately 130-140 MB which is a pain to build and deploy every time. Is there a way to exclude dependencies and just deploy a thin jar to the cluster which comes up to about 50 kB?
You can place the dependency JARs in the cluster beforehand in Flink's lib (see Avoid Dynamic Classloading) and just upload the thin JAR on each job submission.
Here's how we do it with Gradle!
We have two sub-projects:
job: For the stream job that we want to run
runtime: For additional runtime dependencies (e.g. a custom FileSystem implementation)
We create a new gradle configuration for dependencies that are provided at runtime:
configurations {
provided,
compile.extendsFrom provided
}
and then mark the provided dependencies as:
provided("org.apache.flink:flink-java:1.6.0") // flink java v1.6.0
Then, we modify the jar task to build a jar without any provided dependencies:
jar {
dependsOn configurations.runtime
from {
(configurations.runtime - configurations.provided).collect {
it.isDirectory()? it : zipTree(it)
}
} {
exclude 'META-INF/*.RSA'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
}
manifest {
attributes 'Main-Class': 'com.example.Entrypoint'
}
}
The result is a jar with required dependencies (compile) bundled which we then deploy using the Web UI.
As for the custom runtime dependencies, we build a custom Docker image and push the built artifact (runtime.jar, built using same configuration as above) to the libs/directory in Flink. You can do that manually too if you are not using Docker.
And, lastly, in our particular case there is no direct dependency defined between our job and the runtime dependency (which is discovered using reflection).
I'm new to both using gradle and springframework.
How can I use springframework as a gradle plugin without using any external repositories (including a local maven repository.)? i.e. just use dowloaded springframework files, place them on my local directory and tell gradle to reference to them instead.
You may be looking for Flat directory repository:
Some projects might prefer to store dependencies on a shared drive or
as part of the project source code instead of a binary repository
product.
As an example, in the build.gradle add:
repositories {
flatDir {
dirs 'lib'
}
flatDir {
dirs 'lib1', 'lib2'
}
}
This adds repositories which look into one or more directories for
finding dependencies. Note that this type of repository does not
support any meta-data formats like Ivy XML or Maven POM files.
Instead, Gradle will dynamically generate a module descriptor (without
any dependency information) based on the presence of artifacts.
However, as Gradle prefers to use modules whose descriptor has been
created from real meta-data rather than being generated, flat
directory repositories cannot be used to override artifacts with real
meta-data from other repositories. For example, if Gradle finds only
jmxri-1.2.1.jar in a flat directory repository, but jmxri-1.2.1.pom in
another repository that supports meta-data, it will use the second
repository to provide the module.
I have a java gradle project. I have a dependency.
dependencies {
compile project(":mymodule")
compile 'org.springframework:spring-context:4.1.2.RELEASE'
}
Where can I find and use exact jar file name of both my custom module and spring dependency jar to process it further in composing application's libs, folders, etc?
Stick this in a new task:
project.configurations.compile.each{ println it}
Or, for just one specific dependency:
println project.configurations.compile.find {it.name.startsWith("something") }
However, if you're looking to create distributable packages including dependencies, you really should look into the gradle application plugin.