Posted on September 14, 2020

Spine 1.6.0

This release brings numerous API improvements, as well as fixes and infrastructure updates to the framework.


API changes

Execution environment

  1. Custom environments support is introduced [#539, #542, #545].

    The Environment now exposes API to register user-defined environment types. This can be done by extending the EnvironmentType class:

     public final class AwsLambda extends EnvironmentType {
         public boolean enabled() {
             // ...

    Then, the environment can be registered to give the user ability to check if it’s active at any given moment of time:

                .register(new AwsLambda());
     // ...
     if (Environment.instance().is(AwsLambda.class)) {
         this.sender = new AwsEmailSender();

    The Spine framework provides two environments out of the box: Production and Tests.

  2. The io.spine.testing package is added to the list of known testing libraries. When it occurs in the class path, the environment will always be resolved to Tests [#544].

Protobuf Model definition

  1. (min), (max) and (range) constraints will now be verified to be the whole numbers when applied to a whole number field (int32, etc.) [#560].

  2. (is) and (every_is) options will now be applied simultaneously instead of (is) taking priority over (every_is) [#531].

  3. New tools are added for working with regex-es in Protobuf [#520].

  4. An (is_required) validation option is added for oneof group fields [#523].

  5. The spine.ui.Language enumeration is now defined and contains language codes defined by ISO 639-1 [#522].


JSON parser will now ignore unknown fields, allowing easier data migrations between old/new Protobuf schemas [#518].


  1. The Spine protoc plugin location process is simplified. This enables creation of composite builds for Spine-based projects [#559].

  2. Time is tweaked to provide identical behaviour on all platforms under Java 8 and Java 9+ [#554].

  3. The proper import resolution is implemented for the Dart client [#524].

  4. javax.annotations-api dependency is added to the project so the Spine protoc plugin can be run safely with Java 11 [#546].


  1. Stricter Gradle task ordering is introduced to eliminate randomness in build execution and improve the process reliability [#562].

  2. The project build scripts are migrated to Kotlin [#532, #534].

Core Java

API changes


  1. The ability to postAndForget() a command is added to the Client. This method should be called when the user does not care about events/rejections produced by a command.

    The previously used post() method is reserved for cases when one or more event types are actually observed by the client. The value returned by post() can no longer be ignored [#1292].

  2. Event subscriptions are now more flexible, allowing to subscribe to events produced by non-entity objects (e.g. AbstractEventReactor) as well as events not explicitly declared in any BoundedContext [#1258].

  3. The Client is extended with methods to handle streaming and server errors when executing requests [#1270].


  1. The custom environments support is introduced [#1274, #1293].

    The Environment now exposes API to register user-defined environment types and to determine which one is enabled at any given moment of time. See the release notes of base.

    The ServerEnvironment allows to configure environment-dependent values, as follows:

    StorageFactory factory = InMemoryStorageFactory.newInstance();
                     .use(factory, Tests.class);

    The Spine framework provides two environments out of the box: Production and Tests.

  2. Breaking change: Most of the @Internal methods of BoundedContext moved to its internal class InternalAccess instance of which is available via the internalAccess() method.

    The method is available only to the server-side framework code.

  3. Delivery API is extended with a factory method which allows to create asynchronous version of local Delivery [#1265].

  4. The Pair can now be created from an already existing Optional [#1296].

  5. The proper support to the CommandBus filters which throw rejections is added [#1295].


  1. The @External annotation is introduced to mark the handler method parameters of an external origin. It replaces the previously used for this purpose (external = true) attribute of @Subscribe, @React, and @Command annotation. The attribute is deprecated [#1269].

  2. (set_once) constraint in entity states is no longer ignored [#1268].

  3. @ByField is deprecated in favour of @Where [#1270].


  1. The DiagnosticLog messages are made more detailed [#1262].

  2. The standard framework exceptions are expanded with more info [#1255].


Various quality-of-life changes are introduced for the testing API.

See #1249, #1251, #1252, and #1261 for details.

Some of the testing API changes are breaking. They include:

  1. BlackBoxBoundedContext is renamed to BlackBoxContext.
  2. Outdated Verify-based API is removed.
  3. BlackBoxContext no longer exposes eventBus() and commandBus().
  4. The BlackBoxContext.subscribeTo(Topic) semantics changed. See #1249.
  5. Simplified combinations of UserId and ZoneId parameters of BlackBoxContext.


The Migration logic is fixed to properly support entity state updates [#1298].


The project build scripts are migrated to Kotlin [#1278].


With this release the bootstrap plugin receives support for more automated project configurations [#65].

Library dependencies

It’s now possible to add some of the Spine libraries to project dependencies through the API provided by the plugin. This includes:

  • the Google Cloud Datastore storage implementation:
      spine.enableJava {
  • web API library:
  • web library with integration over the Firebase Realtime Database:

IDEA configuration

If both Bootstrap and the idea plugin are applied, Bootstrap configures the idea plugin, so that the IDE displays sources and generated sources as expected.


The project build scripts are migrated to Kotlin [#50].


API changes

  1. The JS Client now supports multitenancy [#141].

    The Client factory API now accepts a TenantProvider as an element of the passed client options.

    The TenantProvider defines the current tenant ID to be used for all requests done with the client. The current tenant ID can be dynamically updated with the help of TenantProvider.update(tenantId). For single-tenant applications, the TenantProvider can be omitted in the options.

    Multitenant client usage example:

     let tenantProvider = new TenantProvider(initialTenantId());
     let client = spineWeb.init({
     		protoIndexFiles: [protoIndex],
      		endpointUrl: endpointUrl,
      		firebaseDatabase: firebaseDatabase,
       		actorProvider: new ActorProvider(),
       		tenantProvider: tenantProvider
     // …
  2. The FirebaseCredentials are now constructed from GoogleCrendetials rather than the deprecated GoogleCredential. The factory method accepting GoogleCredential is deprecated [#137].

  3. The onRejection callback of CommandRequest is renamed to onImmediateRejection to better reflect its purpose [#151]. See also the corresponding changes in core-java.


  1. The JS client docs are now published to [#136].

  2. The project build scripts are migrated to Kotlin [#142].

Google Cloud Java

A public release of Datastore-related Spine libraries.

Notable changes

  1. The definition of Pub/Sub push request message is added [#150].

    It can be used for endpoints that are used with Pub/Sub push subscriptions in order to easily transform incoming JSON data into a respective Protobuf definitions.

  2. The project build scripts are migrated to Kotlin [#148].

JDBC Storage

A public release of Spine library supporting the JDBC-compliant storage engines.

The library as of now is still in the experimental status.


The project build scripts are migrated to Kotlin [#148].


A public release of Spine time library.