// 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.

[[service_injection]]
= Services and Service Injection
:keywords: services, service, injection, inject, objectfactory, providerfactory, workerexecutor, archiveoperations, execoperations, toolingmodelbuilderregistry, testeventreporterfactory

Gradle provides a number of useful services that can be used by custom Gradle types.
For example, the link:{javadocPath}/org/gradle/workers/WorkerExecutor.html[WorkerExecutor] service can be used by a task to run work in parallel, as seen in the <<worker_api.adoc#worker_api,worker API>> section.
The services are made available through _service injection_.

[[services_for_injection]]
== Available services

The following services are available for injection:

1. <<objectfactory,`ObjectFactory`>> - Allows model objects to be created.
2. <<sec:projectlayout,`ProjectLayout`>> - Provides access to key project locations.
3. <<buildlayout,`BuildLayout`>> - Provides access to important locations for a Gradle build.
4. <<providerfactory,`ProviderFactory`>> - Creates `Provider` instances.
5. <<workerexecutor,`WorkerExecutor`>> - Allows a task to run work in parallel.
6. <<filesystemoperations,`FileSystemOperations`>> - Allows a task to run operations on the filesystem such as deleting files, copying files or syncing directories.
7. <<archiveoperations,`ArchiveOperations`>> - Allows a task to run operations on archive files such as ZIP or TAR files.
8. <<execoperations,`ExecOperations`>> - Allows a task to run external processes with dedicated support for running external `java` programs.
9. <<toolingmodelbuilderregistry,`ToolingModelBuilderRegistry`>> - Allows a plugin to registers a Gradle tooling API model.
10. <<testeventreporterfactory,`TestEventReporterFactory`>> - Allows a plugin to access Gradle's test events and its corresponding API.

Out of the above, `ProjectLayout` and `WorkerExecutor` services are only available for injection in project plugins.
`BuildLayout` is only available in settings plugins and settings files.
`ProjectLayout` is unavailable in Worker API actions.

While other services can technically be injected, this practice is not supported and may lead to breaking changes in the future.
Only inject the services explicitly listed above to ensure stability and compatibility.

WARNING: You should avoid injecting types not listed above.

[[objectfactory]]
== `ObjectFactory`

link:{javadocPath}/org/gradle/api/model/ObjectFactory.html[`ObjectFactory`] is a service for creating custom Gradle types, allowing you to define nested objects and DSLs in your build logic.
It provides methods for creating instances of different types, such as properties (`Property<T>`), collections (`ListProperty<T>`, `SetProperty<T>`, `MapProperty<K, V>`), file-related objects (`RegularFileProperty`, `DirectoryProperty`, `ConfigurableFileCollection`, `ConfigurableFileTree`), and more.

You can obtain an instance of `ObjectFactory` using the `project.objects` property.
Here's a simple example demonstrating how to use `ObjectFactory` to create a property and set its value:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=object-factory]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=object-factory]"]
====

TIP: It is preferable to let Gradle create objects automatically by using <<properties_providers.adoc#managed_properties,managed properties>>.

Using `ObjectFactory` to create these objects ensures that they are properly managed by Gradle, especially in terms of configuration avoidance and lazy evaluation.
This means that the values of these objects are only calculated when needed, which can improve build performance.

In the following example, a project extension called `DownloadExtension` receives an `ObjectFactory` instance through its constructor.
The constructor uses this to create a nested `Resource` object (also a custom Gradle type) and makes this object available through the `resource` property:

[source,java]
.DownloadExtension.java
----
include::{snippetsPath}/plugins/nestedObjects/groovy/buildSrc/src/main/java/DownloadExtension.java[tags=download-extension]
include::{snippetsPath}/plugins/nestedObjects/groovy/buildSrc/src/main/java/Resource.java[tags=resource]
----

Here is another example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=object-factory-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=object-factory-inject]"]
====

The `MyObjectFactoryTask` task uses an `ObjectFactory` instance, which is injected into the task's constructor using the `@Inject` annotation.

[[sec:projectlayout]]
== `ProjectLayout`

link:{groovyDslPath}/org.gradle.api.file.ProjectLayout.html[`ProjectLayout`] is a service that provides access to the layout of a Gradle project's directories and files.
It's part of the `org.gradle.api.file` package and allows you to query the project's layout to get information about source sets, build directories, and other file-related aspects of the project.

You can obtain a `ProjectLayout` instance from a `Project` object using the `project.layout` property.
Here's a simple example:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=project-layout]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=project-layout]"]
====

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=project-layout-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=project-layout-inject]"]
====

The `MyProjectLayoutTask` task uses a `ProjectLayout` instance, which is injected into the task's constructor using the `@Inject` annotation.

[[buildlayout]]
== `BuildLayout`

link:{groovyDslPath}/org.gradle.api.file.BuildLayout.html[`BuildLayout`] is a service that provides access to the root and settings directory in a Settings plugin or a Settings script, it is analogous to `ProjectLayout`.
It's part of the `org.gradle.api.file` package to access standard build-wide file system locations as lazily computed value.

NOTE: These APIs are currently incubating but eventually should replace existing accessors in Settings, which return eagerly computed locations: +
`Settings.rootDir` -> `Settings.layout.rootDirectory` +
`Settings.settingsDir` -> `Settings.layout.settingsDirectory`

You can obtain a `BuildLayout` instance from a `Settings` object using the `settings.layout` property.
Here's a simple example:

====
include::sample[dir="snippets/providers/services/kotlin",files="settings.gradle.kts[tags=build-layout]"]
include::sample[dir="snippets/providers/services/groovy",files="settings.gradle[tags=build-layout]"]
====

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="settings.gradle.kts[tags=build-layout-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="settings.gradle[tags=build-layout-inject]"]
====

This code defines a `MyBuildLayoutPlugin` plugin that implements the `Plugin` interface for the `Settings` type.
The plugin expects a `BuildLayout` instance to be injected into its constructor using the `@Inject` annotation.

[[providerfactory]]
== `ProviderFactory`

link:{groovyDslPath}/org.gradle.api.provider.ProviderFactory.html[`ProviderFactory`] is a service that provides methods for creating different types of providers.
Providers are used to model values that may be computed lazily in your build scripts.

The `ProviderFactory` interface provides methods for creating various types of providers, including:

- `provider(Callable<T> value)` to create a provider with a value that is lazily computed based on a `Callable`.
- `provider(Provider<T> value)` to create a provider that simply wraps an existing provider.
- `property(Class<T> type)` to create a property provider for a specific type.
- `gradleProperty(Class<T> type)` to create a property provider that reads its value from a Gradle project property.

Here's a simple example demonstrating the use of `ProviderFactory` using `project.providers`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=provider-factory]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=provider-factory]"]
====

The task named `printMessage` uses the `ProviderFactory` to create a `provider` that supplies the message string.

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=provider-factory-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=provider-factory-inject]"]
====

The `ProviderFactory` service is injected into the `MyProviderFactoryTask` task's constructor using the `@Inject` annotation.

[[workerexecutor]]
== `WorkerExecutor`

link:{javadocPath}/org/gradle/workers/WorkerExecutor.html[`WorkerExecutor`] is a service that allows you to perform parallel execution of tasks using worker processes.
This is particularly useful for tasks that perform CPU-intensive or long-running operations, as it allows them to be executed in parallel, improving build performance.

Using `WorkerExecutor`, you can submit units of work (called actions) to be executed in separate worker processes.
This helps isolate the work from the main Gradle process, providing better reliability and performance.

Here's a basic example of how you might use `WorkerExecutor` in a build script:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=worker-executor]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=worker-executor]"]
====

See <<worker_api.adoc#worker_api,the worker API>> for more details.

[[filesystemoperations]]
== `FileSystemOperations`

link:{javadocPath}/org/gradle/api/file/FileSystemOperations.html[`FileSystemOperations`] is a service that provides methods for performing file system operations such as copying, deleting, and syncing.
It is part of the `org.gradle.api.file` package and is typically used in custom tasks or plugins to interact with the file system.

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=file-system-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=file-system-inject]"]
====

The `FileSystemOperations` service is injected into the `MyFileSystemOperationsTask` task's constructor using the `@Inject` annotation.

With some ceremony, it is possible to use `FileSystemOperations` in an ad-hoc task defined in a build script:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=file-system-adhoc]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=file-system-adhoc]"]
====

First, you need to declare an interface with a property of type `FileSystemOperations`, here named `InjectedFsOps`, to serve as an injection point.
Then call the method link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#newInstance(java.lang.Class,java.lang.Object%2E%2E%2E)[`ObjectFactory.newInstance`] to generate an implementation of the interface that holds an injected service.

TIP: This is a good time to consider extracting the ad-hoc task into a proper class.

[[archiveoperations]]
== `ArchiveOperations`

link:{javadocPath}/org/gradle/api/file/ArchiveOperations.html[`ArchiveOperations`] is a service that provides methods for accessing the contents of archives, such as ZIP and TAR files.
It is part of the `org.gradle.api.file` package and is typically used in custom tasks or plugins to unpack archive files.

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=archive-op-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=archive-op-inject]"]
====

The `ArchiveOperations` service is injected into the `MyArchiveOperationsTask` task's constructor using the `@Inject` annotation.

With some ceremony, it is possible to use `ArchiveOperations` in an ad-hoc task defined in a build script:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=archive-op-adhoc]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=archive-op-adhoc]"]
====

First, you need to declare an interface with a property of type `ArchiveOperations`, here named `InjectedArcOps`, to serve as an injection point.
Then call the method link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#newInstance(java.lang.Class,java.lang.Object%2E%2E%2E)[`ObjectFactory.newInstance`] to generate an implementation of the interface that holds an injected service.

TIP: This is a good time to consider extracting the ad-hoc task into a proper class.

[[execoperations]]
== `ExecOperations`

link:{javadocPath}/org/gradle/process/ExecOperations.html[`ExecOperations`] is a service that provides methods for executing external processes (commands) from within a build script.
It is part of the `org.gradle.process` package and is typically used in custom tasks or plugins to run command-line tools or scripts as part of the build process.

Here is an example using `javax.inject.Inject`:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=exec-op-inject]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=exec-op-inject]"]
====

The `ExecOperations` is injected into the `MyExecOperationsTask` task's constructor using the `@Inject` annotation.

With some ceremony, it is possible to use `ExecOperations` in an ad-hoc task defined in a build script:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=exec-op-adhoc]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=exec-op-adhoc]"]
====

First, you need to declare an interface with a property of type `ExecOperations`, here named `InjectedExecOps`, to serve as an injection point.
Then call the method link:{javadocPath}/org/gradle/api/model/ObjectFactory.html#newInstance(java.lang.Class,java.lang.Object%2E%2E%2E)[`ObjectFactory.newInstance`] to generate an implementation of the interface that holds an injected service.

TIP: This is a good time to consider extracting the ad-hoc task into a proper class.

[[toolingmodelbuilderregistry]]
== `ToolingModelBuilderRegistry`

link:{javadocPath}/org/gradle/tooling/provider/model/ToolingModelBuilderRegistry.html[`ToolingModelBuilderRegistry`] is a service that allows you to register custom tooling model builders.
Tooling models are used to provide rich IDE integration for Gradle projects, allowing IDEs to understand and work with the project's structure, dependencies, and other aspects.

The `ToolingModelBuilderRegistry` interface is part of the `org.gradle.tooling.provider.model` package and is typically used in custom Gradle plugins that provide enhanced IDE support.

Here's a simplified example:

====
include::sample[dir="snippets/providers/services/kotlin",files="build.gradle.kts[tags=tooling-model]"]
include::sample[dir="snippets/providers/services/groovy",files="build.gradle[tags=tooling-model]"]
====

You can learn more at <<tooling_api.adoc#tooling_api,Tooling API>>.

[[testeventreporterfactory]]
== `TestEventReporterFactory`

WARNING: This API is incubating.

link:{javadocPath}/org/gradle/api/tasks/testing/TestEventReporterFactory.html[`TestEventReporterFactory`] is a service that provides access to the test event reporting API.

You can learn more at <<test_reporting_api.adoc#test_reporting_api,Test Reporting API>>.

== Constructor injection

There are 2 ways that an object can receive the services that it needs. The first option is to add the service as a parameter of the class constructor.
The constructor must be annotated with the `javax.inject.Inject` annotation.
Gradle uses the declared type of each constructor parameter to determine the services that the object requires.
The order of the constructor parameters and their names are not significant and can be whatever you like.

Here is an example that shows a task type that receives an `ObjectFactory` via its constructor:

====
[source.multi-language-sample,java]
.Download.java
----
include::{snippetsPath}/plugins/constructorServiceInjection/groovy/buildSrc/src/main/java/Download.java[tags=download]
----
====

[[property_injection]]
== Property injection

Alternatively, a service can be injected by adding a property getter method annotated with the `javax.inject.Inject` annotation to the class.
This can be useful, for example, when you cannot change the constructor of the class due to backwards compatibility constraints.
This pattern also allows Gradle to defer creation of the service until the getter method is called, rather than when the instance is created. This can help with performance.
Gradle uses the declared return type of the getter method to determine the service to make available. The name of the property is not significant and can be whatever you like.

The property getter method must be `public` or `protected`. The method can be `abstract` or, in cases where this isn't possible, can have a dummy method body.
The method body is discarded.

Here is an example that shows a task type that receives a two services via property getter methods:

====
[source.multi-language-sample,java]
.Download.java
----
include::{snippetsPath}/plugins/propertyServiceInjection/groovy/buildSrc/src/main/java/Download.java[tags=download]
----
====
