Releases: aml-org/amf
Changes in AMF 5.0.1
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
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-cli
: CLI client classesamf-api-contract
: API domain classesamf-shapes
: Schema domain classesamf-aml
: AML domain classesamf-validation
: Validation domain classesamf-core
: Core domain classesamf-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 interfaceamf.[module].client
: client exposed interfacesamf.[module].client.platform
: platform (JVM & JS) interface classesamf.[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
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
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
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
- APIMF-3303 - Fixed errors "X should NOT have additional properties and "X should match some schema in Y"
- APIMF-3025 - Not validating oneOf schema correctly involving empty schemas with
required
- APIMF-2975 - Cannot define required facet in property with nillable shorthand type
- APIMF-2973 - Default value is not parsed correctly when type is defined nullable
Changes in 5.0.0-beta.3
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 ofclient.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 beclient.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 parameterProfileName
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
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
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
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 theAsyncAPIConfiguration
- Added
ExecutionEnvironment
setter inAMFConfiguration
Changes in 4.7.5
Interface Changes
Loading validation profiles from strings
There is a new method to load custom validation profiles from a string
Added
- amf.client.validate.Validator.loadValidationProfileString(..)
AMF Fixed issues
APIMF-3103: added interface to load validation profile from string
APIMF-3021: fix raml08 parameter not being added to entries in oas request parser
APIMF-3118: Issue parsing API with APISync resource loader
APIMF-3125: Issue parsing OAS3 API with APISync resource loader
APIMF-3160: Custom domain properties are not parsed from JSON-LD with compact uris
ALS-1532: Fix annotation on referenced example
Fix CLI jar assembly