<!--
  ~ Copyright 2009 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.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.
  -->
<chapter id='tutorial_java_projects'>
    <title>Java Quickstart</title>

    <section>
        <title>The Java plugin</title>

        <para>As we have seen, Gradle is a general-purpose build tool. It can build pretty much anything you care to
            implement in your build script. Out-of-the-box, however, it doesn't build anything unless you add code to
            your build script to do so.</para>

        <para>Most Java projects are pretty similar as far as the basics go: you need to compile your Java
            source files, run some unit tests, and create a JAR file containing your classes. It would be nice if you
            didn't have to code all this up for every project. Luckily, you don't have to.
            Gradle solves this problem through the use of <firstterm>plugins</firstterm>. A plugin is an extension to Gradle
            which configures your project in some way, typically by adding some pre-configured tasks which together do
            something useful. Gradle ships with a number of plugins, and you can easily write your own and share them with
            others. One such plugin is the <firstterm>Java plugin</firstterm>. This plugin adds some tasks to your
            project which will compile and unit test your Java source code, and bundle it into a JAR file.
        </para>

        <para>The Java plugin is convention based. This means that the plugin defines default values for many aspects of the
            project, such as where the Java source files are located. If you follow the convention in your project, you
            generally don't need to do much in your build script to get a useful build. Gradle allows you to customize your
            project if you don't want to or cannot follow the convention in some way. In fact, because support for Java
            projects is implemented as a plugin, you don't have to use the plugin at all to build a Java project, if
            you don't want to.
        </para>

        <para>We have in-depth coverage with many examples about the Java plugin, dependency management and multi-project
            builds in later chapters. In this chapter we want to give you an initial idea of how to use the Java plugin to
            build a Java project.
        </para>
    </section>

    <section>
        <title>A basic Java project</title>
        <para>Let's look at a simple example. To use the Java plugin, add the following to your build file:</para>
        <sample id="javaQuickstart" dir="java/quickstart" includeLocation="true" title="Using the Java plugin">
            <sourcefile file="build.gradle" snippet="use-plugin"/>
        </sample>
        <para>This is all you need to define a Java project. This will apply the Java plugin to your project, which adds
            a number of tasks to your project.</para>
        <tip>
            <title>What tasks are available?</title>
            <para>You can use <userinput>gradle tasks</userinput> to list the tasks of a project. This will let you see
            the tasks that the Java plugin has added to your project.
        </para></tip>

        <para>Gradle expects to find your production source code under <filename>src/main/java</filename> and your test
            source code under <filename>src/test/java</filename>. In addition, any files under
            <filename>src/main/resources</filename> will be included in the JAR file as resources, and any files under
            <filename>src/test/resources</filename> will be included in the classpath used to run the tests. All output
            files are created under the <filename>build</filename> directory, with the JAR file ending up in the
            <filename>build/libs</filename> directory.
        </para>

        <section>
            <title>Building the project</title>
            <para>The Java plugin adds quite a few tasks to your project. However, there are only a handful of tasks
                that you will need to use to build the project. The most commonly used task is the <literal>build</literal> task,
                which does a full build of the project. When you run <userinput>gradle build</userinput>, Gradle will
                compile and test your code, and create a JAR file containing your main classes and resources:</para>

            <sample id="javaQuickstart" dir="java/quickstart" title="Building a Java project">
                <output args="build"/>
            </sample>

            <para>Some other useful tasks are:</para>
            <variablelist>
                <varlistentry>
                    <term>clean</term>
                    <listitem>
                        <para>Deletes the <filename>build</filename> directory, removing all built files.</para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>assemble</term>
                    <listitem>
                        <para>Compiles and jars your code, but does not run the unit tests. Other plugins add more
                            artifacts to this task. For example, if you use the War plugin, this task will also build
                            the WAR file for your project.
                        </para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>check</term>
                    <listitem>
                        <para>Compiles and tests your code. Other plugins add more checks to this task. For example, if
                            you use the <literal>checkstyle</literal> plugin, this task will also run Checkstyle against your source
                            code.
                        </para>
                    </listitem>
                </varlistentry>
            </variablelist>
        </section>

        <section>
            <title>External dependencies</title>
            <para>Usually, a Java project will have some dependencies on external JAR files. To reference these JAR
                files in the project, you need to tell Gradle where to find them. In Gradle, artifacts such as JAR
                files, are located in a <firstterm>repository</firstterm>. A repository can be used for fetching the
                dependencies of a project, or for publishing the artifacts of a project, or both. For this example,
                we will use the public Maven repository:</para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Adding Maven repository">
                <sourcefile file="build.gradle" snippet="repo"/>
            </sample>

            <para>Let's add some dependencies. Here, we will declare that our production classes have a compile-time
                dependency on commons collections, and that our test classes have a compile-time dependency on junit:</para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Adding dependencies">
                <sourcefile file="build.gradle" snippet="dependencies"/>
            </sample>
            <para>You can find out more in <xref linkend="artifact_dependencies_tutorial"/>.</para>
        </section>

        <section>
            <title>Customizing the project</title>
            <para>The Java plugin adds a number of properties to your project. These properties have default values
                which are usually sufficient to get started. It's easy to change these values if they don't suit. Let's
                look at this for our sample. Here we will specify the version number for our Java project, along
                with the Java version our source is written in. We also add some attributes to the JAR manifest.
            </para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Customization of MANIFEST.MF">
                <sourcefile file="build.gradle" snippet="customization"/>
            </sample>
            <tip>
                <title>What properties are available?</title>
                <para>You can use <userinput>gradle properties</userinput> to list the properties of a project. This will allow
                you to see the properties added by the Java plugin, and their default values.</para></tip>
            <para>The tasks which the Java plugin adds are regular tasks, exactly the same as if they were declared in
                the build file. This means you can use any of the mechanisms shown in earlier chapters to customize
                these tasks. For example, you can set the properties of a task, add behaviour to a task, change the
                dependencies of a task, or replace a task entirely. In our sample, we will configure the
                <literal>test</literal> task, which is of type <apilink class="org.gradle.api.tasks.testing.Test"/>, to
                add a system property when the tests are executed: </para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Adding a test system property">
                <sourcefile file="build.gradle" snippet="task-customization"/>
            </sample>
        </section>

        <section>
            <title>Publishing the JAR file</title>
            <para>Usually the JAR file needs to be published somewhere. To do this, you need to tell Gradle where to
                publish the JAR file. In Gradle, artifacts such as JAR files are published to repositories. In our
                sample, we will publish to a local directory. You can also publish to a remote location, or multiple
                locations.
            </para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Publishing the JAR file">
                <sourcefile file="build.gradle" snippet="upload"/>
            </sample>
            <para>To publish the JAR file, run <userinput>gradle uploadArchives</userinput>.</para>
        </section>
        
        <section>
            <title>Creating an Eclipse project</title>
            <para>To create the Eclipse-specific descriptor files, like <literal>.project</literal>, you need to add
            another plugin to your build file:</para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Eclipse plugin">
                <sourcefile file="build.gradle" snippet="use-eclipse-plugin"/>
            </sample>
            <para>Now execute <userinput>gradle eclipse</userinput> command to generate Eclipse project files. More information
            about the <literal>eclipse</literal> task can be found in <xref linkend="eclipse_plugin"/>.
            </para>
        </section>

        <section>
            <title>Summary</title>
            <para>Here's the complete build file for our sample:</para>
            <sample id="javaQuickstart" dir="java/quickstart" title="Java example - complete build file">
                <sourcefile file="build.gradle"/>
            </sample>
        </section>
    </section>

    <section id='sec:examples'>
        <title>Multi-project Java build</title>
        <para>Now let's look at a typical multi-project build. Below is the layout for the project:
        </para>
        <sample id="javaMultiProject" dir="java/multiproject" includeLocation="true" title="Multi-project build - hierarchical layout">
            <layout>
                api/
                services/webservice/
                shared/
                services/shared/
            </layout>
        </sample>
        <!--  TODO: Note that the "settings.gradle" lists four projects, also including "services:shared", in addition
        to "services:webservice". -->
        <para>Here we have four projects. Project <literal>api</literal> produces a JAR file which is shipped to the
            client to provide them a Java client for your XML webservice. Project <literal>webservice</literal> is a
            webapp which returns XML. Project <literal>shared</literal> contains code used both by <literal>api</literal>
            and <literal>webservice</literal>. Project <literal>services/shared</literal> has code that depends on the
            <literal>shared</literal> project.
        </para>

        <section>
            <title>Defining a multi-project build</title>
            <para>To define a multi-project build, you need to create a <firstterm>settings file</firstterm>. The settings
                file lives in the root directory of the source tree, and specifies which projects to include in the
                build. It must be called <filename>settings.gradle</filename>. For this example, we are using a simple
                hierarchical layout. Here is the corresponding settings file:
            </para>
            <sample id="javaMultiProject" dir="java/multiproject" title="Multi-project build - settings.gradle file">
                <sourcefile file="settings.gradle" snippet="include-projects"/>
            </sample>
            <para>You can find out more about the settings file in <xref linkend="multi_project_builds"/>.</para>
        </section>

        <section>
            <title>Common configuration</title>
            <para>For most multi-project builds, there is some configuration which is common to all projects.
                In our sample, we will define this common configuration in the root project, using a technique called
                <firstterm>configuration injection</firstterm>. Here, the root project is like a container and the
                <literal>subprojects</literal> method iterates over the elements of this container - the projects in
                this instance - and injects the specified configuration. This way we can easily define the manifest
                content for all archives, and some common dependencies:
            </para>
            <sample id="javaMultiProject" dir="java/multiproject" title="Multi-project build - common configuration">
                <sourcefile file="build.gradle" snippet="configuration-injection"/>
            </sample>

            <para>Notice that our sample applies the Java plugin to each subproject. This means the tasks and
                configuration properties we have seen in the previous section are available in each subproject.
                So, you can compile, test, and JAR all the projects by running <userinput>gradle build</userinput> from
                the root project directory.</para>
            <para>Also note that these plugins are only applied within the <literal>subprojects</literal> section, not
            at the root level, so the root build will not expect to find Java source files in the root project,
            only in the subprojects.</para>
        </section>

        <section>
            <title>Dependencies between projects</title>
            <para>You can add dependencies between projects in the same build, so that, for example, the JAR file of one
                project is used to compile another project. In the <literal>api</literal> build file we will add a dependency
                on the <literal>shared</literal> project. Due to this dependency, Gradle will
                ensure that project <literal>shared</literal> always gets built before project <literal>api</literal>.
            </para>
            <sample id="javaMultiProject" dir="java/multiproject" title="Multi-project build - dependencies between projects">
                <sourcefile file="api/build.gradle" snippet="dependencies"/>
            </sample>
            See <xref linkend="disable_dependency_projects"/> for how to disable this functionality.
        </section>

        <section>
            <title>Creating a distribution</title>
            <para>
                We also add a distribution, that gets shipped to the client:
            </para>
            <sample id="javaMultiProject" dir="java/multiproject" title="Multi-project build - distribution file">
                <sourcefile file="api/build.gradle" snippet="dists"/>
            </sample>
        </section>
    </section>

    <section>
        <title>Where to next?</title>
        <para>
            In this chapter, you have seen how to do some of the things you commonly need to build a Java based
            project. This chapter is not exhaustive, and there are many other things you can do with Java projects in
            Gradle.
            You can find out more about the Java plugin in <xref linkend="java_plugin"/>, and you can find more sample
            Java projects in the <filename>samples/java</filename> directory in the Gradle distribution.
        </para>
        <para>
            Otherwise, continue on to <xref linkend="artifact_dependencies_tutorial"/>.
        </para>
        <para>
        </para>
    </section>
</chapter>
