Skip to content

Releases: aml-org/amf

Changes in AMF 5.0.1

23 Nov 20:42
9971ffd
Compare
Choose a tag to compare

Released Nov 23, 2021.

JS asset

JVM asset

Interface changes:

A new render option has been added to RenderOptions class with the method withSourceInformation that lets you acquire the URI location from where it was originally parsed of any element in the base unit. This only affects the rendering in JSON-LD, and has been added in the issue APIMF-3319.

GitHub fixed issues

  • #1084: Unable to track JSON schema (the raw value) from a payload

AMF Fixed issues

Changes in AMF 5.0.0

18 Oct 20:49
5fb016b
Compare
Choose a tag to compare

Released Oct 14, 2021.

JS asset

JVM asset

Summary

This new mayor version includes changes focused in the client interfaces and internal structure of AMF with the intention of providing a simplified and clean usage. These changes DO NOT modify underlying functionality with regards to the previous version 4.7.8.

Complementary to these release notes, make sure to see our updated documentation with its migration guide, as well as our examples repository.

Interface Changes

Unify all configuration in a single instance removing static behaviour

Why? In AMF 4 functionality was partially pluggable through a static registry. That is why clients had to invoke asynchronous AMF.init() or similar initialization methods in order for AMFs functionality to work correctly. This initialization was not transparent to the end user, and lead to issues which were difficult to reproduce and debug.

This behaviour has been completely removed in favor of immutable configuration instances. These instances are the single point through which a user defines the functionality is wishes to use (support for a certain API Spec as an example), and other parameters such as parsing/render options, or resource loaders. Users can now create multiple AMF configurations and have a clear sense of the capabilities each one has.
More details here.

Functionality is exposed through clients

Why? In AMF 4 functionality was exposed through a variety of classes, and configurable parameters had to be passed on each invocation.

All of our functionality has now been unified into 2 client interfaces. These client classes are obtained directly from a configuration instance, meaning that all of their configurable parameters are used for the operations invoked by the client. This has also allowed us to move functionality that was exposed through methods defined in model classes making their interface more simple.
More details here.

Explicit result feedback for each operation

Why? In AMF 4 operations such as parsing and resolution did not return any validation results, only returning the resulting BaseUnit. If validation results where to occur, these where collected statically and returned when the validation operation was called. This lead to a static collection that stored all validations and could cause potential memory problems in long executions. This also did not give transparency to users that where only interested in parsing or resolution.

Each operation now returns a specific instance of AMFResult, which not only contains the result BaseUnit, but also a list of all the validation result that where collected.

New Functionality

New specification agnostic parsing functionality through composite configurations

Composite configurations such as APIConfiguration.API() which contain capabilities for more that one specification can only be used for parsing. We have maintained this functionality as it offers AMF users the possibility of parsing any content without knowing the specification type beforehand. Any other operation that is invoked when using composite configuration will result in errors, such as rendering, transformation, or validation as they must apply for a particular specification.

New interfaces for scala adopters

In AMF 4 client interfaces where only available for javascript and java, without support for native scala types such as Future or Option. This has now been included giving classes for clients in java, scala, and javascript. More details as to how our package structure is handled can be found in Transparent packet structure heading.

New EventListeners which replace static ExecutionLog

A new AMFEventListener interface has been defined which can be plugged into any configuration. This listener provides additional insights over the execution of AMF through a set of events. Each event has a name, and a set of additional values according to each type.

New id adoption functionality available for BaseUnit

A new functionality was implemented allowing the possibility of adopting the ids of all the elements of a BaseUnit given a certain base uri. This is used internally by AMF after parsing a BaseUnit to make sure all ids are correctly defined. This functionality has been exposed to the end user if there is a need to modify ids from a parsed or created model in a deterministic manner.
An example of this use case can be found here.

Additional Changes

Restructured modules and artifacts

AMF 5 artifacts are now domain scoped. What used to be the amf-client module in AMF 4 is now broken into multiple
modules. The new AMF ecosystem modules are the following:
amf modules

  • amf-cli: CLI client classes
  • amf-api-contract: API domain classes
  • amf-shapes: Schema domain classes
  • amf-aml: AML domain classes
  • amf-validation: Validation domain classes
  • amf-core: Core domain classes
  • amf-rdf: External RDF interface classes

Transparent package structure

AMF 5 is organized in packages according to their visibility and target platform. These are:

  • amf.[module].internal: internal unsafe interface
  • amf.[module].client: client exposed interfaces
    • amf.[module].client.platform: platform (JVM & JS) interface classes
    • amf.[module].client.scala: native scala interface classes

Removed jena-shacl dependency and extracted RDF related functionality in separate artifact

AMF 5 now provides native SHACL validation without the need for jena-shacl. Jena is no longer a standard dependency in
AMF. The new amf-rdf artifact contains the Jena dependency as well as the necessary classes to interface the AMF
model with external RDF models like the Jena. amf-rdf must be explicitly imported. JAR size decreased around 40%

Discontinued support of custom validation functionality

AMF 5 no longer includes functionality for custom validation. We are working on a new separate project solely focused on this regard allowing us to incorporate more features and enhanced performance.

Changes in 4.7.8

28 Sep 17:47
9f05bc9
Compare
Choose a tag to compare

Released Sep 24, 2021.

JS asset

JVM asset

Validation fixes

Array inheritance in RAML

There was a problem resolving some cases of inheritance on array types that generated a validation error of type Incompatible types [array, array].

Example:

types:
  BaseObject:
    type: object
    properties:
      items:
        type: array
        items:
          type: any
  
  ArrayOfObjects:
    type: object[]

  CustomObjectList:
    type: BaseObject
    properties:
      items:
        type: array
        items:
          type: ArrayOfObjects

Examples with disjoint UnionShapes

There was an error in the propagation of examples in disjoint UnionShapes that ended in validation errors of the type expected type: X, found: Y

Example:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "properties": {
    "gender": {
      "type": [
        "string",
        "null"
      ],
      "examples": [
        "M",
        "F",
        "N",
        null
      ]
    }
  }
}

GitHub fixed issues

AMF Fixed issues

Changes in 5.0.0-beta.4

01 Sep 18:32
28dd609
Compare
Choose a tag to compare
Pre-release

Additions

Expose new ClasspathResourceLoader to load artifacts from class path

Why?: adopter request
Note: this Resource Loader is not added by default in the Configuration objects because it is Java/Scala specific. Fully qualified name is: amf.core.client.platform.resource.ClasspathResourceLoader

Added toString method in AMFResult

Why?: adopter request. Returns a string representation of the AMFResult instance similar to that of the AMFValidationReport

Added platform Annotations accessors to the Scala interface

Why?: scala adopters coming from the java interface didn't have the same accessor methods they used before. This meant that new scala interface adopters had to re-implement these methods by themselves.

Added configuration generation based on a Spec

Why?: once the API was parsed using any of the composite configurations (APIConfiguration, WebApi, Oas, Raml) it wasn't clear how the user could create a configuration compatible with the guessed API spec to validate, transform or render. Now, the user can do:

var client = APIConfiguration.API().baseUnitClient()
var result = client.parse("some-uri")
var specConfig = APIConfiguration.forSpec(result.sourceSpec)
var validationReport = specConfig.baseUnitClient().validate(result.baseUnit)

Added ShapesConfiguration/ShapeElementClient class

Why?: we moved shape specific methods to the ShapeElementClient class for amf-shapes only adopters. Adopters that used the shape render methods: toJsonSchema/toRamlDataType with the AMFElementClient will continue to be able to use them from that class.

Changes

Extracted RDF components to another artifact (amf-rdf) detached from the "main" artifact tree ("amf-api-contract" and "amf-aml")

Why?: this is the next step of removing SHACL as our validation engine. RDF functionality is used by a small amount of adopters and contributes a lot to the final production JAR / JS bundle size.

Important: for adopters that use Rdf functionality you will have to import the amf-rdf artifact in the same namespace as the rest of the amf artifacts.

Size impact on dependency tree:

  • JS bundle (node_modules folder) / 5.0.0-beta.3 -> 27,9 MB; 5.0.0-beta.4 -> 14,5 MB / 48% size decrease
  • JVM artifact (CLI uber jar) / 5.0.0-beta.3 -> 40,5 MB; 5.0.0-beta.4 -> 24,7 MB / 31% size decrease

Dialect ids parsed with parseContent is composed by: the default dialect uri and dialect name and version

Why?: several dialects parsed by content had the same id. If a user registered two different dialects parsed with the parseContent method then they override each others configuration. Adding the name and version to the id resolves that issue.

Linkable link methods were changed for Java / Javascript compatibility

Why?: the link(label: Option[String] = None) was split into: link() and link(label: String)

Removed payloadValidatorFactory method. Payload Validator creation is now via the AMFElementClient -> payloadValidatorFor method

Why?: reduce the public interface area that a user has to deal with by associating the AMFElementClient with payload validation.

Unified AML scala and platform interfaces

Why?: AML platform and scala interfaces were too different making it difficult for users that used both scala/platform packages to use AML classes in similar ways. Besides, it improves interface maintainability.

Removed Example.toJson/toYaml/toXml methods and replaced them for the renderExample method.

Why?: decouple example rendering from the Example model itself. This will enable the emission of the example in several formats if they are plugged into the configuration.

val client = ShapesConfiguration.predefined().elementClient()
val example = // get an Example
client.renderExample(example, "application/json") // predefined supported mediatypes are "application/yaml" | "application/json" | "application/xml"*

* If the example is obtained from an XML document as String

Updated typings

Note: added the link methods to typings and changed the non-existant lexical accessor for position. Added typings for the additions to the public interface.

Changes in AMF 4.7.7

27 Aug 20:53
bf92095
Compare
Choose a tag to compare

Released Aug 27, 2021.

JS asset

JVM asset

RAML 1.0 changes

Parsing nil types

As the RAML Spec declares, nil types are equivalent to union types. However, this was not the case previously in AMF. In AMF 4.7.7 this has been changed and both notations are equivalent.

This change fixed some bugs, for example: Given the following similar RAML types:

types:
  def1?:
    type: integer
    default: 20
  def2:
    type: integer | nil
    default: 20
  def3:
    type: integer?
    default: 20

AMF didn't keep the default value in def3, thus causing an error when validating against that type. Now AMF correctly parses nillable notation and saves default and other facets in that object.

Properties declared in required field

AMF now saves properties declared in required but not present in properties. For example, consider the following JSON Schema:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type" : "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
    },
    "additionalProperties": false,
    "required": [
        "address"
    ]
}

Previously, AMF ignored property address as it was not declared in properties. Now it saves it and requires it in validation.

This change solved problems when using JSON Schemas with anyOf or oneOf and multiple schemas with only required fields.

For example, given the following JSON Schema:

{
    "type": "object",
    "oneOf": [
        {
            "required": [
                "p_1"
            ]
        },
        {
            "required": [
                "p_2"
            ]
        }
    ]
}

Previously AMF ignored properties p_1 and p_2, it parsed two empty schemas where any value would match, thus making it impossible to match with only one of those. Now AMF parses two schemas, one where p_1 and other where p_2 is required.

GitHub fixed issues

AMF Fixed issues

Changes in 5.0.0-beta.3

04 Aug 22:02
68c751c
Compare
Choose a tag to compare
Pre-release

Changes

Removed spec related media types from our interfaces to avoid redundancy

Why?: Previously in beta.2 when rendering, validating and transforming users had to specify the mime type of the specification even if they were using a specific configuration like RAMLConfiguration.RAML10(). This led to redundant code such as:
RAMLConfiguration.RAML10().createBaseUnitClient().render(unit, ProvidedMediaTypes.RAML10)
Now all operations will obtain the specification type directly through the usage of specific configurations. The same use case as above can now be acheived through a more concise code:
RAMLConfiguration.RAML10().createBaseUnitClient().render(unit)
Specific changes for each operation:

  • parse: client.parse(url) method will only receive one parameter for the path of the root file. For the case of client.parseContent(content, mediaType) an optional media type parameter is available only to provide the syntax of the content.
  • transform: The PipelineName parameter, which contained the specification type, no longer exist as only the pipeline id can be provided. An example for transforming with Editing pipeline would be client.transform(unit.baseUnit, PipelineId.Editing).
  • render: client.render(unit, mediaType) now receives an optional mediaType to provide the syntax of the result, while the specification type will depend on the configuration being used. Note: for the case of rendering jsonld `application/ld+json' media type can be used with any configuration.
  • validate: client.validate(unit) no longer receives the optional parameter ProfileName as this value is obtained directly through the configuration used.

Limit usage of composite configurations to parsing

Why?: Composite configurations such as APIConfiguration.API() which contain capabilities for more that one specification can only be used for parsing. We have maintained this functionality as it offers AMF users the possibility of parsing any content without knowing the specification type beforehand. Any other operation that is invoked when using composite configuration will result in errors, such as rendering, transformation, or validation.

New Spec class returned in AMFParseResult

Why?: Due to the multi-spec parsing functionality explained above, we have included a new value in AMFParseResult which provides the specification type that was parsed. This is essential for users that use multi-spec parsing because through the Spec value they will know which specific configurations they need to use for other operations such as transformation or validation.

Removed merging capabilities of configurations

Why?: Since the use of specific configurations is essential for the correct functioning the majority of AMFs operations, we have eliminated the possibility of merging different configuration as this would lead to inconsistent functionality.

Removed jena-shacl dependency for amf-validation artifact

Why?: The SHACL validator provided by jena has been fully replaced by our own implementation, allowing us to exclude this dependency.

Fixes

Fixed parsing of yaml content when using parseContent interface with no specified media type

Why?: In beta.2 when using the parseContent interface if the string was in a yaml format AMF was unable to parse it correctly returning an ExternalFragment. It is now capable of parsing yaml content correctly returning its corresponding Document.

Fixed ValueField hierarchy in JS typings

Why?: The actual hierarchy of ValueField classes was not represented correctly in the typings, leading to compilation errors.

Add resource fetching capabilities to ShapeValidationConfiguration

Why?: Our existing payload validation plugin implementations where fetching files and did not have this functionality available in the previous interface.

Avoid error when parsing JSON-LD with non scalar annotations

Why?: In beta.2 unclear validations where returned in the parsing result.

Changes in 4.7.6

27 Jul 21:00
ef46177
Compare
Choose a tag to compare

Released July 27, 2021.

JS asset

JVM asset

RAML 1.0 - Validation of duplicate properties in data type

Given the following invalid type definition with duplicated property names:

types:
  failing:
    type: object
    properties:
      a: string
      a?: string
    example:
      a: "some example"

AMF was throwing an unrelated violation in JVM, but nothing in JS. A new violation has been added to make the error clearer in both platform, AMF now returns:
Duplicated property names: a

Dependencies Changes

Updated

  • org.apache.commons % commons-compress moved from 1.19 to 1.21
  • ajv javascript dependency moved from 6.5.2 to 6.12.6

AMF Fixed issues

APIMF-3232 - Analyze ajv dependency update
APIMF-3212 - Adding an enum property in an extension duplicates values
APIMF-3211 - RAML inline union in extension not parsing correctly
APIMF-3209 - Missing validation for properties with same name in raml type
APIMF-3097 - SE: Anypoint Design Center doesn't allow uses of the same library multiple times
APIMF-3096 - java.lang.ArithmeticException: Division by zero with multipleOf facet

Changes in 5.0.0-beta.2

19 Jul 19:07
066def3
Compare
Choose a tag to compare
Pre-release

Changes

Added AMFElementClient

Why?: this new client holdscommon operations associated to shapes, such as serializing to Json Schema or RAML, render a domain element and others.

Renamed AMFClient to AMFBaseUnitClient

Why?: distinguish between ElementClient and BaseUnitClient.

Changed Vendor for mediaType: String in ApiDomainElementEmitter

Why?: beta.2 uses mediaTypes instead of Vendors to serialize domain + syntax

Deleted AMFLogger

Why?: its usage overlapped with AMFEventListener.

Renamed bu to baseUnit in AMFResult for the amf.*.client.scala* packages

Why?: to have consistency between scala and platform interfaces

Removed Shape constructors from the public scope

Why?: the primary constructors in the Shape hierarchy used internal argument that shouldn't be used by the end user.

Added LoaderWithExecutionContext helper interface for ResourceLoaders that have to use ExecutionContext

Why?: resource loaders that implement this interface will have their execution context updated whenever the *.Configurations execution context is updated.

Unified RenderOptions with ShapeRenderOptions

Why?: having two kinds of RenderOptions that were nested was confusing.

Added transformPipelineWithId method.

Why?: transform.* methods can be difficult to use as the users have to tell which pipeline they want to use and which spec their BaseUnit was parsed from.

Fixes

Fixed AMFErrorHandler being shared between runs

Why?: this bug caused parsing errors to "leak" between operations. This was only repeatable when using the same configuration for multiple operations.

Explicitly registered SHACL and Ajv to the global scope in JS script

Why?: fix that was added to 4.x.x but wasn't cherry-picked to this version.

Fixed amf.*.client.scala types leaking in amf.*.client.platform classes

Why?: this made very hard for platform adopters, especially users of the JS bundle, to use client classes as amf.*.client.scala classes are not exported to Javascript.

Added JS native object construction for EventListeners

Why?: JS users couldn't plug-in JS objects that respected the AMFEventListener interface. Now they should use the AMFEventListenerFactory to create them.

Added parenthesis to JS exported functions in RenderOptions to make it more "js-like" for JS adopters

Why?: method chaining with Scala no-param functions seems odd in Javascript as they can't be used from that language. For example:

new RenderOptions().withPrettyPrint.withCompactUris.withoutSourceMaps.withFlattenedJsonLd

Adding parenthesis to those methods while useless in Scala makes it easier to read and more natural to JS adopters:

new RenderOptions().withPrettyPrint()
.withCompactUris().withoutSourceMaps().withFlattenedJsonLd()

Renamed ValidationResult to AMFValidationResult

Why?: for consistency between *.scala* and *.platform* interfaces

Added Native JS payload validator interfaces

Why?: similar to the EventListeners change, AMF Payload Validation plugins couldn't be plugged in from Javascript. We added the AMFPayloadValidationPluginConverter static class to convert native js payload validation plugins to Scala ones to be able to plug them in the AMF configuration instance.

Changes in 5.0.0-beta.1

19 Jul 19:06
aa9adbf
Compare
Choose a tag to compare
Pre-release

Changes

Removed withoutFlattenedJsonLd from the public scope in RenderOptions

Why?: as embedded json-ld parsing is deprecated and emission was removed, it didn't make sense to have a render option that let the user emit json-ld in the embedded form.

Removed ExecutionLog and replaced it for EventListeners

Why?: we replaced the ExecutionLog functionality with event listeners as it was part of the static state that we aim to remove in this beta.

Fixes

  • Added AsyncCachePipeline to the AsyncAPIConfiguration
  • Added ExecutionEnvironment setter in AMFConfiguration

Changes in 4.7.5

30 Jun 18:12
a8088f8
Compare
Choose a tag to compare