// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[application_plugin]]
= The Application Plugin

The Application plugin facilitates creating an executable JVM application. It makes it easy to start the application locally during development, and to package the application as a TAR and/or ZIP including operating system specific start scripts.

Applying the Application plugin also implicitly applies the <<java_plugin.adoc#java_plugin,Java plugin>>. The `main` source set is effectively the "application".

Applying the Application plugin also implicitly applies the <<distribution_plugin.adoc#distribution_plugin,Distribution plugin>>. A `main` distribution is created that packages up the application, including code dependencies and generated start scripts.


[[sec:application_usage]]
== Building JVM applications

To use the application plugin, include the following in your build script:

.Using the application plugin
====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=use-plugin]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=use-plugin]"]
====

The only mandatory configuration for the plugin is the specification of the main class (i.e. entry point) of the application.

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=mainClass-conf]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=mainClass-conf]"]
====

You can run the application by executing the `run` task (type: link:{javadocPath}/org/gradle/api/tasks/JavaExec.html[JavaExec]). This will compile the main source set, and launch a new JVM with its classes (along with all runtime dependencies) as the classpath and using the specified main class. You can launch the application in debug mode with `gradle run --debug-jvm` (see link:{javadocPath}/org/gradle/api/tasks/JavaExec.html#setDebug-boolean-[JavaExec.setDebug(boolean)]).

Since Gradle 4.9, the command line arguments can be passed with `--args`. For example, if you want to launch the application with command line arguments `foo --bar`, you can use `gradle run --args="foo --bar"` (see link:{javadocPath}/org/gradle/api/tasks/JavaExec.html#setArgsString-java.lang.String-[JavaExec.setArgsString(java.lang.String)].

If your application requires a specific set of JVM settings or system properties, you can configure the `applicationDefaultJvmArgs` property. These JVM arguments are applied to the `run` task and also considered in the generated start scripts of your distribution.

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=application-defaultjvmargs]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=application-defaultjvmargs]"]
====

If your application's start scripts should be in a different directory than `bin`, you can configure the `executableDir` property.

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=executableDir-conf]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=executableDir-conf]"]
====

[[sec:application_modular]]
== Building applications using the Java Module System

Gradle supports the building of https://www.oracle.com/corporate/features/understanding-java-9-modules.html[Java Modules] as described in the <<java_library_plugin.adoc#sec:java_library_modular,corresponding section of the Java Library plugin documentation>>.
Java modules can also be runnable and you can use the application plugin to run and package such a modular application.
For this, you need to do two things in addition to what you do for a non-modular application.

First, you need to add a `module-info.java` file to describe your application module.
Please refer to the <<java_library_plugin.adoc#sec:java_library_modular,Java Library plugin documentation>> for more details on this topic.

Second, you need to tell Gradle the name of the module you want to run in addition to the main class name like this:

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=mainModule-conf]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=mainModule-conf]"]
====

That's all.
If you run your application, by executing the `run` task or through a <<#sec:the_distribution,generated start script>>, it will run as module and respect module boundaries at runtime.
For example, reflective access to an internal package from another module can fail.

The configured _main class_ is also baked into the `module-info.class` file of your application Jar.
If you run the modular application directly using the `java` command, it is then sufficient to provide the module name.

[[sec:the_distribution]]
== Building a distribution

A distribution of the application can be created, by way of the <<distribution_plugin.adoc#distribution_plugin,Distribution plugin>> (which is automatically applied). A `main` distribution is created with the following content:

.Distribution content
[%header%autowidth]
|===
| Location | Content

| (root dir)
| `src/dist`

| `lib`
| All runtime dependencies and main source set class files.

| `bin`
| Start scripts (generated by `startScripts` task).
|===

Static files to be added to the distribution can be simply added to `src/dist`. More advanced customization can be done by configuring the link:{javadocPath}/org/gradle/api/file/CopySpec.html[CopySpec] exposed by the main distribution.

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=distribution-spec]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=distribution-spec]"]
====

By specifying that the distribution should include the task's output files (see <<incremental_build.adoc#sec:task_inputs_outputs, incremental builds>>), Gradle knows that the task that produces the files must be invoked before the distribution can be assembled and will take care of this for you.

You can run `gradle installDist` to create an image of the application in `build/install/__projectName__`. You can run `gradle distZip` to create a ZIP containing the distribution, `gradle distTar` to create an application TAR or `gradle assemble` to build both.

[[sec:customizing_start_script_generation]]
=== Customizing start script generation

The application plugin can generate Unix (suitable for Linux, macOS etc.) and Windows start scripts out of the box.
The start scripts launch a JVM with the specified settings defined as part of the original build and runtime environment (e.g. `JAVA_OPTS` env var).
The default script templates are based on the same scripts used to launch Gradle itself, that ship as part of a Gradle distribution.

The start scripts are completely customizable.
Please refer to the documentation of link:{groovyDslPath}/org.gradle.jvm.application.tasks.CreateStartScripts.html[CreateStartScripts] for more details and customization examples.

[[sec:application_tasks]]
== Tasks

The Application plugin adds the following tasks to the project.

`run` — link:{groovyDslPath}/org.gradle.api.tasks.JavaExec.html[JavaExec]::
_Depends on_: `classes`
+
Starts the application.

`startScripts` — link:{groovyDslPath}/org.gradle.jvm.application.tasks.CreateStartScripts.html[CreateStartScripts]::
_Depends on_: `jar`
+
Creates OS specific scripts to run the project as a JVM application.

`installDist` — link:{groovyDslPath}/org.gradle.api.tasks.Sync.html[Sync]::
_Depends on_: `jar`, `startScripts`
+
Installs the application into a specified directory.

`distZip` — link:{groovyDslPath}/org.gradle.api.tasks.bundling.Zip.html[Zip]::
_Depends on_: `jar`, `startScripts`
+
Creates a full distribution ZIP archive including runtime libraries and OS specific scripts.

`distTar` — link:{groovyDslPath}/org.gradle.api.tasks.bundling.Tar.html[Tar]::
_Depends on_: `jar`, `startScripts`
+
Creates a full distribution TAR archive including runtime libraries and OS specific scripts.

[[sec:application_extension]]
== Application extension

The Application Plugin adds an extension to the project, which you can use to configure its behavior. See the link:{groovyDslPath}/org.gradle.api.plugins.JavaApplication.html[JavaApplication] DSL documentation for more information on the properties available on the extension.

You can configure the extension via the `application {}` block shown earlier, for example using the following in your build script:

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=executableDir-conf]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=executableDir-conf]"]
====

[[sec:application_licensing]]
== License of start scripts

The start scripts generated for the application are licensed under the https://www.apache.org/licenses/LICENSE-2.0[Apache 2.0 Software License].

[[sec:application_convention_properties]]
== Convention properties (deprecated)

This plugin also adds some convention properties to the project, which you can use to configure its behavior. These are *deprecated* and superseded by the extension described above. See the link:{groovyDslPath}/org.gradle.api.Project.html#N14FED[Project] DSL documentation for information on them.

Unlike the extension properties, these properties appear as top-level project properties in the build script. For example, to change the application name you can just add the following to your build script:

====
include::sample[dir="snippets/java/application/kotlin",files="build.gradle.kts[tags=applicationName-conf]"]
include::sample[dir="snippets/java/application/groovy",files="build.gradle[tags=applicationName-conf]"]
====
