Some questions about Gradle for Android Development - java

I have some questions about Gradle.
What is the difference between buildscript.dependencies and
dependencies ?
What is the difference between classpath and compile?
What does apply plugin: mean?

Just check their docs, they have described it well. But here is it:
1:
If your build script needs to use external libraries, you can add them
to the script's classpath in the build script itself. You do this
using the buildscript() method, passing in a closure which declares
the build script classpath.
This is good for external dependencies (for example from internet repos which are in buildscript part too.)
2:
Docs with table and descriptions for each.
compile will get dependencies during compiling. (for example you can set 'runtime' and these dependencies will be used during runtime, or testCompile will be used only during compiling tests). This is very important! Read their docs. Of course you can try to compile everything everytime, but this is really bad idea. Good example are JUnit tests, you need JUnit only during compiling tests co then you use compileTest:
testCompile "junit:junit:X.YZ"
3:
It means that you applied plugin :) You apply java, or when you need spring or spring boot, then you simply can tell Gradle, hey Gradle, I am going to using this, so aplly it. More here.

I suggest you download the full Gradle distribution, only because it provides a PDF version of the User Guide (I don't know of any other way to get the user guide PDF). Read it from top to bottom, skipping chapters that are clearly irrelevant to you. You will get answers to all of these questions, and more that you haven't asked yet.
However, I'll give you some brief answers.
Q1: Gradle has dependencies for the build script, and dependencies for the code you're building. They are separate.
Q2: Classpath is a runtime notion used by Java, which Gradle utilizes in different ways. Compile is a "configuration" which you can add dependencies to, which affects the eventual runtime classpath.
Q3: "apply plugin" is applying a Gradle plugin. Read the user guide.

Related

Best way to turn in a java project: Maven vs Simple java project

Here is my situation: I am turning in a coding challenge for an interview. We are allowed to use any programming language, I chose Java. I completed the project and it provides the correct output, but I am stuck on some technicalities of turning it in. The spec says that it will be compiled and run using the terminal on a mac or linux machine, and it says to "turn in source code only, please do not include compilation artifacts or binary dependencies". I have a couple jars as dependencies. Does this mean I can't include them with my source code? How would they compile the program then. Right now I am not using any management tool. I could use Maven and declare the dependencies in the pom.xml, but then I have to assume whoever grades my solution has Maven installed to run "mvn".
Should I stick with a basic java project and include the jars, use Maven instead, or is there another better way to do this? Sorry if I am overthinking this, I want to make it simple to run my project so my work can be assessed for its accuracy, not how I packaged it.
Yes, you can't include any dependencies as JARs. You need to use Maven or Gradle for this.
You don't need to assume that Maven is installed, Maven Wrapper can be used instead.
You can provide mvnw, what stands for maven wrapper. It's project-local installation of maven that is treated as source code and is used by calling ./mvnw instead of global mvn command (to make it working for the first time, use mvn -N io.takari:maven:wrapper). Reference.

How to include Apache Derby as a Gradle dependency using downloaded binaries

I know Java pretty well and am an experienced C/Python programmer, but I may have some fundamental misconceptions when it comes to Gradle.
I'm developing in the terminal and vim, it's just who I am. I have Apache Derby set up on my system: downloaded, environment variables set, etc. I wish to use this in my Java project which I'm building with Gradle, but I don't know how to include it in the dependencies other than from the Maven repository.
If I do:
testCompile group: 'org.apache.derby', name: 'derby', version: '10.5.3.0'
My understanding is that this downloads it from the Maven repo again. Am I going about things the wrong way by wanting to use my system Derby, or is there a way to point Gradle to it? If this question is riddled with misconceptions I would appreciate them being put straight.
Thanks.
+1 for using vim/terminal, that is cool! 😎
Gradle is extremely flexible and will do whatever you ask - although there are best practices, see below. You can have a libs/ folder with all your libraries in it, and point Gradle to it:
dependencies {
implementation fileTree('libs') { include '*.jar' }
}
This will add all JARs in the libs/ folder to your classpath. Gradle calls this a file dependency. The libs folder does not have to be in your project directory, so yes, you can point to your system-wide libs, too.
However.
Gradle has a very advanced caching mechanism, which will minimize network usage and even balance this with local storage requirements. It will also reliably share downloads between projects. You want to use this.
Also, many Java libs have dependencies of their own ("transitive dependencies"), often quite a lot of them, resulting in whole trees of dependencies. Since the transitive closure of all of them will end up on your classpath, there can be conflicts, which Gradle will resolve for you. You will not want to perform manual dependency resolution.
Plus, your project will be easier to compile for others because Gradle will make sure the dependency is loaded and present. Whereas a "system derby" would need to be installed in some other way before running Gradle.
File dependencies have a myriad of other problems as well, so I would urge you to have Gradle handle this for you and use the syntax from your question:
dependencies {
implementation group: 'org.apache.derby', name: 'derby', version: '10.5.3.0'
}
Here's a little more info on so-called "configurations", like testCompile and implementation to help you choose the right ones.
All of this will work perfectly with Vim and terminal. So well in fact that I often call Gradle from a terminal while developing in IntelliJ. 😊

How can I make a simple gradle build script to compile a java program?

I am trying to learn how to use gradle to make compiling and packaging my java programs easier. I already have experience programming in java and usually I just use eclipse to manage this, or, I just compile my programs manually (using javac in a terminal). However, I am getting to a point where I want to use libraries that seem to be easiest to use & maintain with gradle.
To understand more of how gradle works, I went to the gradle site where they have tutorials for making a simple gradle setup for use when writing a java application (this is the one I found). However, this tutorial didn't really explain how any of this was supposed to work, and it seemed to assume that you were following some specific system for the layout of your project. It also included some testing program or something to test your program when you build it. And in addition to these things, it never really explained how running the gradle build function worked or where (and what) the file was that held the instructions for what it was doing when you built the program.
So essentially, I am asking if someone can explain the steps to take to make a simple gradle environment that simply compiles a set of .java files and either puts them in an executable jar or just leaves them as .class files in a separate bin folder or something. It would also be helpful if you explained what each part was doing and how I can make changes to add more stuff (like basic dependencies, maybe adding .exe wrappers around the .jar, etc.)
Let's start with a simple question: What basic steps are required to build a Java project? Well, as long as your project is not using some fancy preprocessing or code generation, the first step will probably be the compilation of .java files to .class files. Those .class files (and resources, if provided) may then be packed into a .jar file. It may not seem obvious to you right now, but in general, you also should run (unit) tests when your project is built. Depending on your project, there may be many more possible steps (e.g. publishing, documentation, quality control).
In Gradle, those steps are called tasks. A task can basically do anything that helps you build your software. This often means that a task takes some input files and transforms them to some output files. As an example, a compilation task transforms .java files to .class files. Another task can transform .class files to a .jar file (lets call this task jar task). Since the .class files need to be created to put them into a .jar file, the jar task depends on the compilation task. You can express this relation using Gradle, so every time the jar task runs, Gradle will ensure that the compilation task has run beforehand. Tasks do not need to do something, they might just be used to express such relations (such a task is called a lifecycle task). You may create tasks of a specific task type to reuse functionality, for a example two different tasks may be used to compile production code and test code, but both internally use a compiler and just operate on a different set of input files.
You can create tasks manually and I definitively encourage you to create some tasks to understand how their relations and their execution works, but quite often you don't need to create tasks in your build scripts, because all necessary tasks are created by plugins. Gradle plugins are really mighty, as they can basically do everything you could do manually in your build script and there is a plugin for almost everything you might want to do in your build process.
[...] I am asking if someone can explain the steps to take to make a simple gradle environment that simply compiles a set of .java files [...]
The easiest way to compile a Java project using Gradle is to create a file build.gradle with the following content:
plugins {
id 'java'
}
That's it! Gradle is ready to build your project (just run gradle build). How is this possible? Well, the Java plugin creates all the necessary tasks to compile, test and pack your project and configures them to follow the common conventions. Take a look at the documentation of the Java plugin, it even includes a nice image that shows all the tasks and their dependencies. As shown by the image, the build task depends on all other tasks. This task is executed when you call gradle build. You can also call gradle jar or gradle assemble and Gradle will only run the tasks that are required to build the .jar file.
[...] it seemed to assume that you were following some specific system for the layout of your project.
Yes, Gradle follows an approach called convention over configuration. This means that there is a (somehow common or useful) convention for everything that otherwise would have to be configured manually.
A simple example for this approach is the location where source and resource files are expected. As you can see, this location is not configured in the build script above. However, there is a convention (established by Maven) that .java source files should go into src/main/java for production code and src/test/java for test code. Of course, those paths may be changed, but in most projects you should simply stick to the conventions.
It would also be helpful if you explained what each part was doing and how I can make changes to add more stuff (like basic dependencies [...])
Let's simply take a look at the build file in your tutorial:
plugins {
id 'application'
}
repositories {
jcenter()
}
dependencies {
testImplementation 'junit:junit:4.13'
implementation 'com.google.guava:guava:29.0-jre'
}
application {
mainClass = 'demo.App'
}
The first block is similar to the example above, but instead of the plugin with the identifier java the plugin with the identifier application is applied. However, this won't change much as the Application plugin internally applies the Java plugin, too.
Now let's take a look at the blocks repositories and dependencies. The dependencies block can be used to register dependencies. You may add dependencies on local .jar files, on other Gradle projects (in multi-project builds) or on external modules. The word external refers to remote repositories that provide libraries that you may use in your project. The lines inside the dependencies block each denote a specific dependency by defining the dependency scope and a module identifier that consists of a group identifier, an artifact identifier and a version (using : as a separator). The dependency scope (also called configuration in Gradle) basically defines where and how a dependency may be used. As an example, the first dependency can only be used in test code (due to the testImplementation scope). Now Gradle knows what library is required to build the project, but it does not know where to get that library. Here the repositories block comes to the rescue, because it can be used to define where Gradle should look for external module dependencies. Most of the time you will mainly use jcenter(), mavenCentral() or google(), however it is also possible to add repositories accessible under custom URLs.
The last part applies a configuration that is necessary, because no useful convention can be applied. Gradle simply does not know which class in your project should be used as the main class of your application, so you must define it manually.
Now, thanks to the Application plugin, you may not only build your project using gradle build, but also run your application from Gradle using gradle run, as the task run is one of the tasks created on top of the tasks created by the Java plugin.

Configure Gradle project to tell JAR to look in specific folder for dependency artifacts at runtime

Apologies if this question has already been asked, the barrier to entry with Gradle seems very high and I'm not sure what to search for.
My Kotlin project depends on various artifacts to offer the Kotlin runtime, such as kotlin-stdlib-jdk8-1.2.60.jar, for example.
The Kotlin library is being loaded by a raw Java application.
I need to inform the Kotlin library JAR that I am distributing to look in the /kotlin directory (relative to the directory in which it will be placed) for its runtime libraries and any other dependencies. From what I have seen, I need to add this to the runtimeClasspath or similar but I am unsure how.
Thanks for any help.
If your jars are public for the world, you would only need to declare them in your build.gradle (module, not project) like
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
Gradle would pick them up, no need to store them in your project.

How to specify dependency on tomcat libraries with gradle

A bit of background about my knowledge level: I'm currently trying to learn how to build a project with gradle. So far I don't have much experience with build tools (almost none). I do understand the general idea and have seen ant and maven files before but never written them myself. Until now I just used other peoples build scripts or configured my builds using Eclipse. So I might be on a completely wrong track here, if so please point me in the correct direction.
Also, I sadly don't have much experience building jars by hand.
I have an Eclipse project which I want to compile into a jar. Required library jars are on my local file system. I managed to make gradle use these via
dependencies {
compile fileTree(dir:'lib', include:'*.jar')
}
in addition I have my source files in src/main/java and just use apply plugin: 'java' in the build.gradle file. Trying to build the project with gradle build seems to do the right thing, as far as I can tell.
However, the library is supposed to be used in a web project running on a tomcat and makes use of some libraries that are supplied by tomcat, as far as I understand. E.g. I'm using javax.servlet.http.HttpServletRequest.
The project works fine in Eclipse, but there I have the tomcat library added to my Eclipse build path. When I check in Eclipse I can see that javax.servlet.http.HttpServletRequest is part of the servlet-api.jar which is part of the Tomcat library.
Now, when I build the project I get build errors because the java compiler cannot find the class because I didn't specify the servlet-api.jar in the dependencies. I guess I could download it somehow (or learn how to specify it as an external dependency to make gradle download it from some repository) but I am not sure whether that would be correct.
Is there a way to tell gradle to use the same library that Eclipse uses? Or some other general way to tell it about all the tomcat jars, the same way I can simply add the complete Tomcat library in Eclipse?
Or do I actually need another copy of these jars somehow and have to specify each one individually?
Also, do I need to add these library jars to my build-result library jar? As far as I know I need to add any jar I depend on to the resulting jar as well. But then again, I have read somewhere that some libraries are supplied by tomcat itself so they would have to be part of any war deployed on it.
I'm afraid, I'm confused by the combination of how to build a jar-file to be used in a war-file to be deployed on a tomcat using gradle and I don't know from which of these parts my problems originate. I hope someone reading this can help me untangle my thoughts and point me in the right direction or at least tell me how to add the jars included in the Tomcat library to my gradle dependencies.
With Gradle, whenever you add files or directories as dependencies, they are not treated as full-fledged artifacts (with group, name and version), but rather as simple files containing classes. It means that Gradle will not perform any conflicts resolutions on them, or pull transitive dependencies.
For you, just to get started, I recommend just to add tomcat dependency. Make sure it is the same version as the one in Eclipse.
apply plugin: 'war'
repositories {
mavenCentral()
}
dependencies {
providedCompile 'org.apache.tomcat:tomcat-catalina:7.0.47'
}
Also, look into Eclipse Integration Gradle project as a long-term solution.

Categories

Resources