diff --git a/docs/gradle-quickstart.md b/docs/gradle-quickstart.md index 8ae5b81800d5..67cadbd40cc7 100644 --- a/docs/gradle-quickstart.md +++ b/docs/gradle-quickstart.md @@ -20,6 +20,10 @@ This documents explains how to use Gradle directly from the command line via the command. All Gradle tasks can also be invoked from the Gradle view in [IntelliJ IDEA](intellij-quickstart.md). +For more information, also refer to the +[documentation of the Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions#build) +which this project uses. + There are several Gradle tasks you can use. Most notably: - `./gradlew assemble` compile all code and create all Jar files @@ -38,68 +42,11 @@ You may run `./gradlew` (without arguments) for a detailed overview ## Using Gradle during Development -### Changing or adding Modules of Hedera (aka Gradle Subprojects) - -All modules are listed in [settings.gradle.kts](../settings.gradle.kts) using -`include(":", "")`. The `module-folder-path` should be a folder in -a subdirectory like [platform-sdk](../platform-sdk) or [hedera-node](../hedera-node). In the folder, -the following files are expected: - -- `build.gradle.kts` specifies to which group of modules the module belongs, e.g. - `id("com.hedera.gradle.services")` or `id("com.hedera.gradle.platform")` and may contain - [dependency definitions](#changing-or-adding-dependencies) for tests. -- `src/main/java/module-info.java` is the Java Module specification that is also used to determine - the [dependencies of the module](#changing-or-adding-dependencies) by Gradle. Note that the last - segment of the module name defined in the `module-info.java` file needs to correspond to the - name of the module defined in [settings.gradle.kts](../settings.gradle.kts). - -### Changing or Adding Dependencies - -This project use of the _Java Module System (JPMS)_. With this, dependencies between modules are -defined in the `src/main/java/module-info.java` files that each module contains. Other modules are -identified by their _Module Name_ there. For example, a dependency to the `swirlds-logging` module -is expressed by `requires com.swirlds.logging`. A dependency to the 3rd party library -`com.fasterxml.jackson.core` is expressed by `requires com.fasterxml.jackson.core`. Note: This -project utilizes the -[org.gradlex.java-module-dependencies](https://github.com/gradlex-org/java-module-dependencies) -plugin to achieve this integration between Gradle and the Java Module System. - -Each dependency definition contains a scope – e.g. `requires` or `requires transitive`. If you are -unsure about a scope, use `requires` when adding a dependency. Then execute `./gradlew qualityGate` -which runs a dependency scope check that analysis the code to determine which Java types are visible -(and should be visible) to which modules. If the check fails, it will advise you how to change the -scope. - -### Adding or Changing the Version of a 3rd party dependency - -If you use a 3rd party module lke `com.fasterxml.jackson.core`, a version for that module needs to -be selected. For this, the -[hedera-dependency-versions/build.gradle.kts](../hedera-dependency-versions/build.gradle.kts) -defines a so-called _Gradle platform_ (also called BOM) that contains the versions of all 3rd party -modules used. If you want to upgrade the version of a module, do this here. Remember to run -`./gradlew qualityGate` after the change. If you need to use a new 3rd party module in a -`src/main/java/module-info.java` file, you need to add the version here. (If the new module is not -completely Java Module System compatible, you may also need to add -[patching rules](#patching-3rd-party-modules)). - -### Patching 3rd Party Modules - -Some 3rd party libraries we use are not yet fully Java Module System compatible. And some modules -pull in other dependencies that we can neglect. Situations like this are treated as wrong/incomplete -metadata in our Gradle setup and the file -[com.hedera.gradle.jpms-modules.gradle.kts](../gradle/plugins/src/main/kotlin/com.hedera.gradle.jpms-modules.gradle.kts) -contains the rules to adjust or extend the metadata of 3rd party libraries to address such problems. - -Note: This project utilizes the -[org.gradlex.extra-java-module-info](https://github.com/gradlex-org/extra-java-module-info) and -[org.gradlex.jvm-dependency-conflict-resolution](https://gradlex.org/jvm-dependency-conflict-resolution/#resolution-plugin) -plugins to ease the definition of patching rules. - -### Incrementing the Version of Hedera itself - -Our Gradle build has a single version number for all modules. It is defined in -[version.txt](../version.txt). Changing this version number will automatically apply to every -module. +### Defining modules and dependencies + +Please refer to the section about _modules and dependencies_ in the +[documentation of the Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions#modules) +which this project uses. ### Testing diff --git a/docs/intellij-quickstart.md b/docs/intellij-quickstart.md index 26639e0be792..12337341a177 100644 --- a/docs/intellij-quickstart.md +++ b/docs/intellij-quickstart.md @@ -10,6 +10,10 @@ git clone https://github.com/hashgraph/hedera-services.git From IntelliJ, choose `File -> Open` the _hedera-services/_ directory you just cloned. +For more information, also refer to the +[documentation of the Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions#build) +which this project uses. + ### (optional) IntelliJ plugins The following plugins add comfort features for working with certain parts of the code base: diff --git a/hedera-node/docs/design/modules.md b/hedera-node/docs/design/modules.md index df0b667b1a1d..398b62280375 100644 --- a/hedera-node/docs/design/modules.md +++ b/hedera-node/docs/design/modules.md @@ -9,24 +9,25 @@ Java modules. ## Gradle module description -Each module needs a `build.gradle.kts` file that describes the module. +Please also refer to the +[documentation of the Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions#modules) +which describes a common approach for structuring projects and modules in Hiero and Hedera repositories. -General best practices for all our (Java) modules are defined in custom plugins that can be found -under `gradle/plugins/src/main/kotlin`. For a Java module the `com.hedera.gradle.java` plugin should be used. -Next to this each module should have a description. Since nothing else is needed for a minimal module the most simple -`build.gradle.kts` looks like this: +Each module needs a `build.gradle.kts` file that describes the module. +In the `build.gradle.kts` file, you define the type of the module by using one of the +[_Module_ convention plugins](https://github.com/hiero-ledger/hiero-gradle-conventions#plugins). +provided by the Hiero Gradle Conventions. ``` -plugins { - id("com.hedera.gradle.java") -} +plugins { id("org.hiero.gradle.module.library") } description = "A minimal module without any dependecies" ``` -The `group` and `version` of the module should not be added here. The `group` is the same for all modules on the -repository (`com.hedera.hashgraph`) and its definition can be found in the `com.hedera.gradle.conventions` plugin. -For the `version` we use a global definition, too. The current `version` is defined in the `gradle.properties` file in +Note: the `group` and `version` of the module should not be added here. The `group` is the same for all modules that +belong to a _product_, and it is +[defined in `settings.gradle.kts`](https://github.com/hiero-ledger/hiero-gradle-conventions#modules). +For the `version` we use a global definition, too. The current `version` is defined in the `version.txt` file in the root folder of the project. The `name` of a module is simple created based on the folder name of the module. ## Project sources set @@ -45,36 +46,44 @@ specific path below the `src/main/resources/com/hedera/node/app/services/foo` fo ## Tests -All modules can have different types of tests. The `com.hedera.gradle.java` plugin provides direct support -for unit test, integration tests, and end-to-end tests. Next to this the test fixtures functionality of Gradle is -supported. +All modules can have different types of tests. The `org.hiero.gradle.module.library` plugin provides direct support +for unit tests. Other test sets can be added by applying additional feature plugins: + +- `id("org.hiero.gradle.feature.test-hammer")` +- `id("org.hiero.gradle.feature.test-integration")` +- `id("org.hiero.gradle.feature.test-time-consuming")` +- `id("org.hiero.gradle.feature.test-timing-sensitive")` + +Next to this, the test fixtures functionality of Gradle is supported. ### Test fixtures To create clean and readable unit tests it is best practice to provide common functionality for tests in the test -fixtures of a module. Based on the `com.hedera.gradle.java` plugin test fixtures are supported for all -Java modules. +fixtures of a module. To add test fixture support to a module, apply the `id("org.hiero.gradle.feature.test-fixtures")` +plugin. All Java sources for the test fixtures must be placed under `src/testFixtures/java`. Additional resources that should be shared for tests can be placed under `src/testFixtures/resources`. Like for the source set of a project the test fixtures sets are defined as full JPMS modules, too. Based on that a `module-info.java` file must be placed directly under `src/testFixtures/java` if at least one Java file is present. -The name of the test fixtures module should be based on the name of the source module and add a `testfixtures` suffix. +The name of the test fixtures module should be based on the name of the source module and add a `test.fixtures` suffix. For the given sample of the foo service the name and the base package for the test fixtures set would -be `com.hedera.node.app.services.foo.testfixtures`. Since the test fixtures JPMS module will only be used in tests it +be `com.hedera.node.app.services.foo.test.fixtures`. Since the test fixtures JPMS module will only be used in tests it should be fully opened. This makes the content of the `module-info.java` much more readable since no individual `opens` statements need to be added. The complete module will be opened by adding the `open` keyword directly to the module definition: ``` -open module com.hedera.node.app.services.foo.testfixtures { +open module com.hedera.node.app.services.foo.test.fixtures { //... } ``` -**Hint:** Similar to any other module the test fixtures set of a module can be added as a dependendency by using the -correct Gradle syntax like in this sample: `testImplementation(testFixtures(project(":foo-service"))) ` +**Hint:** Similar to any other module the test fixtures set of a module can be added as a dependency by using the +corresponding `requires`. In this sample: `requires com.hedera.node.app.services.foo.test.fixtures` +(in module-info.java) or `testModuleInfo { requires("com.hedera.node.app.services.foo.test.fixtures") }"` +(in build.gradle.kts for unit tests that have no module-info.java). ### Unit tests @@ -84,25 +93,21 @@ same base package as the module sources. By doing so unit tests can access packa ### Integration tests -For the integration test set the `src/itest/java` and `src/itest/resources` folders must be used. All integration tests -will be executed on the module path to be as near to the real usage as possible. Based on that a `module-info.java` file -is needed. Like for test fixtures the name for the module and the base package is based on the name of the source module -plus the 'itest' suffix. For the given sample the JPMS module name for the integration tests would -be `com.hedera.node.app.services.foo.itest`. Since the test fixtures JPMS module will only be used in tests it should be -fully opened. This makes the content of the `module-info.java` much more readable since no individual `opens` -statements need to be added. The complete module will be opened by adding the `open` keyword directly to the module -definition: +For the integration test set the `src/testIntegration/java` and `src/testIntegration/resources` folders must be used. +All integration tests will be executed on the module path to be as near to the real usage as possible. Based on that a +`module-info.java` file is needed. Like for test fixtures the name for the module and the base package is based on the +name of the source module plus the 'test.integration' suffix. For the given sample the JPMS module name for the +integration tests would be `com.hedera.node.app.services.foo.test.integration`. Since the test fixtures JPMS module +will only be used in tests it should be fully opened. This makes the content of the `module-info.java` much more +readable since no individual `opens` statements need to be added. The complete module will be opened by adding the +`open` keyword directly to the module definition: ``` -open com.hedera.node.app.services.foo.itest { +open com.hedera.node.app.services.foo.test.integration { //... } ``` -### End-to-end tests - -For the end-to-end test set the `src/eet/java` and `src/eet/resources` folders must be used. - ## JMH benchmarks Next to tests a module can have several benchmarks to test the performance of critical components within the module. All @@ -113,29 +118,29 @@ benchmarks must be based on JMH and the `src/jmh/java` and `src/jmh/resources` f Based on the given definitions a module folder in the project looks like this: ``` - foo-service/ - ├── src/main/java/ - │ ├── com.hedera.node.app.service.foo - │ │ ├── FooService.java - │ │ └── package-info.java - │ └── module-info.java - ├── src/main/resources/ - │ ├── com.hedera.node.app.service.foo - │ │ └── some_data.json - │ └── logging.properties - ├── src/testFixtures/java/ - │ ├── com.hedera.node.app.service.foo.testfixtures - │ │ └── FooServiceTestConfig.java - │ └── module-info.java - ├── src/test/java/ - │ └── com.hedera.node.app.service.foo - │ └── FooServiceTest.java - ├── src/itest/java/ - │ ├── com.hedera.node.app.service.foo.itest - │ │ └── FooServiceITest.java - │ └── module-info.java - └── build.gradle.kts - ``` +foo-service/ +├── src/main/java/ +│ ├── com.hedera.node.app.service.foo +│ │ ├── FooService.java +│ │ └── package-info.java +│ └── module-info.java +├── src/main/resources/ +│ ├── com.hedera.node.app.service.foo +│ │ └── some_data.json +│ └── logging.properties +├── src/testFixtures/java/ +│ ├── com.hedera.node.app.service.foo.testfixtures +│ │ └── FooServiceTestConfig.java +│ └── module-info.java +├── src/test/java/ +│ └── com.hedera.node.app.service.foo +│ └── FooServiceTest.java +├── src/testIntegration/java/ +│ ├── com.hedera.node.app.service.foo.itest +│ │ └── FooServiceITest.java +│ └── module-info.java +└── build.gradle.kts +``` ### Open questions: diff --git a/hedera-node/docs/design/services/service-modules.md b/hedera-node/docs/design/services/service-modules.md index bb7be5df64c7..8be8860d31ff 100644 --- a/hedera-node/docs/design/services/service-modules.md +++ b/hedera-node/docs/design/services/service-modules.md @@ -24,10 +24,10 @@ hedera-foo-service/ ``` The api modules should depend on the `com.hedera.node.app.spi` module and provide it as a transitive dependency. To do -so `api(project(":hedera-node:hedera-app-spi"))` must be a dependency in the gradle file. The module should only contain -the public api of services. The complete content of the module should be exported. Since the service interface that are -defined in the api modules will be loaded by the Java SPI the interfaces must be defined in the module info by using -the `uses` keyword. +so `requires transitive com.hedera.node.app.spi` must be a dependency in the `module-info.java` file. The module should +only contain the public api of services. The complete content of the module should be exported. Since the service +interface that are defined in the api modules will be loaded by the Java SPI the interfaces must be defined in the +module info by using the `uses` keyword. Based on this given constraints the `module-info.java` of an api module looks like this: @@ -49,14 +49,10 @@ plugins { } description = "Hedera Foo Service API" - -dependencies { - api(project(":hedera-node:hedera-app-spi")) -} ``` The public service api can depend on additional libraries. Such libraries will be defined as **public api** and must be -added as `api(...)` dependencies to gradle and defined as `requires transitive` in the `module-info.java`. No api module +added as `requires transitive` in the `module-info.java`. No api module must ever depend on any service implementation or the `hedera-mono-service` module. The `@NonNull`/`@Nullable` annotations can be used in the service definitions. Since the annotations are already defined as transitive dependencies at compile time by the `hedera-app-spi` module no extra dependency needs to be added. Unit tests and integration tests diff --git a/platform-sdk/README.md b/platform-sdk/README.md index 52919c105e2a..704b114197f0 100644 --- a/platform-sdk/README.md +++ b/platform-sdk/README.md @@ -7,8 +7,6 @@ - **Adoptium OpenJDK 17** - Available from [https://adoptium.net/temurin/releases/](https://adoptium.net/temurin/releases/) -- **Gradle 7.5.1** - - Available via the provided Gradle wrapper included in this repository. ### Standard Build Command @@ -23,6 +21,10 @@ cd hedera-services/platform-sdk ./gradlew build ``` +For more information, also refer to the +[documentation of the Hiero Gradle Conventions](https://github.com/hiero-ledger/hiero-gradle-conventions#build) +which this project uses. + ## Support If you have a question on how to use the product, please see our