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/lib
To 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
coreutils
package installed.
git submodule update --init
before the first buildgit submodule update
when 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.config
contains extra JVM options that has proved to speed up the build.maven.config
contains default Maven command line flags (not included, ignored by Git).maven-template.config
is 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:
core
contains the APIs to define and implement an Exonum service.core-native
contains the glue code between Java and Rust.app
is an application that runs a node with Java and Rust services.common
provides common functionality to Exonum core and light clients: Exonum proofs, hashing and cryptographic operations, serialization support.exonum-service-archetype
implements 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-core
artifact. 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.