In Polypheny, we manage our Java dependencies via Gradle, aiming for consistency and maintainability across our stack. This guideline outlines the best practices for integrating these dependencies into Polypheny-DB and other components of the Polypheny stack.
‘java-library’ Plugin
In Polypheny-DB, we use the java-library
plugin instead of the java
plugin. The java-library
plugin offers extended capabilities over the java
plugin, allowing a more refined handling of dependencies. For more information on the java-library
plugin, you can refer to the official documentation.
Adding Dependencies
The java-library
plugin introduces two new configurations, api
and implementation
, that we use in place of compile
for adding dependencies.
API
The api
configuration should be used when you want to include a dependency that needs to be available to all other subprojects having your project as a dependency. Here is an example:
dependencies {
api group: "com.example", name: "example-lib", version: example_lib_version
}
Implementation
The implementation
configuration should be used when a dependency is required merely for the implementation of your functionality and doesn’t need to be exposed to the subprojects that include your project. Here is an example:
dependencies {
implementation group: "com.example", name: "example-lib", version: example_lib_version
}
implementation
.
Test Dependencies
Test dependencies are those libraries that are used solely for testing purposes and are not required in production runtime. Just like our regular dependencies, we manage these using Gradle.
Just like the main dependencies, test dependencies are added using the testImplementation
and testApi
configurations. The distinction between these two is the same as for implementation
and api
configurations, but it’s applied to the testing context. That is, testImplementation
is used when a dependency is needed only for testing within the module, and testApi
is used when a testing dependency needs to be shared among multiple modules.
In order to make the test classes of the core module available, you can add them as dependency:
testImplementation project(path: ":core", configuration: "tests")
Version Numbers
To ensure that all subprojects use the same version of a dependency, we store version numbers in the gradle.properties
file. This approach fosters consistency across our projects.
In your build.gradle
file, the version part should reference the property from gradle.properties
. For instance:
dependencies {
implementation group: "com.example", name: "example-lib", version: example_lib_version
}
Then, you need to add a corresponding entry in the gradle.properties
file like so:
...
example_lib_version = 23.1.2
...
Gradle Licensee Plugin
The Gradle Licensee plugin is a nifty tool we used to check the licenses of our project dependencies. It works by scanning the project’s dependencies and comparing them against a list of allowable licenses. This ensures that only dependencies with licenses that comply with your project’s licensing policy are bening used.
The plugin is configured to fail the build if it encounters any dependency with an unacceptable or unknown license. It is automatically applied to all modules in Polypheny-DB.
licensee {
allow('Apache-2.0')
allow('MIT')
//...
allowDependency('com.example', 'example-lib', '1.15') { because 'Reason why it compatible (e.g., the license)' }
}
The allowDependency function is used to explicitly allow specific dependencies that might not be covered by the licenses stated in the allow functions. This is particularly useful when a dependency’s licensing is compatible with Polypheny’s licensing policy, but may not be automatically recognized by the plugin. Remember to include a justification for allowing the dependency, providing transparency and maintainability to your codebase.
Importantly, as a safety measure, when adding dependencies in this manner, do not use the version variable defined in the gradle.properties file. Instead, explicitly state the version in the allowDependency function. This provides an additional layer of protection, ensuring that the dependency is validated for the exact version specified.