Posted on October 17, 2017
Spine 0.10.0
Core Java
This release brings even more features to the framework, making it very close to 1.0
release.
IMPORTANT. The framework package names were renamed from org.spine3.*
to io.spine.*
.
Here is a quick summary of changes. For more details please refer to the list of pull requests and Javadocs.
Reacting upon Events
and Rejection
s
It is now possible to emit events in reaction to other events. This is particularly useful
for AggregatePart
s:
/**
* A part of {@code Task} aggregate. Defines the essence of a task.
*/
public class TaskDefinition
extends AggregatePart<TaskId, Task, TaskVBuilder, TaskRoot> {
@Assign
public TaskCompleted handle(CompleteTask cmd) {
// Handle the command and emit a `TaskCompleted` event.
// ...
return taskCompletedEvent;
}
@Apply
void on(TaskCompleted event) {
// Update state accordingly.
// ...
}
}
/**
* Another part of {@code Task} aggregate. Responsible for all comments
* of a single task.
*/
public class TaskComments
extends AggregatePart<TaskId, TaskComments, TaskCommentsVBuilder, TaskRoot> {
@React
public TaskCommentingDisabled handle(TaskCompleted event) {
// Disable commenting of the completed task.
//...
return commentingDisabledEvent;
}
@Apply
void on(TaskCommentingDisabled event) {
// Update own state as well.
// ...
}
}
In the example above TaskComments
reacts to the event, emitted by another part and updates
own state. Before such a feature became available, an intermediate ProcessManager
should have
been used for this purpose.
It is also possible to @React
upon a rejection in the same manner.
This feature is available for Aggregate
, AggregatePart
and ProcessManager
entities.
Entity API Updates
All the Entity
implementations, which are able to handle events, are now descendants of a newly
introduced EventPlayingEntity
. Its API allows to play events in a unified fashion.
Entity state modification is now available via ValidatingBuilder
.
The direct state update, which was previously available to Projection
s, Aggregate
s and
ProcessManager
s via numerous methods (such as updateState
and incrementState
), is NOT
available anymore. The designed way to modify the entity is via getBuilder().set...
calls.
In addition, an automatic version management is introduced. For each applied event the version is automatically incremented. Direct version modification is not exposed as public API anymore.
For more details please see #466.
Entity Column Queries
It is now possible to use EntityColumn
s in the queries:
public class CustomerProjection
extends Projection<CustomerId, Customer, CustomerVBuilder> {
// ...
// Defines an entity column.
public PersonName getContactName() {
return getState().getContactPerson().getName();
}
}
Then in your client code:
// Retrieve customers by a contact name.
// Obtain the parameters for the query from somewhere like user interface.
final PersonName contactName = getContactName();
// Create the `Query` instance.
final Query customerQuery = myRequestFactory.query()
.select(Customer.class)
.withMask("id", "address", "domain")
.where(eq("contactName", contactName))
.build();
// Get the client stub of the `QueryService`.
final QueryService queryService = getServerApi();
// Execute the query, setting the callback for results.
queryService.read(query, callback);
In the example above the results will contain customers, whose contactPerson.name
value
matches the one set in the query.
IntegrationBus
To integrate several BoundedContext
s, an IntegrationBus
is defined. It allows to subscribe
to so called “external” events in one BoundedContext
to receive events of a required type
from another BoundedContext
.
E.g. the first bounded context Projects
defines an external event handler method in
the projection as follows:
public class ProjectListView extends Projection<...> {
@Subscribe(external = true)
public void on(UserDeleted event) {
// Remove the projects that belong to this user.
// ...
}
// ...
}
Let’s say the second bounded context is Users
. In case these bounded contexts share the same
transport, any UserDeleted
event emitted inside of Users
will also get delivered to
ProjectListView
of Projects
bounded context. It will be done via IntegrationBus
.
For more details see #580.
One-liner updates
- Base data types and utilities have been extracted into
base
repository. core
module was introduced in thecore-java
repository; it defines classes and interfaces, that are essential for building application in the Event Sourcing paradigm.- Custom Protobuf options defined by the framework now take numbers in the range
73812-75000
. Failure
is renamed toRejection
to comply with Reactive Manifesto definition of “Failure” better.EndpointDelivery
strategy is now available; it allows to define how messages are delivered to particularEntity
instances.- Entity visibility options are added;
VisibilityGuard
is a registry of repositories that controls an access.
Version updates
- Gradle 4.1.
- Protobuf 3.3.0.
- gRPC 1.4.0.