The Modeling Language

Talon aims to make working with messages and state as simple as working with Plain Old Java Objects (POJOs). The Application Data Modeler (ADM) defines an XML language to model messages and state entities and tools to generate message and state classes. The generated code handles encoding, serialization and transactional functionality that underpin the platform. This section describes how to model messages and state and to use the code generation tools.

Overview

The following depicts the various sections of an ADM model.

<model xmlns="http://www.neeveresearch.com/schema/x-adml"
       xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
       namespace="com.example.trading"
       name="MyModel"
       doc="My model"
       defaultFactoryId="100" >
     
  <import model="../other/model.xml"/>
  <import model="com/mynamespace/messages.xml"/>
  <factories>
    <factory name="MyObjectFactory" id="1" />
  </factories>
 
  <enumerations>
    <!-- Enumerations -->
  </enumerations>
 
  <types>
    <!-- Semantic types -->
  </types>
 
  <fields>
    <!-- reusable field definitions -->
  </fields>
 
  <messages>
    <!-- Messages -->
  </messages>
 
  <entities>
    <!-- Entity Definitions -->
  </entities>
 
  <collections>
    <!-- Collection Definitions -->
  </collections>
</model>

Messages

The messages section contains message definitions.

  • Each message is assigned a numeric id.

    • Message ids must be unique across all messages, entities and collections in a model and should only be reused over the lifetime of the model per the ADM model versioning rules.

  • Each message is comprised of a set of fields.

  • Each field is of a type supported by the ADM Type System.

  • Each field is assigned a numeric id.

    • Field ids must be unique within a message definition and should only be reused over the lifetime of a message definition per the ADM model versioning rules.

The following defines an AddCustomerMessage message. It contains the following fields

  • A field named firstName of type String with an id of 1.

  • A field named lastName of type String with an id of 2

  • A field name age of type Integer with an id of 3

  • A field named address of type Address with an id of 4.

    • Address is an Embedded Entity type

The state and city fields in the Address entity are enumerations whose definitions are not depicted in the example below.

See Fields for more information on the various attributes in the field element

Each message definition generates a Java class. The class's namespace is the model's namespace, and the class name is the name of the message in the model. The following is a code snippet depicting how the generated message is instantiated and populated.

See Messages for more information

Entities

The entities section contains entity definitions. There are two types of entities:

  • State Entities

  • Embedded Entities

Each entity definition supports an asEmbedded attribute. An entity with asEmbedded=false is a state entity while an entity with asEmbedded=true is an embedded entity.

Embedded Entities

An embedded entity is a field container just like a message in that it can contain fields of types from the ADM Type System. Embedded entities are technically part of the ADM Type System and, as such, can contain fields that reference other embedded entities as the field type. Embedded entities cannot contain fields that reference other state entities and collections as the field type.

State Entities

State entities are used to model a microservice's state tree. A state entity is a field container just like a message or embedded entity except that state entities can contain fields that reference other State entities and collections as the field type. These references to other state entities and collections form the parent child relationships in the modeled state tree.

The following is an example of a state tree modeled using ADM

In the above, the Customer entity contains an embedded Address entity and references a child Order entity. The Customer-Order relationship is a parent-child relationship in the state model.

Setting and getting referenced state entities is the same as with embedded entities. Here is an example that illustrates the creation and population of a Customer entity object

Difference Between a State and Embedded Entity

The difference between a state entity and embedded entity is related to object serialization. When a message, state entity or embedded entity containing another embedded entity is serialized, then the contents of container message, state entity or embedded entity and the contained embedded entity are all serialized together into the same unit of transportation and/or persistence. However, when a state entity A contains a field that references another state entity B as uts type, then when A is serialized, it only serializes the contents of A and not B. In other words, a state entity containing a field that refers to another state entity is a referential relationship while a field of an embedded entity type is a containment relationship.

In the above example, if the Customer object was serialized, the serialized contents would contain the Customer fields and the Address fields. If the serialized contents were used to materialize a new Customer object, then the Address field would also be present in the materialized Customer. However, when the Customer object is serialized, the serialized contents do not contain the serialized form of the Order object i.e. the order field would be null in the Customer object materialized from the serialized contents. In other words, when the state tree is persisted, each node in the tree is persisted independently and the relationships reconstituted when deserialized from the persisted form. The storing and reconstituting of the relationships between the objects is done by the Talon runtime during state persistence and replication so that the application always works with the fully constituted object tree.

See Entities for more information

Collections

The Collections section contain collection definitions. A Collection is a collection of State Entities of one of the following types

  • Queue

  • LongMap

  • StringMap

Collections are part of a state tree model. It serves as a node in the state tree that is a child node of the State Entity that references the Collection and is the parent node of each State Entity that it contains. Here is an example to illustrate this

The above model is the same as the prior model but extended to hold a collection of Customer state entities in a map keyed by the customer id of type Long. The following code illustrates how to work with code generated from the above.

See Collections for more information

Factories

Message and Object factories are used by the Talon runtime to convert message and state POJOs to and from its serialized form that is transported on the wire and/or persisted to disk. Talon provides programmatic and configuration mechanisms by which message and object factories are registered with Talon SMA and ODS runtimes for this purpose.

The factories section defines the various factories generated by the model. Each factory is assigned an id that needs to be unique in the entire system. In addition, each message, state entity and embedded entity is assigned a factory id that must be one of the ids of the factories defined in the factories section. The model also contains a defaultFactoryId attribute that set the default factory id for those messages and entities that don't have a factory id explicitly assigned to them. The defaultFactoryId also needs to be one of the ids of the factories defined in the factories section of the model.

Enumerations

Enumerations are part of the ADM Type System. The enumerations section contains definitions of the various enumerations in the model. The following example illustrates how an enumeration - the PaymentTerms enumeration used by the terms field in the Order entity - is defined.

The ADM code generator generates a Java enum class for each enumeration defined in a model.

Namespace

Each model contains a namespace attribute. This value of this attribute is sets the name of the package of the generated classes. For example, in the below model, all the generated classes - AddCustomerMessage, Customer, Address, PaymentTerms, Order and Customers - are in the same com.mycompany Java package.

Imports

Since ADM models are essentially class definitions, Talon aims to enable developers to work with these models as development artifacts equivalent to Java classes. The first part of this integrated support with build tools to inject the code generation seamlessly into the build cycle. The other is the ability to import models as one would do with Java classes.

The imports section defines models that contain entity definitions that are referenced in other models. Once a model A is imported into another model B, then entities in B can reference entities in A.

See Imports for more information.

Fields

The ADM model allows fields either to be defined in place (directly on the message or entity that is using the field) or by reference to a field declared in the model's fields section. It is a matter of preference which approach an application developer uses: if many messages contain the same field, then it may be more convenient to model the fields in a reusable fashion in the element, but in other cases, it may be more convenient to define the fields in place.

The following is an example that illustrates the use of field definitions>

See Fields for more information.

Types

The types section is used to define types based on the platform's primitive and built-in types. Such semantic types can be used in place of their corresponding primitive type in the model and will inherit their documentation. The type used for the field in generated messages and entities will be the base type specified by the named field.

The following is an example that illustrates the use of semantic types

See Semantic Types for more information.

The ADM Type System

ADM supports the following types.

  • Primitive Types

  • Primitive Type Arrays

  • Enumerations

  • Enumeration Arrays

  • Embedded Entities (Field Groups)

  • Embedded Entity Arrays

These types can be used as field types for fields in messages and entity definitions in an ADM model.

Primitive Types

ADM Type
Java Type

Boolean

boolean

Byte

byte

Char

char

Short

short

Integer

int

Long

long

Float

float

Double

double

String

java.lang.String

com.neeve.lang.XString

Date

java.util.Date

Primitive Type Array

ADM Type
Java Type

Boolean[]

boolean[] com.neeve.lang.XBooleanSequence

Byte[]

byte[] com.neeve.lang.XByteSequence

Char[]

char[] com.neeve.lang.XCharSequence

Short[]

short[] com.neeve.lang.XShortSequence

Integer[]

int[] com.neeve.lang.XIntSequence

Long[]

long[] com.neeve.lang.XLongSequence

Float[]

float[] com.neeve.lang.XFloatSequence

Double[]

double] com.neeve.lang.XDoubleSequence

String[]

java.lang.String[] com.neeve.lang.XStringSequence

Date[]

long[] com.neeve.lang.XDateSequence

Enumerations

ADM Type
Java Type

{enumeration name}

{model namespace}.{enumeration name}

Enumerations are defined in the enumerations section of the ADM model. The name of the enumeration can be used as the type of message and entity fields. See Enumerations for sample and more details.

Enumeration Array

ADM Type
Java Type

{enumeration name}[]

{model namespace}.{enumeration name}[] com.neeve.lang.X{Enum Type}Sequence

Embedded Entity

ADM Type
Java Type

{entity name}

{model namespace}.{entity name}

Embedded entities serve as field groups and can be referenced as a type by fields in entities and messages. Embedded entities are defined in the entities section of the ADM model.

Embedded Entity Array

ADM Type
Java Type

{entity name}[]

{model namespace}.{entity name}[] com.neeve.lang.XLinkedList<{model namespace}.{entity name}>

The ADM Model

ADM models are XML models specified by the x-adml.xsd schema included at the root of the nvx-rumi-adm-<version>jar. Be sure to update your editor's schema validator to reference it.

If you are working in an IDE such as Eclipse, try importing the ADM XSD schema into your eclipse XML catalog so that you can get usage tips on the ADM model by pressing control-space.

Root Element

The root element of a message model is the model element, which is used to define a namespace qualified set of modeling elements. To conform to x-adml.xsd schema and pass validation, a model must define target XML namespace xmlns="http://www.neeveresearch.com/schema/x-adml". This is not to be confused with the namespace attribute described below.

The following table describes the various attributes of the root element

Attribute
Description
Required

name

The Model name can now be specified in the model element itself instead of being supplied externally. If the name contains spaces, then in cases where it used as type name it will be converted to camel case with no spaces (for example "Trading model" would become "TradingModel")

No

namespace

The model's namespace. Model elements use the model namespace as the package name when generating other models, and model importing another model refer to imported model elements using the imported model's namespace.

Yes

defaultFactoryId

The default factory id to be used on model elements that require a factoryId but don't specify one. If the model doesn't define a factory element with a matching id, one is created implicitly by camel casing the model name and appending 'Factory', e.g. TradingFactory.

No

doc

A brief one-line description of the model.

No

Model Name

The ADM model has a name property which is used in certain ways during code generation.

For example, the name of the model is used with the Protobuf code generator as follows:

  • As the name of .proto file when IDL is generated.

  • As the name of outer java class that wraps model types

The model name can be derived from the model filename, or by defining it explicitly in XML. Name explicitly defined in XML takes precedence over the filename.

For the example above, name property will have a value of ModelNameGoesHere (it will be converted to Pascal Notation). If we do not define name attribute, the model name would be derived from filename: sampleModel.xml -> SampleModel.

Naming the model

The conversion of a user-defined name to an internally used ADM name can only handle white space as a word separator. Since name will be used to declare a Java class, the developer must take care when specifying a model name to only use white space and characters that are allowed in a class name. \

If we named the model sample-model, the resulting ADM name would be Sample-model, which cannot be used as a Java class name because it contains a dash character. Generating code with Protobuf encoding would then cause Java compilation errors. This applies both to name defined through XML attribute and filename-derived ones.

Imports

The import statement allows you to import messages entities and fields from a model in a different namespace.

Mixing encodings via import

Types from a model imported must be generated with the same encoding type as the model importing them. It is not possible to mix and match different encoding types within a message or entity. So if MessageA is generated with Xbuf and embedded EntityB is generated with Protobuf, Message cannot use EntityB as a field.

When generating code and copying model to output, encoding information is written to target model XML as a directive. If the model for which code is generated and any of its imports have an encoding mismatch, the code generator will raise a model validation error. For imported models that do not have encoding info (resolved directly to OS path or packaged to jar with earlier versions of ADM), this validation is not enforced.

See also Imported Model Resolution (TODO)

Factories

The factories section defines object factories that are used to instantiate the generated object. Each factory in an application must have a unique factory id. The ID is serialized along with the object or transported in MessageMetadata and is used to reconstitute its objects during deserialization. A single model can define multiple factories, allowing Messages and Entities to be grouped together as the application sees fit. A factory can contain a maximum of 32767 types, so in practice, it is rarely a requirement to use multiple factories within a single model. Each type in the model defines the factory to which it belongs via its factoryid attribute. The user application may define factories with ids greater than or equal to 1, ids <= 0 are reserved for platform internal use.

Attribute
Description
Required

name

The factory name to be used for code generation.

No

id

The factory's id which is used to register the factory with the runtime and identify the factory to use when decoding the factory's serialized objects.

The factory id must be between 1 and 65536 inclusive. Values of 0 or less are reserved for use by the platform.

Yes

doc

A brief one-line description for the factory. If more detailed documentation is needed, a child <documentation> element can be used.

No

deprecated

When a factory is marked as deprecated it will be marked as deprecated by the code generator.

No

Enumerations

Enumeration types can be modeled as follows and can be declared as fields of entity or message types. Unlike other model elements, enumerations aren't tied to a particular factory despite being scoped to the model's namespace. Generated java enumerations don't have dependencies on the rest of the platform and can be used standalone.

ADM

Generated Enumerations can specify a type which is accessible in the generated code. The type can be int, char or String. A const should not be removed from an enumeration, if the newly generated code is expected to deserialize enums that were persisted with an earlier version, in addition, the order of constants is important and should not be changed.

Generated Source

Fields

The ADM model allows fields either to be defined in place (directly on the message or entity that is using the field) or by reference to a field declared in the model's section. It is a matter of preference which approach an application developer uses: if many messages contain the same field, then it may be more convenient to model the fields in a reusable fashion in the element, but in other cases, it may be more convenient to define the fields in place.

Field Element Attributes

Attribute
Description
Required

name

The name of the field

yes

type

The field type. For message and embedded entities, the supported field types are the types in the ADM Type System. For state entities, the field type could also be a name of another state entity or collection.

yes

id

The field id

Note: Field ids must be between 0 and 32767 inclusive

no

required

Whether or not the field is a required field for the type. Fields declared as required will cause a check to be added for the value being set in the generated types isValid() method.

no

isKey

True if this field should serve as the key when inserting the entity into a Map collection. In this case, insertion of the message in the collection with a given key will update this field with the key value. Note: Only applies to state entity elements

no

doc

The doc to use for the field

no

deprecated

When true all methods generated for the field will be marked as deprecated.

no

Field Reference Element Attributes

Attribute
Description
Required

ref

The name of the referenced field. Name may be with or without the namespace of owner model (i.e. full-qualified name). In both cases, the field will be looked up in both the current model and its imports. If the non-fully-qualified name is declared in the current model and in one of the imports, the field from the current model will take precedence. If multiple imports define the same name, an error will be reported.

The best practice when importing a field from another model is to use the fully qualified name of the imported field (e.g. com.example.importedmodel.someField), as this insulates your model from future conflicts in the event that imported models are changed.

Yes

name

Optionally, a name for the field that overrides the referenced field's name. Otherwise, the field name defaults to that of the referenced field.

No

jsonName

Optionally overrides the referenced field's jsonName.

No

id

Optionally overrides the id specified by the field being referenced.

Field ids must be between 0 and 32767 inclusive

No

required

Whether or not the field is a required field for the type. Fields declared as required will cause a check to be added for the value being set in the generated types isValid() method.

No

isKey

True if this field should serve as the key when inserting the entity into a LongMap or StringMap collection. In this case, insertion of the message in the collection with a given key will update this field with the key value. Note: Only applies to state entity elements

No

doc

The doc to use for the field which overrides that specified by the referenced field.

No

deprecated

When true all methods generated for the field will be marked as deprecated.

No

Semantic Types

The ADM model provides a section that can be used to define types based on the platform's primitive and built-in types. Such semantic types can be used in place of their corresponding primitive type in the model and will inherit their documentation. The type used for the field in generated messages and entities will be the base type specified by the named field.

ADM Model

Generated Code

Note that "Price" doesn't result in a new java type being created. The generated source uses its base type (float) directly and inherits the documentation of the semantic type. This is true of all semantic types, with the exception of types with a base of String that are declared as poolable (See poolable string types below).

Entities

Entities are defined in the entities element of the model and must have a unique id with respect to other types within the scope of their factory.

ADM Model

Entity Element Attributes

Attribute
Description
Required

name

The name of the field, must be unique within the model.

Yes

id

The id of the entity, which must be unique within the scope of all types in the entity's factory.

Entity / Message ids must be between 0 and 32767 inclusive

Yes

factoryId

The id of the factory, which must be unique within the scope of all factories used within an application. When a message is received, the factoryId and entityId uniquely identify the type to be deserialized. factory IDs <= 0 are reserved for platform use.

Yes

asEmbedded

Defaults to false, Indicates whether or not this entity is generated to be used as an embedded or child field of another entity. Embedded entities are always serialized transported with its parent entity. Entities used as fields in messages must be declared as embedded.

No

transactional

Whether or not this entity supports transaction commit and rollback via the applications ODS store.

No

Entity Field Element Attributes

type

The type of the element.

If the type is defined in this namespace, is defined in only one of the imported models, or is a primitive or collection type, only the simple name of the type need be used. A non-fully-qualified name will be looked up in both the current model and its imports. If name is declared in the current model and in one of the imports, the type from the current model will take precedence. If multiple imports define the same name, an error will be reported. The best correction in such case is to use the fully-qualified name.

If the field is an array type, it should be suffixed with array indices such as MyEntity[] to denote it as an array.

Yes

name

The name of the field, must be unique within the model.

Yes

jsonName

Contains the name of the JSON property that will be used for the field when the message is serialized to JSON. Defaults to using the value defined in name.

No

id

The id of the field. The id must be unique with the scope of this entity. For Xbuf/Protobuf encoding, this tag is used as the tag value for the field on the wire. If not set, a unique id will be generated by the source code generator. For better control over compatibility, it is recommended that application set this value manually.

Field ids must be between 0 and 32767 inclusive

No

isKey

True if this field should serve as the key when inserting the entity into a LongMap or StringMap collection. In this case, insertion of the message in the collection with a given key will update this field with the key value.

No

Generated Source

For an entity named "MyEntity" an interface and an implementation will be generated using the model's namespace. Entities will extend IRogNode or IRogContainerNode marking that they can be used as nodes with ODS.

Messages

Messages are defined in the messages element and must have a unique id with respect to other types within the scope of their factory. Messages can use all modeling capabilities of entities, but cannot use non-embedded entities or non-array collections as fields.

ADM Model

Message Attributes

Messages support the same attributes as entities (listed above) with the exception that transactional defaults to false for messages.

Message Field Attributes

Message fields support the same attributes as entities (listed above).

Notes

For Xbuf and Protobuf encoding, the id is used to generate the protobuf field tag, so changing field ids will break wire compatibility. If fields are not explicitly assigned IDs in the model, then the ADM generate will assign them automatically. in this case, fields should not be removed or changed in order to maintain wire compatibility with earlier versions of the generated code.

Messages can only declare primitive types, built-in types, embedded types as fields (or arrays of those types). Collections, Messages, and non-embedded Entities can't be used.

Generated Source

For an entity named "MyMessage" an interface and an implementation will be generated using the model's namespace. Entities will extend IRogNode or IRogMessage, marking that they can be used as nodes with the platform's ODS and SMA modules.

Collections

Collections are defined in the element and must also have a unique id with respect to other types within the scope of their factory. Collections may not be declared as embedded at this time.

ADM Model

Generated Source

Last updated