23. GRADLE. Сборщик проектов. (Java Enterprise - полный курс)

23. GRADLE. Сборщик проектов. (Java Enterprise - полный курс)

What is Gradle and How Does It Work?

Introduction to Gradle

  • Gradle is an automation tool for project builds, similar to Maven. It utilizes repositories like Maven but enhances performance through caching.
  • The structure of Gradle tasks is flexible and can be easily configured, distinguishing it from Maven's more rigid system.

Advantages of Using Gradle

  • Unlike Maven, which relies on cumbersome XML configurations, Gradle offers a more streamlined approach with better flexibility and extensibility.
  • Developers can write dependencies between tasks (e.g., Install, Build, Clean) more intuitively in Gradle compared to Maven.

Project Setup with Gradle

  • To create a new project in Gradle, users select "New File" > "New Project," choosing the appropriate settings such as Java version.
  • Installation of the Gradle wrapper simplifies setup; it allows projects to specify their own version without requiring individual installations by each developer.

Benefits of the Gradle Wrapper

  • The wrapper ensures that all developers use the same version of Gradle without needing separate installations or configurations.
  • If a project updates its version of Gradle, only the wrapper needs updating; this centralizes management and reduces configuration overhead for developers.

Configuration Files in Gradle

  • The main configuration file (build.gradle) serves as an equivalent to Maven's XML files. It defines project settings and dependencies using Groovy or Kotlin syntax.
  • Additional configuration files include settings.gradle, which manages multi-module projects by listing modules within a single root project.

Understanding Key Interfaces in Gradle

  • The core interface created during a build contains information about tasks that need execution. This includes methods for retrieving task graphs essential for building projects.

Understanding Gradle Project Structure

Overview of Gradle Settings and Project Configuration

  • The discussion begins with the concept of settings in a modular project, highlighting that each build grade will have its own Project object.
  • Key methods include getTasks(), which retrieves all tasks to be executed, and the Task interface that describes specific tasks for each build grade.
  • Tasks consist of actions, with the method getActions() returning these actions. An action is defined as a functional interface with a single execution method.

Initialization Phase in Gradle

  • The universal Script objects are created for any Gradle script type, allowing for custom configurations while delegating creation to the appropriate script type.
  • During initialization, Gradle reads configuration files (e.g., settings.gradle), creating a main object even if no custom files exist.
  • After reading configuration files, it creates Script objects within the settings object, marking the end of initialization.

Configuration Phase and Multi-module Projects

  • In multi-module projects, multiple Project objects are created based on their respective build.gradle files.
  • The task graph is constructed by calling getTasks() on each Project object to determine the sequence of task execution during project assembly.

Printing Configuration Information

  • A demonstration using Groovy language shows how to print configuration information such as project and root project hashes.
  • It emphasizes that in multi-module applications, there will always be a Root Project containing references to other projects.

Creating Custom Tasks in Gradle

  • Instructions on creating custom tasks are provided; users can define tasks quickly and execute them without performing any operations beyond printing output.
  • Users can access tasks by name or through task collections and modify properties like description and group easily.

Managing Task Actions

  • Users can specify input parameters directly within tasks similar to method arguments. This allows for streamlined task definitions.
  • The ability to create maps within tasks enables dynamic handling of key-value pairs related to task execution.

Executing Multiple Actions Within Tasks

  • Two methods (doLast and doFirst) allow users to define action order within tasks effectively.

Understanding Task Management in Gradle

Task Execution Order and Dependencies

  • The method dulast adds tasks to a queue, placing each subsequent task at the end. This results in du-last 2 being the last added task.
  • In contrast, the method for adding tasks to a stack places the first added task at the beginning, leading to a different execution order.
  • When executing tasks, they follow a specific sequence based on their dependencies; for example, if Task Build is called, it will compile and run tests before proceeding.
  • Dependencies can be established between tasks; for instance, Task 2 can depend on Task 3, ensuring that Task 3 executes before Task 2.
  • Syntax sugar allows omitting parentheses when defining dependencies in Gradle scripts, simplifying code readability.

Managing Task Graph and Execution Flow

  • By establishing dependencies like Task 4 Final 1, you can control execution order; this ensures that certain tasks complete before others begin.
  • The task graph is constructed based on these dependency definitions and dictates the order of execution during project builds.
  • Each task has an associated list of actions that are executed sequentially as defined by the task graph.
  • To visualize the task graph in Gradle, commands can be used to print out all tasks and their relationships once they are fully configured.
  • The output from running build commands reveals a comprehensive list of tasks involved in various phases such as compilation and resource processing.

Configuration Properties and Customization

  • Gradle allows defining properties like Java version within an extension block (ext) for better configuration management across projects.
  • Project settings can be stored in a dedicated properties file (gradle.properties) to streamline configuration access throughout your project setup.
  • It's important not to mix custom properties with core Gradle configurations; only relevant settings should be included in this file for clarity.

Organizing Large Build Scripts

  • For large build files with extensive configurations, creating separate script files helps maintain organization and readability within your project structure.
  • A new script file (e.g., .gradle) can encapsulate all necessary configurations which are then linked back into the main build file using simple commands.

Creating Custom Plugins

Understanding Gradle Plugins and Build Lifecycle

Introduction to Custom Plugins

  • The discussion begins with the necessity of applying a custom plugin in Gradle, emphasizing that it should be utilized rather than just described as a class.
  • A reference is made to existing Java plugins within Gradle that facilitate default tasks for application builds, highlighting the importance of creating custom plugins for specific tasks like resource copying.

Flexibility in Project Configuration

  • The speaker discusses the flexibility of Gradle's lifecycle management, allowing developers to create tailored build profiles for different environments (development, testing).
  • An illustration of the application's lifecycle is presented, showing how tasks are interconnected and executed sequentially during a build process.

Task Execution and Dependencies

  • The execution flow is explained through code examples where cleaning the application leads to task creation and compilation processes.
  • It’s noted that when executing classes, both Java files are compiled and resources processed simultaneously, demonstrating how multiple tasks can be handled efficiently.

Generating JAR Files

  • The process of generating JAR files is introduced; it involves archiving project outputs while maintaining dependencies on previous tasks like compiling Java classes.
  • A distinction is made between essential tasks (like creating JAR files) and intermediary ones that serve as links between more significant operations.

Testing and Building Phases

  • The testing phase follows similar patterns as compilation but focuses on test-specific directories. However, tests themselves are not executed at this stage.
  • A comprehensive overview of the build phase reveals its role in consolidating all necessary components for a complete project assembly.

Dependency Management in Gradle

  • The final segment addresses dependency management within Gradle projects, comparing it with Maven's approach while introducing repository configurations.
  • Default repositories such as Maven Central are discussed alongside company-specific repositories for managing internal libraries effectively.

Conclusion on Dependency Integration

Understanding Dependency Management in Gradle

Exploring Dependencies and Their Locations

  • The speaker discusses how to find dependencies within the Gradle build system, specifically looking for the Spring Web framework version 6.0.10 and its transitive dependencies.
  • It is noted that all dependencies can be located in a user-specific directory on the local machine, similar to how paths are defined in Maven's settings.xml file.
  • The speaker navigates through the user's directory to locate Gradle cache files, emphasizing the structure of these files which include compiled JARs and source code.

Understanding Dependency Configurations

  • The complexity of dependency structures due to caching is highlighted, showing that additional information is stored alongside libraries for faster operations.
  • Different types of dependency configurations are introduced: implementation, testImplementation, and runtimeOnly. Each serves distinct purposes during compilation and execution phases.

Detailed Breakdown of Dependency Types

  • The implementation configuration indicates necessary libraries for both compilation and runtime. In contrast, compileOnly signifies classes needed only at compile time but not at runtime.
  • The concept of annotation processors is introduced with Lombok as an example; these are used during compilation for processing annotations in code.

Test Dependencies Explained

  • The distinction between test-related dependencies such as testImplementation (needed for compiling test code), and testRuntimeOnly (only required during test execution), is clarified.
  • A summary of how different configurations (testCompileClasspath, etc.) work together to manage testing dependencies efficiently.

Managing Transitive Dependencies

  • Transitive dependencies are discussed, explaining their implicit nature where one library may depend on others. This can lead to conflicts if multiple versions exist across different libraries.
  • Strategies for resolving conflicts among transitive dependencies are outlined, including using exclusion directives similar to those in Maven.

Conclusion on Dependency Management Practices

  • Best practices suggest explicitly managing transitive dependencies by excluding unnecessary ones to avoid potential conflicts when multiple modules have overlapping requirements.

Creating a Multi-Module Project with Spring Framework

Overview of Module Exclusions and Dependencies

  • The discussion begins with the option to exclude specific modules from dependencies, highlighting how the Spring module can be removed from transitive dependencies.
  • A multi-module project is introduced, which will include a root project called "Great Doll Starter" along with modules for web services, database, utilities, and core functionalities.

Project Structure Creation

  • Steps are outlined for creating new Gradle modules within an IDE, including naming conventions and selecting appropriate options for web service configurations.
  • The creation of various modules such as Database, Service, Web, Common (for utility classes), and Core is discussed. Each module serves a distinct purpose in the overall architecture.

Dependency Management

  • The settings file structure is reviewed to ensure proper organization of the root project and its submodules. Unnecessary projects are identified for exclusion.
  • Instructions on establishing links between different modules are provided. For instance, the Database module depends on Utility classes to facilitate database connections.

Transitive Dependencies Explained

  • It’s explained that while services utilize repositories from the Database module, they do not automatically inherit visibility of Utility classes unless explicitly defined.
  • To make Utility classes visible in services as transitive dependencies, adjustments in dependency declarations are necessary using specific Gradle plugins.

Best Practices in Dependency Declaration

  • Recommendations are made regarding how to declare dependencies effectively across multiple projects without redundancy by utilizing central repository definitions.
  • The importance of managing transitive dependencies through proper configuration in build files is emphasized to streamline project management.

Comparison Between Build Tools: Gradle vs Maven

  • A comparison between Gradle and Maven highlights their relevance in modern development practices. Both tools have unique strengths but share many foundational concepts.
Video description

Все как на работе: https://javaguru.by/bootcamp Микросервисы и kafka: https://javaguru.by/developer Трудоустройство: https://javaguru.by/job Kubernetes, метрики и логи: https://javaguru.by/kuber Углубленная kafka: https://javaguru.by/kafka Все мои курсы: https://javaguru.by Телеграм канал: https://t.me/javaguru_by Презентация: https://prezi.com/view/wd9PueWTCOIHqq04Isdz/ Разберем gradle в сравнении с maven. Настроим конфигурацию. Исследуем внутренности gradle. Научимся создавать свои таски, экшены и строить таск графы. Поймем как написать свой плагин. Освоим Gradle Task Graph, скоупы. Создадим многомодульный проект на gradle 00:00 Зачем нужен? Модель работы. Чем отличается от Maven? 02:18 Создаем gradle проект в idea 03:15 Wrapper. Конфигурация Gradle 06:55 Конфигурационные файлы 08:33 Как внутри устроен Gradle 12:47 Наглядная структура работы Gradle 14:50 Вызываем команды в build.gradle 16:30 Создаем свой Task 19:05 Создаем Action в Task 21:40 Строим свой Task Graph 27:00 Блок ext 28:00 gradle.properties 29:00 Делаем свой скрипт script.gradle 30:19 Делаем свой плагин 31:20 Плагин Java в gradle - все дефолтные таски 31:38 Зачем делать свои плагины? 32:23 Application Lifecycle - дефолтный Task Graph 38:55 Как подключаются зависимости и репозитории 43:09 Scope в gradle 48:00 Транзитивные зависимости 50:52 Многомодульный проект 58:09 Итог