I'm using gradle V4.10.2 and eclipse for building WAR files. I have some common JAR files for all the wars. I need them to use only during compile time and need to exclude them while building into WAR file. Also I don't want to exclude all the JARs file.
I've put all the JARs in libs folder. In build.gradle, I have specified only the JARs to be included. Since the exclude list is bigger then include list of JARs I'm not using exclude
war {
rootSpec.include("**/test.jar")
}
The above results the WAR file without META-INF folder. Hence, webapp is not started. I have tried adding the libs as reference lib in eclipse but that results in compilation error.
Execution failed for task ':compileJava'.
Compilation failed; see the compiler error output for details
So I have to include all the JARs in libs folder and then need to use only required JARs in the WAR built. How to include only specific JARs into build?
I strongly recommend reading about building Java projects with Gradle and in particular the part about web applications
In short you should add the JARs needed for compilation only to the compileOnly configuration and the JARs needed for compilation and at runtime in the implementation configuration.
Gradle will then use all of them for compilation and only include the ones in implementation when packaging the WAR.
While you can do that by selecting them from your libs folder, I strongly recommend moving to libraries and its metadata sourced from a repository, private or public, so that the dependency management is done for you.
Related
I’m using https://github.com/googlemaps/google-maps-services-java in an app which has a WAR file contained in an EAR file deployed to a web server. Following the readme, I added:
repositories {
mavenCentral()
}
dependencies {
implementation ‘com.google.maps:google-maps-services:(insert latest version)’
implementation ‘org.slf4j:slf4j-simple:1.7.25’
}
to build.gradle for my WAR. This builds successfully and I can see the library included in my Eclipse environment. However, when I build the EAR and deploy it, I see:
java.lang.NoClassDefFoundError: com.google.maps.GeoApiContext$Builder
indicating to me that the dependency isn’t being included in the EAR. Presumably, I need to edit build.gradle for the EAR, but it’s not clear to me how to do this. Copying the same edits from the WAR build file causes the compilation to fail:
Could not find method implementation() for arguments [com.google.maps:google-maps-services:0.10.1] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
Could anyone explain to me how to tell Gradle to include this library in the EAR?
My directory sturcture is,
C:\Grapher\src\ *.java
C:\Grapher\lib\ *.jar
There are many java files and many jar dependencies. I want to create a tomcat deployable WAR.
Can any one suggest me how to create a WAR using a gradle script? What are the dependencies to be included in Gradle to create a WAR.
Have you read and understood https://docs.gradle.org/current/userguide/war_plugin.html?
The War plugin adds two dependency configurations named providedCompile and providedRuntime. Those two configurations have the same scope as the respective compile and runtime configurations, except that they are not added to the WAR archive. It is important to note that those provided configurations work transitively. Let's say you add commons-httpclient:commons-httpclient:3.0 to any of the provided configurations. This dependency has a dependency on commons-codec. Because this is a “provided” configuration, this means that neither of these dependencies will be added to your WAR, even if the commons-codec library is an explicit dependency of your compile configuration. If you don't want this transitive behavior, simply declare your provided dependencies like commons-httpclient:commons-httpclient:3.0#jar.
If you use providedCompile or providedRuntime, those dependencies will not be added to your war archive.
The folder structure you need to have in your project is:
app
|-src
|-main
|-java
|-webapp
In the java folder you add your own packages and classes. In the webapp folder you add web content if your application makes use of such items.
What is the difference between the maven scope compile and provided when artifact is built as a JAR? If it was WAR, I'd understand - the artifact would be included or not in WEB-INF/lib. But in case of a JAR it doesn't matter - dependencies aren't included. They have to be on classpath when their scope is compile or provided. I know that provided dependencies aren't transitive - but is it only one difference?
From the Maven Doc:
compile
This is the default scope, used if none is specified. Compile
dependencies are available in all classpaths of a project.
Furthermore, those dependencies are propagated to dependent projects.
provided
This is much like compile, but indicates you expect the JDK or a
container to provide the dependency at runtime. For example, when
building a web application for the Java Enterprise Edition, you would
set the dependency on the Servlet API and related Java EE APIs to
scope provided because the web container provides those classes. This
scope is only available on the compilation and test classpath, and is
not transitive.
Recap:
dependencies are not transitive (as you mentioned)
provided scope is only available on the compilation and test classpath, whereas compile scope is available in all classpaths.
provided dependencies are not packaged
Compile means that you need the JAR for compiling and running the app. For a web application, as an example, the JAR will be placed in the WEB-INF/lib directory.
Provided means that you need the JAR for compiling, but at run time there is already a JAR provided by the environment so you don't need it packaged with your app. For a web app, this means that the JAR file will not be placed into the WEB-INF/lib directory.
For a web app, if the app server already provides the JAR (or its functionality), then use "provided" otherwise use "compile".
Here is the reference.
If you're planning to generate a single JAR file with all of its dependencies (the typical xxxx-all.jar), then provided scope matters, because the classes inside this scope won't be package in the resulting JAR.
See maven-assembly-plugin for more information
compile
Make available into class path, don't add this dependency into final jar if it is normal jar; but add this jar into jar if final jar is a single jar (for example, executable jar)
provided
Dependency will be available at run time environment so don't add this dependency in any case; even not in single jar (i.e. executable jar etc)
For a jar file, the difference is in the classpath listed in the MANIFEST.MF file included in the jar if addClassPath is set to true in the maven-jar-plugin configuration. 'compile' dependencies will appear in the manifest, 'provided' dependencies won't.
One of my pet peeves is that these two words should have the same tense. Either compiled and provided, or compile and provide.
If jar file is like executable spring boot jar file then scope of all dependencies must be compile to include all jar files.
But if jar file used in other packages or applications then it does not need to include all dependencies in jar file because these packages or applications can provide other dependencies themselves.
I have zip dependency from repository. It has 50+ jars in it. I am able to download it and unpack it. Now I want to add these jars to classpath for compilation. these jars not getting added to classpath, so build is failing with compiler errors. I need these jars only for compilation(not in war).
I spent two days didn't satisfacoty solution(don't want to use system scope, local repository). I this link How to put maven zip dependency on classpath for Java tests. it didn't work because may be its for test not for compile. I need same thing for compile.
I'm building an Android app that has a dependency on a custom library, and Gradle is only willing to include my custom library when I use a project dependency, not when I use a files dependency to include the library's jar file. I'm building both my app and the library with the API levee 19 SDK.
failing dependencies section from build.gradle:
dependencies {
compile 'com.android.support:appcompat-v7:+'
compile files('libs/MyLibrary.jar')
}
If I use the above dependencies section, none of the class in MyLibrary.jar are included in the build apk file, as verified by extracting its classes.dex and running dexdump. I have also verified that all of the classes are present in the jar file I'm using.
If I use the following dependencies section, then all of the classes in MyLibrary are included in the apk file:
dependencies {
compile 'com.android.support:appcompat-v7:+'
compile project(':MyLibrary')
}
I'm using Android Studio 0.4.0, Gradle 1.9, and I think the Gradle plugin 0.7.1.
What is going on here? I'd really like to build my app with the API level 18 sdk to test compatibility, but I can't get that working unless I'm able to just use the jar file for my library.
Okay, this was my fault. My library's build.gradle was configured to only include the source files in the jar output file. The following is incorrect Gradle code and will give you the same problems as I've had.
task jar(type: Jar) {
from android.sourceSets.main.java
}
This answer shows how to fix the jar file creation. It's ugly, but it seems to work.
Jar task does not include dependencies in the final jar artifact.
From Gradle documentation on jar task:
The jar task creates a JAR file containing the class files and
resources of the project.
It assumes that since you are building jar for your project, all dependencies will be provided during runtime. As opposed to war, where all dependencies are usually included in the final artifact.
If you need to create "fat jar", which will include the dependencies, then look into specific plugins, for example gradle-fatjar-plugin.
It's a little bit of a longshot, but if you're not using Android Studio 0.4.0 and you've just added the jar file, try cleaning your project and rebuilding from scratch. We've seen this bug: https://code.google.com/p/android/issues/detail?id=63366 where libraries don't get included without cleaning the project, though this bug refers to a dependency downloaded from Maven and not a local jar file (which may or may not be an important difference). This was fixed in Android Studio 0.4.0 (more specifically, in the Gradle plugin 0.7.0).