The Talon Manual

Skip to end of metadata
Go to start of metadata

In This Section

Overview

Code generation is accomplished using the ADMCodeGenerator class distributed with the ADM module (nvx-adm-<vesion>.jar or the nvx-talon-all-<version>.jar). The XML schema is bundled in these jars at the jar root: /x-adml.xsd. 

Encoding Types

ADM code generation currently supports generating classes in the following encoding types :

  • Json: Javascript Object Notation serialization; not very efficient but highly readable
  • Protobuf: Google's protobuf serialization format, which can be useful for portability purposes providing a reasonable balance between performance and interoperability.
  • Xbuf: Neeve's protobuf implementation which can operate in a wire compatible mode with Google's protobuf, but allows zero garbage operation along with other performance enhancements.  

See Choosing an Encoding for more information on choosing an appropriate encoding. 

Protobuf IDL

For Xbuf and Protobof the protobuf idl (.proto) is output in the generated source folder using the model's fully qualified namespace.

Generated Encoding Output

Invoking the code generator on a model outputs source for objects in a particular encoding: Json, Xbuf or Protobuf to a package that is by default defined as the model's namespace. The code generator, however, can be used to generate source to a namespace specified to the code generator. This makes it possible to generate source for multiple encodings of the same model by invoking the code generator multiple times with a separate namespace and encoding for each execution. Furthermore, it is possible to convert between any of the separate encodings by serializing/deserializing to json which is compatible between all encodings (and in the case of Xbuf/Protobuf to a binary format since the are binary compatible). 

It is perfectly legal to mix separate encoding types at runtime across different models so long as the models have separate factory ids (since the factory id is used to determine which generated factory to use to decode a message). 

While it is legal to mix and match different encoding types within your application, it is isn't possible to mix and match encodings within a model via import. For example, if you generate one model with protobuf, it is not possible to use types already generated with protobuf in a model being generated with Xbuf.

Code Generator Options

The following options are available for the ADM code generation: 

Command Line/AntMaven PluginDescriptionDefault
-f,
--file

modelFile

The input file specified either as OS path or URL-
-m,
--modelsdir
modelsDirectoryBase directory to use when searching for imported models that are not found on the project / generator's classpath.-
-o,
--outdir
projectOutputDirectory

Base output directory for the generated files.

For maven plugin defaults to target/generated-[test]-sources/nvx-adm

-
-c,
--classesdir
classesOutputDirectoryClasses output folder (to which generated resoures should be copied). May be specified multiple times to copy to multiple directories.-
-e,
--encoding
encodingTypeEncoding type of content underlying the generated classes (Xbuf | Protobuf | Json)Protobuf
-x,
--xpcompat
protoXbufGenerationCompatibilityWire compatibility between protobuf and xbuf generated classes (None | Xbuf | ProtobufProtobuf
-y,
--emptyifnullarray
generateArrayGetterEmptyIfNullInstructs the code generator return empty arrays instead of null for unset array fieldsfalse
-n,
--namespace
namespaceNamespace override of model parsed from the input file (overrides namespace in model file if supplied)-
-p,
--protodir
N/A

An additonal directory in which to search for imported .proto files.

-
-d,
--directive
directives

A key=value pair specifying a code generation directive. (May be specified multiple times).

See Directives below.

-
-b,
--buildinfo
buildInfoString with build-time information such as project version, timestamp or machine. This is added to the AdmGenerated annotation of generated classes.-
-i,
--incremental
incrementalBuildTrigger incremental code generation - run only if something changed since last run

false

(true for maven plugin)

N/AuseBasicDeltaDetectionWhen running an incremental build, basic delta detection indicates thatmodel'sare rebuilt based on whether source model timestamp. With advanceddeltadetection dependencies are examined as well.false
-u,
--bundledir
modelBundleOutputDirectoryDirectory to which to output model XML and IDL files if applicable-
N/AgenerateModelBundleIndicates whether models with all their dependencies and IDLs should be output to modelBundleOutputDirectoryfalse
N/AcodegenListenerClassNameClass name of external listener to receive events from code generator. See ADM Code Generation Events.-
N/AcodegenListenerPropertiesAdditional properties to pass to the constructed code gen listener.-

Directives

Some advanced properties can be passed to the code generator as directives. The following is a list of supported directives:

DirectiveDescriptionDefault
requireExplicitCollectionKeys

Directive indicating that map collections' contained entities must define an explicit field field to store the key for the entity when it is in the map. When this directive is false, it is possible that as the model evolves the implicitly generated key field could change and cause existing keys to be ignored on upgrade.

(lightbulb) It is recommend that new projects set this directive to true.

SINCE 3.11

false
generateEmbeddedEntityInterfaces

Directive indicating that the generator should create interfaces for embedded entities. This can be disabled for applications with stringent performance requirements to reduce the overhead associated with multi-morphic vtable lookups.

true
generateEmbeddedEntitiesNonFinal

When this directive is set to true the generated entity class is not declared as final nor are its accessors. This feature can be useful for applications that need to mock embedded entities in test frameworks such as CGLIB, but is not recommended for production use for performance reasons. 

SINCE 3.8.189

false
generateDefaultGettersWhether or not to generate default getters that accept a value to return when the field is not set. Not typically recommendedfalse
generateThrowOnUnsetGettersWhether or not to generate getXXXOrThrow() or accessors that will throw an ERogFieldNotSetException when the field has not been set. This provides an alternative to calling hasXXX for a field to test if the field is unset. Usage of this directive is not recommended; hasXXX is the recommended approach to testing if a field is not set. Exception throwing is more expensive, and the generated getXXXOrThrow method introduces extra invocation overhead and a larger code size.false
generateRequiredFieldValidatorsWhether or not validation logic is generated in the types validators for required fields. Enabling this leads large generated code size, and validation checks are expensive, so this is not recommended for performance sensitive applications.false
generateFluentSettersDirective indicating that fluent style setters should be generated for fields. This can be enabled to generate fluent accessors on generated types. This can be useful for writing concise test code, but is more overhead, so it's usage is not typically recommended.false

generateAllStringsPoolable

Directive indicating that all Strings fields in the model should be generated as poolable types regardless of the value of the field's poolable attribute.

false
pooledStringFieldTypeNameSuffixPolicyCan specify None, Always or OnConflict to instruct the code generator as to how to handle naming conflicts that arise from a pooled string field type name generated from a field name are suffixed to avoid a name clash."None"
pooledStringFieldTypeNameSuffix Specifies the suffice to use to resolve pooled string type name conflicts with Always or OnConflict suffixing policies."String"
generateProtobufClasses

Specified that protobuf classes should be generated using the protoc code generator in addition to the encoding type specific generated classes. This directive only applies to Xbuf and Xbuf2 encoding types.

SINCE 3.12.5

"String"


Running with Java

To run the generator with java you can use:

or you can use the platform jar which contains ADM:

Using Maven

To use the code generator with Maven add the following to your pom's plugin section:

Maven Plugin GoalsDescription
generate, adm-generateGenerates code to a generated sources folder which would be included in the built jar.
generateTest, adm-generateTestGenerates code to a generated test sources folder which would be included in the built test jar

Using the Platform Plugin

If your project is using the nvx-platform-bom and you want to generate code with the same version of the platform you are using, you may also use the nvx-platform-maven-plugin. The advantage of this approach is that you can use the same version of the plugin as the platform bom. Because maven BOMs don't cover plugin versions, using the nvx-core-maven-plugin would mean that the nvx-core-maven-plugin-version would have to be specified separately.

Using ANT

Imported Model Resolution 

To handle multi-module and multi-project builds, the ADM XML Parser, and Maven Build plugin search for model imports on the classpath using the imported model's fully qualified namespace. The model xml (and .proto for Xbuf/Protobuf) will be copied to the generated source folder in fully qualified form. To allow other models to resolve the model being generated from their classpath, users should ensure that these files are copied to the target classes folder.


SINCE 3.4
ADM Code Generator Maven plugin will copy these files by default to target classes folder and include them into project artifact's jar.

 

Import resolution searches both current classpath and OS file system when resolving an import. Recommended is to use relative classpath strings whenever possible. Consider the following example project with two models, model.xml imports other_model.xml:

 

${basedir}/src/some/package/model.xml [In xml we define namespace = "some.model.namespace"]
${basedir}/src/other/package/other_model.xml [In xml we define namespace = "some.other_model.namespace"]

 

The recommended way to define import would be one of the following:

Import through classpath

The reason why this works is that the result of running code generation would be:

${basedir}/target/classes/some/model/namespace/model.xml
${basedir}/target/classes/some/model/namespace/Model.proto
${basedir}/target/classes/some/model/namespace/GeneratedModelClass1.class
${basedir}/target/classes/some/model/namespace/GeneratedModelClass2.class
...
${basedir}/target/classes/some/other_model/namespace/other_model.xml
${basedir}/target/classes/some/other_model/namespace/OtherModel.proto
${basedir}/target/classes/some/other_model/namespace/GeneratedOtherModelClass1.class
${basedir}/target/classes/some/other_model/namespace/GeneratedOtherModelClass2.class
... 

The requirement is that code generation first runs for other_model.xml so that it can be found in classes folder at the time of running model.xml. 


The following modes of import model resolution are provided for advanced use cases but are discouraged. 

From from project src folder through OS filesystem

Platform Bundled IDLs

The platform bundles the following IDLs in the packaged jars to support custom options used by ADM to enrich handling of enums, and to define additional data types used by ADM. 

IDLFull PathDescription
descriptor.protogoogle/protobuf/descriptor.protoDefines options available in Protobuf
AdmTypes.protocom/neeve/adm/types/protobuf/AdmTypes.protoDefines custom enum options and additional ADM data types

Incremental Code Regeneration

SINCE 3.4

The Maven Plugin and ADM Code generator take a source model's last modified timestamp or checksum into account. Code generation will be skipped if:

  • The model file has been changed since the last build.
  • Any import model file has changed (checked recursively in imports of imports...)
  • Any input option for code generation has changed such as encoding type, namespace, directives etc.

The incremental code generation works by tracking above given changes in an XML file which may be found in output dir. The file has a name with a pattern like this:

.${model_filename}.xml_${md5checksum}.metadata. model_name is the name of the model file for which code was generated. md5checksum is a signature calculated from input options given to code generator so that if any of them changes, the resulting filename no longer represents same code generation. Stored in this file are input options given to code generator and list of models with a number that would be different every time model file is persisted to disk. These files do not go into the jar and may be deleted at any time (which they usually do when a clean build is triggered).

Regeneration of Imported Models

On the roadmap

The ADM Code generator will be enhanced to allow the code generator to operate in a mode in which it will regenerate all pre-built imported models. This intent of this mode is that it will ensure that all models used by an application are built with the same version of the platform that the importing application is built with. This can be used to work around issues where older dependencies haven't been updated to a newer version of the X platform which is no longer API compatible. 

 

  • No labels