The Talon Manual

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • ADM generated source depends on platform APIs that may not exist in earlier versions. 
  • ADM generated source depends on imported class that are potentially generated with an earlier version of ADM. 
  • ADM objects are serialized between different versions of the platform, so there are wire format considerations. 
  • The application's ADM model is changing evolves over time (new types and fields may be added or removed). 

The below This sections discuss discusses how the compatibility implications of is enforced. 

Compatibility Goals

Wire Compatibility

...

  • A best effort is made to maintain backwards API compatibility with code generated within the same major version so that a new version of the platform runtime can operate with code generated within that version. 
  • However:
    • To allow introducing new functionality in the generated code sometimes dependencies on new platform APIs are introduced. In this case a minor API compatibility version is incremented. This means that newly generated code can not be used with older versions of the platform. 
    • In extreme cases such as critical bug fixes it is possible that API changes are required in the generated code API which necessitates a major increment which makes a newer version of the platform require newly generated code (older generated code cannot be used). 

Versioning Recommendations

This section provides recommendations on how to version your projects to ensure that they can use the latest and greatest ADM generated source code for their models.  

Small Projects

For small projects that are not versioned independently and are all expected to operated against the same Talon version then regenerating ADM models with each release is the best way to ensure that your generated models are API compatible with the runtime. 

Large Projects

For larger organizations that have applications that are versioned independently and upgrade X Platform version in a staggered fashion, it can be a challenge if those applications share the same models while on different X versions. There are 2 approaches to handling this situation:

Strategy 1 - Each Project Builds Private Models

If you have relatively few models, simply having each project (micro-app) generate and build its own private copy of the generated ADM source code is a simple approach to ensure that each project can use ADM code generated with their target platform version. It can break down if your organization has a lot of shared models and Stategy 2 below may be more appropriate. 

Strategy 2 - Centrally build platform qualified Models

In this approach ADM models that are shared by multiple projects are built and managed as independently versioned artifacts. The generated ADM source code is generated against each platform version to be used by the organization as a whole and the resulting artifact is qualified with the X Platform version so that the resulting artifact reflects both the model version and the platform version from which it was generated. 

Take for example an ADM Model called common-messages share by Project A and Project B that are both initially using X Platform 3.1.104, but will be independently upgrading to X 3.2.121.

common-messages v1.0

 

<model namespace="com.example" defaultFactoryId="1">
  <messages> 
    <message name="MyMessage" factoryid="1" id="1">
        <field name="myIntField" type="Integer" doc="A sample integer field"/>
    </messsage>
  </messages>
</model>

 

And then the model is changed to add a new long field:

common-messages v1.1

 

<model namespace="com.example" defaultFactoryId="1">
  <messages> 
    <message name="MyMessage" factoryid="1" id="1">
        <field name="myIntField" type="Integer"/>
        <field name="myLongField" type="Long"/>
    </messsage>
  </messages>
</model>

 

Under this scheme the common-messages would be built and packages as:

  • common-messages-1.0-adm3.1.104.jar
  • common-messages-1.1-adm3.1.104.jar
  • common-messages-1.0-adm3.2.121.jar
  • common-messages-1.1-adm3.2.121.jar

The above packaging allows each project to independently upgrade to either the model version or a compatible X version as appropriate. If Project B upgrades to platform version 3.2.121 it could do the following:

  • continue to use common-messages-1.0-adm3.1.104.jar: 
    • It won't get the new long field in v1.1 model. When it receives a 'MyMessage' serialized by the v1.1, version myLongField will be invisible. 
    • It won't get the enhancement for detecting stale enums in the 3.2.121 generated code. 
  • switch to common-messages-1.1-adm3.1.104.jar: 
    • If will pick up the new long field in v1.1. It can exchange 'MyMessage' with Project A, but Project A won't see the value of myLongField until it upgrades to a 1.1 version of the model. 
    • It will not get the platform enhancements in the generated code. 
  • switch to common-messages-1.0-adm3.2.121.jar: If Project B isn't ready for v1.1 of the model, but want the platform enhancements in generated code. 
    • It won't get the new long field in v1.1 model. When it receives a 'MyMessage' serialized by the v1.1 version, myLongField will be invisible. 
    • It will get platform enhancements in the generated code. 
  • switch to common-messages-1.1-adm3.2.121.jar: 
    • If will pick up the new long field in v1.1. It can exchange 'MyMessage' with Project A, but Project A won't see the value of myLongField until it upgrades to a 1.1 version of the model. 
    • It will get platform enhancements in the generated code. 

The ADM Compatibility Level

The ADM compatLevel is of the form [MAJOR].[MINOR].[PATCH]. This compatLevel is added to the AdmGenerated  annotation's place on ADM generated classes. This annotation is used determine if the generated code is compatible with the platform version being run. Note that the ADM  COMPATIBILITY_LEVEL is versioned and tracked independently of the platform version. 

Info

See also: the ADM Compatibility Matrix for a listing of the compatibility level changes.

AdmGenerated Annotation

To validate compatibility of the generated code with the version of the platform jars on which the generated classes are being used, an com.neeve.adm.runtime.annotations.ADMGenerated annotation is added to ADM generated types. The ADMGenerated annotation has runtime retention and is thus available for introspection by applications at runtime.

...

  1. When a message factory is registered with the platform it's compatLevel will be examined to ensure that it is runtime compatible with the platform. The platform will increase it's runtimeCompatibilityVersion each time a change is made that would break compatibility with previously generated code. See Compatibilty Level Rules below.
  2. Trace can be enabled to display the version of the platform that generated the factory when it is registered with the runtime to assist with support issues (nv.sma.trace=verbose or nv.ods.trace=verbose). 
    Sample output from this trace is:

    Code Block
    com.neeve.toa.sample.oms.dict.OmsDictionaryFactory(id=-23) ADM generated (encoding=Protobuf, compatLevel=2.0.0, buildDate=5/4/15 1:49 AM, admVersion=nvx-core-all v1.9-SNAPSHOT (build 0), buildInfo=nvx-toa-sample-dict-1.0-SNAPSHOT (nvx-core-maven-plugin))
  3. It is also possible for the application to call MessageViewFactoryRegistry.dumpFactoryVersionInfo(StringBuilder) or StoreObjectFactoryRegistry.dumpFactoryVersionInfo(StringBuilder) at any time to collect the above trace at any time

Runtime

...

Compatibilty Check

The ADM compatLevel is of the form [MAJOR].[MINOR].[PATCH]. This compatLevel is added to the AdmGenerated  annotation's compatLevel property, and is used determine if the generated code is compatible with the platform version being run. Note that the ADM  COMPATIBILITY_LEVEL is versioned and tracked independently of the platform version. See the ADM Compatibility Matrix for a listing of the compatibility level changes.compatibility rules are enforced as follows:

At runtime when Factories are registered with the platform their compatibility will be checked, and an EAdmCompatibilityException will be thrown if the classes are found to be incompatible.

Tip

Though not recommended, it is possible to disable compatibility checks by setting -Dnv.adm.disablecompatcheck=true

The compatibility rules are enforced as follows:

Bump in patch version

For the same major and minor versions, two differing patch versions must be API compatible at runtime even if the patch version differs. This relation holds true for platform code compiled as 2.0.0 and code generated by a later version of the platform at 2.0.1. The older platform code must be able to operate with the newer platform code.

...

Code Block
titleSample Compatibility Error - Older Generated Source
Caused by: com.neeve.adm.runtime.EAdmCompatibilityException: com.neeve.aep.messages.AepMessageFactory 
generated with ADM 'nvx-adm v1.9.275 (build 275)' and a compatibility level of '2.0.0' is not compatible with 
platform version 'nvx-core-all v2.0.100 (build 100)' with a compatibility level of '3.0.0'
	at com.neeve.adm.runtime.AdmCompatibility.assertRuntimeCompatibility(AdmCompatibility.java:125)
	at com.neeve.sma.MessageViewFactoryRegistry.registerMessageViewFactory(MessageViewFactoryRegistry.java:218)
	at com.neeve.aep.AepEngine.<clinit>(AepEngine.java:3138)
	... 10 more

Versioning Recommendations

This section provides recommendations on how to organize your projects' code generation to ensure that they can use the latest and greatest ADM generated source code while remaining interoperable. 

Small Projects

For small projects that are not versioned independently and are all expected to operated against the same Talon version, then regenerating ADM models with each release is the best way to ensure that your generated models are API compatible with the runtime. 

Large Projects

For larger organizations that have applications that are versioned independently and upgrade X Platform version in a staggered fashion, it can be a challenge if those applications share the same models while on different X versions. There are 2 approaches to handling this situation:

Strategy 1 - Each Project Builds Private Models

If you have relatively few models, simply having each project (micro-app) generate and build its own private copy of the generated ADM source code is a simple approach to ensure that each project can use ADM code generated with their target platform version. It can break down if your organization has a lot of shared models and Stategy 2 below may be more appropriate. 

Strategy 2 - Centrally build platform qualified Models

In this approach ADM models that are shared by multiple projects are built and managed as independently versioned artifacts. The generated ADM source code is generated against each platform version to be used by the organization as a whole and the resulting artifact is qualified with the X Platform version so that the resulting artifact reflects both the model version and the platform version from which it was generated. 

Take for example an ADM Model called common-messages share by Project A and Project B that are both initially using X Platform 3.1.104, but will be independently upgrading to X 3.2.121.

common-messages v1.0

 

<model namespace="com.example" defaultFactoryId="1">
  <messages> 
    <message name="MyMessage" factoryid="1" id="1">
        <field name="myIntField" type="Integer" doc="A sample integer field"/>
    </messsage>
  </messages>
</model>

 

And then the model is changed to add a new long field:

common-messages v1.1

 

<model namespace="com.example" defaultFactoryId="1">
  <messages> 
    <message name="MyMessage" factoryid="1" id="1">
        <field name="myIntField" type="Integer"/>
        <field name="myLongField" type="Long"/>
    </messsage>
  </messages>
</model>

 

Under this scheme the common-messages would be built and packages as:

  • common-messages-1.0-adm3.1.104.jar
  • common-messages-1.1-adm3.1.104.jar
  • common-messages-1.0-adm3.2.121.jar
  • common-messages-1.1-adm3.2.121.jar

The above packaging allows each project to independently upgrade to either the model version or a compatible X version as appropriate. If Project B upgrades to platform version 3.2.121 it could do the following:

  • continue to use common-messages-1.0-adm3.1.104.jar: 
    • It won't get the new long field in v1.1 model. When it receives a 'MyMessage' serialized by the v1.1, version myLongField will be invisible. 
    • It won't get the enhancement for detecting stale enums in the 3.2.121 generated code. 
  • switch to common-messages-1.1-adm3.1.104.jar: 
    • If will pick up the new long field in v1.1. It can exchange 'MyMessage' with Project A, but Project A won't see the value of myLongField until it upgrades to a 1.1 version of the model. 
    • It will not get the platform enhancements in the generated code. 
  • switch to common-messages-1.0-adm3.2.121.jar: If Project B isn't ready for v1.1 of the model, but want the platform enhancements in generated code. 
    • It won't get the new long field in v1.1 model. When it receives a 'MyMessage' serialized by the v1.1 version, myLongField will be invisible. 
    • It will get platform enhancements in the generated code. 
  • switch to common-messages-1.1-adm3.2.121.jar: 
    • If will pick up the new long field in v1.1. It can exchange 'MyMessage' with Project A, but Project A won't see the value of myLongField until it upgrades to a 1.1 version of the model. 
    • It will get platform enhancements in the generated code.