Exonum Java is open to any contributions, whether it is a feedback on existing features, a request for a new one, a bug report or a pull request. This document describes how to work with this project:
- how to build it
- how to test it
- the code style guidelines
- how to submit an issue
- how to submit a PR
Such as this project has sub-projects with sub-modules it is possible to build the whole project as well as any of the sub-projects separately. This guide shows how to build the whole project only.
You need to install the following dependencies:
- Linux or macOS. Windows support is coming soon.
- JDK 11+.
- Maven 3.5+.
- Stable Rust compiler. The minimum supported version is Rust 1.41.0.
- The system dependencies of Exonum. You do not need to manually fetch and compile Exonum.
Important: It is necessary to install RocksDB
package and to set the environment variable ROCKSDB_LIB_DIR.
To install the package on Ubuntu:
sudo add-apt-repository ppa:exonum/rocksdb
sudo apt-get update && sudo apt-get install librocksdb6.2
export ROCKSDB_LIB_DIR=/usr/libTo install the package via Homebrew on Mac:
brew install rocksdb
export ROCKSDB_LIB_DIR=/usr/local/lib- For automatic packaging of the Exonum Java app you need CMake installed in your system.
Also on Mac you need a
coreutilspackage installed.
git submodule update --initbefore the first buildgit submodule updatewhen the submodule revision changes.
Set required environment variables, once in a shell you use to build the project:
$ source exonum-java-binding/tests_profile
Then run:
$ ./run_all_tests.sh
Run:
$ cd exonum-java-binding
$ ./package_app.sh
This command will build and package Exonum Java app with all the necessary runtime dependencies
in a single zip archive in exonum-java-binding/packaging/target directory.
Before packaging, the script will also run all the tests to guarantee that the generated application
is valid. It may take a long time, so you can pass --skip-tests flag to skip tests running:
$ ./package_app.sh --skip-tests
By default, the Exonum Java app is built in debug mode, which affects performance
and is not desired for production usage. To enable release mode, you need
to pass --release flag to the package_app.sh script.
Each independent module and the root aggregator project contain .mvn directory
with Maven configuration files.
jvm.configcontains extra JVM options that has proved to speed up the build.maven.configcontains default Maven command line flags (not included, ignored by Git).maven-template.configis a template file with some configuration options that can be copied in a localmaven.config. Some options that can be considered:--threads 1C— will activate parallel builds. Independent modules will be built concurrently, with the given number of threads (here — 1 times the number of available cores).-Djunit.jupiter.execution.parallel.enabled=true+-Djunit.jupiter.execution.parallel.mode.default=concurrent— enable parallel JUnit 5 test execution.-Djacoco.skip— if you never browse the local reports when running all tests.
Why `.mvn` is present in each independent module?
Remember that configuration files in .mvn are used when Maven is launched from
its parent directory; or when you build a child project in multi-module build, the
parent’s .mvn is used. For example, if you build core, ../.mvn will be picked up because
core is a child of ejb-parent; but if you build ejb-parent, ../.mvn will not have any
effect because ejb-parent is not a child of exonum-java-parent.
See Maven configuration documentation for details.
Run mvn clean -DcleanRust.
The Exonum Java Binding project is split into several modules. Here are the main ones:
corecontains the APIs to define and implement an Exonum service.core-nativecontains the glue code between Java and Rust.appis an application that runs a node with Java and Rust services.commonprovides common functionality to Exonum core and light clients: Exonum proofs, hashing and cryptographic operations, serialization support.exonum-service-archetypeimplements an archetype generating a template project of Exonum Java service.
There are several categories of tests:
- Unit tests in Java and Rust modules.
- Integration tests in Java, some of which require a native library.
- Integration tests in Rust that require a JVM together with
ejb-coreartifact. Reside incore-native. - System tests — these are currently performed internally and use a QA-service.
For convenience, the tests are divided into several groups. To run all tests, invoke this script:
$ ./run_all_tests.sh
The following scripts can be run separately from the exonum-java-binding directory:
./run_maven_tests.sh— all tests in Java and unit tests in Rust../run_native_integration_tests.sh— integration tests in Rust../run_app_tests.sh— application tests in Rust../run_tutorials_tests.sh— tutorials tests in Java.
Use JUnit + Mockito or hand-written fakes. Currently there is no project-wide default for an assertion library: Hamcrest and AssertJ are used in various modules.
The integration tests in core are bound to verify phase of the Maven build.
The name of IT classes must end with IntegrationTest.
If your test verifies the behaviour of a class with native methods,
or depends on such classes, the native library is required,
which can be loaded with LibraryLoader.load().
IntelliJ IDEA infers the JVM arguments from the pom.xml and runs ITs just fine.
If you use another IDE, configure it to pass -Djava.library.path system property
to the JVM when running tests. For more details, see the failsafe plugin
configuration.
All tests require several environment variables to be set.
These variables with the brief explanation can be found in the ./tests_profile script.
They can be imported into the current shell with source ./tests_profile.
It’s more convenient to use the corresponding ./run_XXX_tests.sh script.
Java code must follow the Google code style.
Checkstyle checks the project
during validate phase (i.e., before compilation) of the build. You can also run it manually:
$ mvn validate
Development builds only report violations, pass -P ci-build to fail the build in case of violations.
Rust code follows the Rust style guide.
rustfmt enforces the code style.
After installation, you can run it with
$ cd exonum-java-binding/core/rust
$ cargo +stable fmt --all -- --check
Use Github Issues to submit an issue, whether it is a question, some feedback, a bug or a feature request: https://github.com/exonum/exonum-java-binding/issues/new
JIRA is for internal use so far and is not publicly available yet.
Before starting to work on a PR, please submit an issue describing the intended changes. Chances are — we are already working on something similar. If not — we can then offer some help with the requirements, design, implementation or documentation.
It’s fine to open a PR as soon as you need any feedback — ask any questions in the description.