Posted on December 30, 2016

Spine 0.7.0

Core Java

New artifact IDs for Core Java modules

Gradle:

repositories {

   // Spine releases repository.
   maven { url = 'http://maven.teamdev.com/repository/spine' }

}

dependencies {

    compile 'org.spine3:spine-server-core:0.7.0'
    compile 'org.spine3:spine-client-core:0.7.0'

    compile 'org.spine3:spine-users:0.7.0'
    compile 'org.spine3:spine-values:0.7.0'

    testCompile 'org.spine3:spine-testutil-core:0.7.0'
}

Handling changes and mismatches of values

This version introduces Protobuf types for describing field changes. Examples are StringChange, TimestampChange, Int64Change, etc. For more types, please see the spine/change/change.proto file.

These types are for being used in commands (to request a change) and events (to describe the change made).

The ValueMismatch type allows to fire a failure when an entity already had a value of a field, which differs from one described as a previousValue of corresponding change request. Please also see Java utility classes in the org.spine3.change package for details.

Wildcard (by) option was introduced for enrichments

Now a single enrichment message can be used with multiple target events. E.g.

message EnrichmentForSeveralEvents {
     string username = 1 [(by) = "*.user_id"];
}

message EventOne {
     option (enrichment) = "EnrichmentForSeveralEvents";

     int32 user_id = 1;
}

message EventTwo {
     option (enrichment) = "EnrichmentForSeveralEvents";

     int32 user_id = 1;
}

Behavioural changes and improvements

Automatic ProjectionRepository catch-up after #initStorage

As we discovered from the real-world cases, the catch-up for the ProjectionRepository is typically initiated right after the storage factory is set. E.g.

// Spine 0.6.0: 
repository.initStorage(storageFactory);
repository.catchUp()

Now the default behaviour is to invoke #catchUp automatically. So less code, less mistakes. E.g.

// Spine 0.7.0: 
repository.initStorage(storageFactory);

Of course, you can always turn off the automatic catch-up passing false to the ProjectionRepository constructor.

ProcessManager changes

ProcessManagers may now have no commands handled. So it is now possible to build the process on top of events only.

Syntax sugar for type names

Some sugar is now available to get the type name for a Message. E.g.

// Spine 0.6.0:
String name =  TypeUrl.of(msg).getTypeName();

// Spine 0.7.0.
String name = TypeName.of(msg);

System and runtime improvements

Aggregate state double-checking upon update

Improvements were made to keep the Aggregate state consistent across different threads or even scaled instances of the application. Now Aggregate repository checks that no new events have arrived to the event storage since the start of the command processing.

In case any new events are detected, the processing of this command is repeated.

CommandBus configuration

CommandBus can now be configured to avoid spawning new threads during the bus operation. It is helpful for sensitive target runtimes such as Google AppEngine. E.g.

final CommandBus commandBus = CommandBus.newBuilder()
                                        // Allowed by default. Let's disable.
                                        .setThreadSpawnAllowed(false)
                                        .build();

Core singletons made thread-safe

ConverterRegistry and DefaultStateRegistry made thread-safe.

Validation

Goes option introduced

Declarative validation rules for the Protobuf model were extended with (goes) option. It is now possible to declare a message field that can only be present if another field is present. E.g.

message ScheduledItem {
     ...
     spine.time.LocalDate date = 4;
     spine.time.LocalTime time = 5 [(goes).with = "date"];
}

Required option simplified

(required) Protobuf option has been simplified and is now a bool instead of a RequiredOption message. E.g.

// Spine 0.6.0:
MyMessage field = 1 [(required).value = true];

// Spine 0.7.0.
MyMessage field = 1 [(required) = true];

Structural Changes:

  • CommandBus made configurable via CommandBus.Builder instead of CommandBus#newInstance.

General Improvements

  • Date/Time API improvements.
  • Entity version is now propagated to Stand upon an update. That allows to store the version properly in StandStorage.

Dependency Updates

  • Guava 20.0
  • gRPC 1.0.2
  • Protobuf 3.1.0

Spine is now integrated with Codacy, exposing the code quality metrics to everyone.