@Xoom
@ResourceHandlers
@AutoDispatch
@Persistence
@EnableQueries
@Projections / @Projection
@Adapters /
@Adapter
@DataObjects
@Xoom
main()
method. In addition, when creating of a VLINGO XOOM application or microservice, we must instantiate World
, and pass it to other classes that use it for actors operation. So, that's what the @Xoom
annotation mainly provides.Initializer
class with a static main()
method, which is the hook for JVM in the application executionWorld
and Stage
with the AddressFactory
option, making the Stage
instance accessible for classes that request Actor
operations directly from it@Xoom
takes care of reading the properties file with the Mailbox
definition and starts a XOOM HTTP server. All of those tasks are achieved simply by annotating a basic class.name
attribute is the minimal information for running application with @Xoom
but there are also other attributes. Here's the full list.name
String
blocking
Boolean
addressFactory
Annotation
AddressFactory
type: BASIC
, UUID
, GRID
; and IdentityGenerator
type:RANDOM
, TIME_BASED
, NAME_BASED
@Xoom
attributes with non-default values.io.vlingo.xoom.turbo.XoomInitializationAware
.@ResourceHandlers
@Xoom
-related annotation for REST resources initialization. First, your custom resource class must extend io.vlingo.xoom.http.resource.DynamicResourceHandler
. This resource class should implement a constructor that takes a Stage
instance parameter. The resource class must also implement a routes()
method, through which fluent route mappings are possible, see XOOM HTTP.InsuranceResource
, annotate the initializer class providing the package containing the REST resource classes.@ResourceHandlers
supports two optional attributes, but only one must be set. value
Class <? extends DynamicResourceHandler> []
DynamicResourceHandler
subclasses.packages
String []
package
names that each contains some number of DynamicResourceHandler
subclasses.@AutoDispatch
@AutoDispatch
enables you to invest less in writing REST resources and broker/bus exchange message listeners so that you are able to focus on the core of your application, that is, the domain model. @AutoDispatch
resource. Now, following the order of how each annotation is placed in the code, let's understand how it works.@AutoDispatch
@AutoDispatch
, which is the root annotation and accepts these values:path
String
handlers
Class<?>
ProductResourceHandlers
class, declared in the @AutoDispatch
handler attribute in the previous code snippet. Looking at it, we can see the aggregate methods to which REST requests are going to be forwarded.HandlerEntry
relates an integer index to a function that invokes an aggregate method. Through that index, an aggregate/queries method can be set as the handler of a specific route as showed in the ProductResource
interface:HandlerEntry
generics. In other words, the first generic type, from left to right, is always the method return type, so, in the HandlerEntry
corresponding to the Product Registration,Completes<ProductState>
is the return type when Product.register
is invoked while Stage
and ProductData
are the parameter types.HandlerEntry
match with the parameter types supported by its corresponding route. However, in the previous example, Stage
is also a required parameter but it's not in the route signature. Fortunately, at compile-time, Stage
and Logger
are automatically included as an instance member in the auto-dispatch resource class. Just be aware that, for accessing any instance member inside a HandlerEntry
function, you need always to use the $ + memberName
pattern (e.g $stage
, $logger
).HandlerEntry
is served by a set of interfaces for parameter type declaration which allow you to inform two to five parameter types:@AutoDispatch
resources, you are freed from annotating your bootstrap class with @ResourceHandlers
. @Model / @Queries
@Model
and @Queries
class-level annotations meets the condition that a @AutoDispatch
route must perform operations on a specific aggregate entity or read data from a query actor. That implies you have to use at least one of these annotations and, at most, one of each. Here's the supported field list:protocol
Class<?>
actor
Class<? extends EntityActor/ Actor>
data
Class<?>
@Queries
, you are able to access the queries actor inside the HandlerEntry function through the instance member named as $queries
:@Route
@Route
annotation has to be used at method-level mainly declaring a HTTP method. Optionally, you may inform a relative URI subpath and its handler index.method
io.vlingo.xoom.http.Method
path
String
handler
int
@ResponseAdapter
handler
int
@Id
@Id
indicates a route operation that is performed on an existing entity and makes VLINGO/XOOM responsible for loading it. So, the benefit is that you can just take care of using the loaded entity inside the HandlerEntry
function. ProductResource
and see how it works:@Id
. Afterwards, its handler function is much simpler because it's benefited by the auto-loaded entity:product
parameter is exactly the corresponding entity to the id passed in the route parameter.@Body
@Body
simply tells XOOM HTTP to deserialize the request payload into that parameter. In the following example, the payload is deserialized into a ProductData
object.@Persistence
onInit()
method you can choose to manually create the code for the application infrastructure, as in the Hello, World example.@Persistence
for a more succinct way to set up the persistence. By using that annotation, VLINGO XOOM supports auto-configuration of:Storage Type
for the Domain Model;State Store
for the Query Model and the selected Storage Type
for the Command Model;@Persistence
attributes:basePackage
String
cqrs
Boolean
vlingo-xoom.properties
database
VLINGO_XOOM_DATABASE
database.name
VLINGO_XOOM_DATABASE_NAME
database.driver
VLINGO_XOOM_DATABASE_DRIVER
database.url
VLINGO_XOOM_DATABASE_URL
database.username
VLINGO_XOOM_DATABASE_USERNAME
database.password
VLINGO_XOOM_DATABASE_PASSWORD
database.originator
VLINGO_XOOM_DATABASE_ORIGINATOR
IN_MEMORY, POSTGRES, HSQLDB, MYSQL, YUGA_BYTE
.database
becomes query.database
, the environment variable VLINGO_XOOM_DATABASE
becomes VLINGO_XOOM_QUERY_DATABASE.
vlingo-xoom.properties
:@Persistence
and can be only used along with it. @EnableQueries
is an annotation correlated to @Persistence
and provides the proper way to make VLINGO XOOM responsible for handling your query actor implementations. In other words, using this essential annotation, these implementations become a QueryStateStoreProvider
property, so we only need to take care of accessing it and using it. For a practical understanding, take a look at the following configuration class:@EnableQueries
only accepts a combination of actor/protocol classes surrounded by the@QueriesEntry
annotation which supports the following types:protocol
Class<?>
QueriesActor
protocol classactor
Class<?>[]
Array
of supported DomainEvents
@EnableQueries
properly configured, which also includes the attribute cqrs
of@Persistence
set to true, makes the compile-time generated QueryStateStoreProvider
the holder of all mapped queries actors. So, as an illustration, let's say we need to use the CustomerQueries
serving a rest resource:@Projections
relates the projections to their supported events, so DomainEvents
can be projected into the Query Model.@Projections
accepts only a list of @Projection
with a pair of attributes:actor
Class<? extends
StateStoreProjectionActor>
ProjectionActor
classbecauseOf
Class<?>[]
Array
of supported DomainEvents
@Adapters
for Aggregate/Entity state translation, so the object state within a service or application can be serialized to be persisted, and vice-versa. Here's how to set up:@Adapters
and @Projections
are not dependent but both can be naturally used together as follows:@DataObjects
, VLINGO XOOM can also take care of the creation of database tables for data objects, which are commonly used for holding your query model data. All you need to do is to map the data objects as demonstrated below: