Version 4.17 (Sep-2020)
PATCH v6 1/5 misc: Add Synopsys DesignWare xData IP driver. Gustavo Pimentel Fri, 12 Feb 2021 09:31:23 -0800. Add Synopsys DesignWare xData IP driver. This driver enables/disables the PCI traffic generator module pertain to the Synopsys DesignWare prototype. Misc: Add Add Synopsys DesignWare xData IP driver -2021-02-03: Gustavo Pimentel: New v4,2/6 misc: Add Synopsys DesignWare xData IP driver to Makefile misc: Add Add Synopsys DesignWare xData IP driver -2021-02-03: Gustavo Pimentel: New v4,1/6 misc: Add Synopsys DesignWare xData IP driver misc: Add Add Synopsys DesignWare xData. Svddriver Query or set the underlying LAPACK driver used by 'svd'. Svds Find a few singular values of the matrix A. Swapbytes Swap the byte order on values, converting from little endian to big endian and vice versa. Sylvester Solve the Sylvester equation symamd.
New:Full support to use XML documentation in Swagger documents. You can now describe your REST API documentation using XML documentation syntax, and even using the same content for both. Write your documentation once, use it in several places - for your Delphi developer, for your API consumer.
New:SwaggerExclude attribute allows you to exclude specific endpoints from the final Swagger API documentation.
New:Swagger demo shows how to create Swagger documentation, provide SwaggerUI interface to your end user, and use XML documentation to enrich your documentation content.
Improved:Service contract routing now allows replacing the root URL. Requests like 'GET /' or 'POST /' can be now be configured to be routed to your own service implementation.
Improved: Swagger documents now take entity set permissions into account, omitting Aurelius CRUD endpoints which are not available due to the entity set permissions configuration.
Improved: The endpoints for Swagger-UI ('/swaggerui') and Swagger.json ('/openapi/swagger.json') don't appear anymore in the Swagger document itself. This avoids pollution of the Swagger document, focusing only on your own API endpoints.
Improved: Endpoints are now sorted alphabetically in Swagger documents, making it much easier to be visualized in Swagger-UI for example.
Improved: Parameters and function results of type TDate, in service contracts, will now show in Swagger document as 'date' instead of 'date-time'.
Version 4.16 (Aug-2020)
New:FireDAC-SQL demo shows how to create a REST resource (GET, POST, PUT, DELETE) using FireDAC to access the database directly via SQL, without using TMS Aurelius.
Improved: EXDataClientException now contains property Info holding the JSON response of the error.
Improved: XData Web Request (THttpRequest) now provides Timeout property.
Improved: Compatibility with TMS Web Core 1.5.
Fixed: Service operations returning objects and also with 'out' params were returning wrong JSON.
Fixed: When loading objects using TXDataClient, proxied objects were not being loaded if they were located at a depth level higher than the MaxEagerDepth configuration (default to 3).
Fixed: SwaggerUI was not working in SQLiteConsoleServer demo.
Version 4.15 (Jun-2020)
Improved: XData trial binary compatibility with TMS Web Core 1.4.2 trial.
Fixed: Wrong serialization of objects that indirectly inherited from List<T>. For example, TList2 = class(TList1), TList1 = class(TList<TSomeClass>). Serialization of TList2 was wrong.
Version 4.14 (Jun-2020)
- Improved:Web Core client components updated to support the newest TMS Web Core 1.4.
Version 4.13 (May-2020)
New:Flexible URL routing mechanism using Route attribute, allows multiple segments in path routing, and flexible parameter binding. For a single method, users can route it to an URL like 'orders/approved/{year}/{month}'. The service operation will be routed from the invoked URL, and the values passed in URL will be automatically bound to method parameters.
New:Delphi 10.4 Sydney support. Full compatibility with the recently released new Delphi version.
New:XData server now returns a xdata-version header in each request. This will make it easier to tell the available features of the XData server being connected to. Current version returned is 2.
New:TXDataClient.ForceBlobLoading property for backward compatibility with old XData servers that could not receive eager blobs as @xdata.proxy.
Improved:Significant performance increase when sending entities to XData server that contain blobs. For example, consider a Customer with Photo (blob) field you retrieved using TXDataClient. In previous versions, calling Put to update the customer would load the Photo content from the server, even if it was not modified. Now it's optimized and it will send to the server just a proxy information. The server is also now smart enough to identify those proxies and proceed properly, even when the blob is not lazy.
Improved:Blob serialization was not flagging blob as loaded, causing a lazy blob to be loaded multiple times. Suppose there is a property TCustomer.Photo of type TBlob. Such blob is lazy and not loaded. During JSON serialization, the content of the blob is loaded, but property TCustomer.Photo was not being marked as load. Thus, in a second serialization, or when the app tried to read property content, the blob would load again.
Improved:It's now possible to send blobs in JSON using format 'Photo@xdata.proxy': 'Customers(1)/Photo', even for blobs not flagged as lazy. In previous versions, this was only possible for lazy blobs. Sending such values will simply not modify the blob value in the server.
Improved:Ambiguity between enumeration and member name solved in $filter expressions. Suppose a filter expression like '$filter=Pending eq 2'. There might be a situation where Pending would be both an enumeration name and an entity property. Now, if that happens, Pending will be considered as an entity property. Otherwise, as an enumeration.
Improved:Enumeration values can be prefixed by the enum type in $filter expressions. To avoid ambiguous naming, enumeration values in filter expressions can now be prefixed by the enum type. For example: '$filter=Pending eq TStatus.Pending'. TStatus.Pending is an enumeration value, Pending is a property value.
Fixed: Memory leak when building a TXDataAureliusModel object using a TXDataModelBuilder raises an error.
Fixed: TXDataClient 404 error not raising exception when server methods did not return objects (procedures, not functions).
Fixed:Value endpoints (/$value) were not returning correct string values when the content had double quotes.
Fixed: Serialization of TArray<byte> and TBytes was not working correctly when the application/server was compiled using runtime packages.
Fixed: Error 'Requested action has ambiguous implementation' in SwaggeUI endpoint when starting/stopping XData server multiple times.
Fixed: Delphi IDE splash screen showing multiple XData icons.
Fixed: XData Web App Generator creating wrong persistent fields when XData server had GUID field types.
Version 4.12 (Apr-2020)
Improved: UriPathSegment now can be applied to entities (for entity set naming).
Fixed: TXDataWebClient not raising OnError events when an error happened during RawInvoke call.
Fixed: XData Web Application generator updated to work with latest Web Core 1.4.
Fixed: XData Music Demo updated to work with latest Web Core 1.4.
Version 4.11 (Apr-2020)
New:Enumerated literals now supported in $filter query string.
Fixed: Wrong TXDataWebDataset date/time conversion from JSON (regression). It was causing 'Invalid date time' errors and also was displaying wrong date time fields, by incorrectly adding time zone offset to the date.
Fixed: TXDataClient.IgnoreUnknownProperties had no effect when using service operations.
Version 4.10 (Mar-2020)
New:OnEntityDeleted, OnEntityInserted, OnEntityModified are new server-side events that fire after automatic CRUD endpoint operations are performed, in addition to existing OnEntityDeleting, OnEntityModifying and OnEntityInserting events, which are performed before such operations.
New:JsonConverter attribute allows for custom JSON serialization/deserialization of specific PODO and entity properties. You can for example serialize an integer as an string, a date/time as a string in a specific format, etc.
New:Support for TStream param mixed with other params. You can now have a service operation that receives a TStream parameter to also receive more parameters, as long as they are not defined to be in the request body (using FromBody parameter). This way you can use the TStream to process the raw body of the request, but still receive other parameters through the URL (either using FromQuery or FromPath attributes).
New:Demo project showing how to use multiple models (multi-model design) in XData.
New:BasicAuth demo showing how to use Basic Authentication in both server and client sides.
New:Demo project showing how to use XData as an Apache module.
Improved: Swagger doesn't include definition names for lists anymore (interface gets less cluttered).
Fixed: Swagger specification was wrong for entity sets (in automatic CRUD endpoint). It was indicating an array of entities, but the correct format was an object with 'value' property and then array of entities, according to the specification.
Fixed: Sending an object with a blob property set to null was not modifying the blob in the database.
Fixed: Generated XData Web Application was being created with title 'TMS XData Music Web Application'. The word 'Music' was removed from the title.
Version 4.9 (Nov-2019)
New:Support for Android 64-bit platform (Delphi 10.3.3 Rio).
New:TXDataOperationContext.CreateManager and AddManager methods. You can now add more Aurelius managers (TObjectManager) to the XData context. This makes it easier to create other Aurelius managers in addition to the default one, and at the same time return entities from that new manager, without worrying about evicting those objects to destroy them.
New:TXDataClient.IgnoreUnknownPropeties property. You can now set this property to true to force the client to ignore properties sent by the server that the client don't know. Until now, the client would raise an exception saying the property is unknown.
Improved: $expand now appears as an optional parameter in SwaggerUI for endpoints that return Aurelius entities.
Improved: SwaggerUI was displaying parameters as required even when they had default values in service operations.
Improved: TXDataWebDataset compatibility with TMS Web Core 1.3. There is a breaking change between TMS Web Core 1.3 and 1.2 regarding dataset, which means this XData version won't work with previous TMS Web Core versions (1.2 and lower).
Fixed: TXDataClient and TXDataWebClient were building request URLs with double slashes (//) in some requests. This didn't cause any errors but was wrong anyway.
Fixed: TMS XData Music Demo failed to compile in TMS Web Core 1.3 (fixed in 4.9.1).
Fixed: TMS XData Web Application wizard was generating code that didn't compile (fixed in 4.9.1).
Version 4.8 (Oct-2019)
Improved: TXDataWebClient was raising some exceptions as Exception class. It's now using EXDataClientException.
Fixed: SQLiteConsoleServer demo (the 'Music server' used in several demos, like the TMS XData/Web Core Music Web Application) was not correctly importing Tracks into Albums.
Version 4.7 (Sep-2019)
New:$expand query option now also applies for blobs. In previous versions, clients could request associations to be inline in JSON response by using the $expand query option in format '$expand=Customer'. Now you can also ask for blob properties to be inline (as base64 string) in the JSON response, by providing the name(s) of blob properties in the $expand query option. For example, '$expand=Photo'.
Improved: TXDataWebClient.Post now updates the key (id) properties of the object with the generated value returned by the server. When calling TXDataWebClient.Post you pass a Javascript object instance to the method, which will be serialized as JSON and sent to the server to be inserted. If the server generates a new id for the object, then the Javascript object instance passed to Post will have its id property automatically updated with the id generated by the server. This has a good side effect on using TXDataWebDataset as well: when automatically applying updates using TXDataWebDataset, the id fields will automatically be filled with the server-side generated value.
Improved: Polymorphism when deserializing JSON objects allows deserializing both PODO and XData/Aurelius entities using the same method. For example, suppose a service operation (server-side method) that receives a parameter of type 'TObject'. Clients can now send either a PODO object or a Aurelius entity object to that method, and either will be serialized correctly. In previous versions it would consider everything as PODO and wrongly serialize the Aurelius entity.
Fixed: Multiple calls to TXDataWebDataset.ApplyUpdates could cause some errors. That would happen if in the second call to ApplyUpdates, the modifications of the first call were not yet sent to the server, causing the same delta to be processed twice.
Version 4.6 (Jul-2019)
New:HttpPatch attribute to specify service operations responding to PATCH HTTP method.
New:macOS 64 support in Delphi Rio 10.3.2.
Fixed: Swagger not including all service operation actions when the actions endpoints were the same.
Version 4.5 (Jun-2019)
New:FromQuery, FromPath and FromBody attributes allow higher control in parameter binding and URL routing for service operations.
New:Support for SwaggerUI provides a built-in web-based environment to test the API from the browser.
New:SwaggerOptions and SwaggerUIOptions properties allow to easily enable and configure Swagger support for the API.
New:EnableEntityKeyAsSegment property allows single-entity URL endpoints to follow the format 'entity/id' - for example, customer/10, in addition to existing default format customer(10).
Improved: String and enumeration literals now can be sent in URL without being enclosed by single quotes (e.g., CustomerByName?Name=John instead of CustomerByName?Name='John').
Fixed: TXDataWebClient invoking service operations with default parameters was requiring all parameters to be passed, including the ones with default values.
Version 4.4 (Mar-2019)
Fixed: Index out of range error in TMS XData Web Application Wizard when XData server has no entities.
Fixed: Generated XData Web Application not supporting filtering by subproperties (e.g., Invoice/Customer/Name eq 'John').
Version 4.3 (Jan-2019)
New:XData Server wizards generate XData server applications using the new design-time components instead of pure code. The generated application is now way easier to maintain and evolve, given it uses the RAD approach with design-time components. There is now wizard for server as VCL application. Next versions will include console application, Apache module or Windows service.
New:TXDataWebDataset.EnumAsInteger property controls how enumerated type properties will be represented in the dataset. This is a breaking change.
Improved: All demos refactored, now using the new non-visual components: TXDataServer, TAureliusConnection, TXDataConnectionPool and TSparkleHttpSysDispatcher, making them easier to understand for beginners and easier to change them.
Improved:TXDataWebClient.OnLoad method now provides the newly created entity in the Args.Result property, when using Post method.
Fixed: TXDataWebClient.OnRequest event not being called when executing service operations with RawInvoke method.
Fixed: Workaround a bug in Delphi Rio causing serialization of TJSONNumber values to be always serialized as null (TJSONNumber.Null always returning true).
Fixed: Type mismatch when passing an empty array to a service operation that receives the dynamic array as var/out parameter.
Fixed: XData Service wizard did not appear if there was no open project in IDE.
Fixed: Inoffensive memory leak in TSparkleHttpSysDispatcher when the dispatcher was never activated.
Fixed: TXDataWebDataset now creates TFloatField field for XData properties of type Currency, instead of TCurrencyField (unsupported in TMS Web Core clients).
Fixed: XData Music Demo was issuing JSON Web Tokens with wrong expiration date/time.
Version 4.2 (Dec-2018)
Improved: TXDataWebConnection now 'disconnects' (cleans model object, requiring a new connection) when URL is modified.
Fixed: Workaround for a bug in Delphi Rio causing JWT tokens to be always rejected due to expiration (TJSONNumber.Null always returns true).
Fixed: TXDataWebClient.RawInvoke did not allow to receive a full JSON object as a single parameter.
Fixed: XData Web App Application Wizard incorrectly created TExtendedField fields for Int64 types on the server.
Fixed: Typo in the generated XData service code: 'form the client' should be 'from the client'.
Version 4.1 (Nov-2018)
New:XData Web Application Wizard to generate GUI to perform CRUD operations on entities. You can now generate a web application that allows users to insert, modify and/or delete entities.
New:Support for Delphi 10.3 Rio.
Fixed: TTime fields not correctly supported in TXDataWebDataset.
Fixed: XData Service Wizard created new service units in the first project of a project group. New services will be created in the currently active project now.
Version 4.0 (Nov-2018)
New:XData Web App Generator wizard. This wizard creates a complete TMS Web Core client app based on a responsive Bootstrap template. The generated application should be based on an XData server and will provide a user-interface for listing XData server entities, including searching, ordering and pagination.
New:Design-time support with a new set of components for XData: TXDataServer and TXDataConnectionPool components.
New:XData Service Operation wizard. Makes it very easy to create new service operations (server-side business logic).
Improved:TXDataWebDataset.Load now automatically connects the TXDataWebConnection if it is not connected.
Improved:TXDataServerModule.SetEntitySetPermissions supports '*' as the entity set name which will be considered the default permissions for all entity sets.
Improved:TXDataClientResponse.ResultAsArray and ResultAsObject for quick access to Result as a Json array or object.
Fixed: TXDataWebClient.RawInvoke did incorrectly require parameters of type 'out'.
Fixed: TXDataWebDataset did not set correct datetime values for the entity properties.
Version 3.2 (Sep-2018)
New:TXDataWebDataset properties QueryTop, QuerySkip, ServerRecordCount, ServerRecordCountMode. This makes it easier to retrieve paged results from the server (QueryTop, QuerySkip) and retrieve the total number of records on the server (ServerRecordCount, ServerRecordCountMode). This number does not take the page number and page size into account.
New:TJwtMiddleware.AllowExpiredToken and ForbidAnonymousAccess properties. This makes it easier to reject requests with expired tokens or requests without tokens (anonymous). Just set these properties. This is a breaking change as the middleware now rejects expired tokens by default. Please refer to the TMS Sparkle documentation for more information.
New:TCorsMiddleware middleware makes it straightforward to add CORS support to any Sparkle module. Please refer to the TMS Sparkle documentation for more info.
Improved: XData Music Demo includes options for ordering, paging and filtering (search) of listed records.
Improved: 'New TMS XData Server' Wizard adds commented code to include CORS and Compress middleware. Uncomment the generated code to easily enable the features.
Improved:URIPathSegment attribute with empty string can be inside a service contract; it supports creating service operations at the 'root' of the server.
Fixed: TXDataWebDataset now correctly creates TStringField for GUID properties (TGuidField is not supported in TMS Web Core).
Fixed: Removed memory leaks in desktop client of the JWT Auth demo.
Fixed: 'New TMS XData Server' wizard updated with option to use new TMS Aurelius native database drivers.
Version 3.1 (Jul-2018)
New:XData Music Web Application demo. A complete web application example using a TMS XData server with TMS Web Core as web front-end. Full source code is provided, and the online version of the demo is available at https://app.devgems.com/xdata/music/app.
New:TXDataWebClient.ReferenceSolvingMode allows automatic solving of $ref occurrences in JSON response, which is now the default behavior.
New:Demos XData Web-Client Framework, showing use of TXDataWebClient, TXDataWebDataset and integration with FNC Grid.
New:TXDataWebConnection.OnResponse event intercepts all successful HTTP requests made by the XData web client framework (3.1.1).
Fixed: Servers with Int64 type in model were not supported when used from TMS Web client (3.1.1).
Version 3.0 (Jul-2018)
New:Full-featured TMS XData Web-Client Framework provides RAD, design-time and high-level components for building web applications using TMS Web Core and TMS XData. Buildling a REST API-based web application has never been as easy. This includes dataset-like usage that feels home to Delphi developers.
New:TXDataWebClient.RawInvoke allows low-level invoking of service operations from TMS Web Core applications.
New:TXDataWebConnection.OnRequest and TXDataWebClient.OnRequest events allow intercepting and modifying outgoing requests (for example, to add authentication headers).
New:TXDataWebDataset.CurrentData provides the underlying JSON object of the current web dataset record.
New:TXDataWebConnection.OnError event which is fired whenever an error happens while performing requests to XData server from TMS Web Core apps.
New:TXDataWebClient request methods (List, Get, Post, RawInvoke, etc.) now have overloaded methods that accept callback functions.
New:TXDataWebConnection.Open method allows for providing callbacks for connection successful and connection error.
New:TXDataWebConnection.DesignData allows for adding custom headers at design-time (for example authorization) to properly connect to XData server.
Improved: Smooth design-time experience with TXDataWebDataset. Manually loading field defs is not necessary anymore - just connect a dataset to a web connection, provide the URL and fields will be loaded automatically at both design-time or runtime. Design-time menu option 'Load Field Defs' has been removed.
Improved: Editing TXDataWebDataset.EntitySetName at design-time in object inspector now provides a combobox with the list of available names retrieved from the server.
Improved: Dataset fields now supported in TXDataWebDataset. They will contain data (list of objects) for associated lists (many-valued associations).
Improved:TXDataWebDataset.SetJsonData now accepts non-array values (to edit a single object, for example).
Improved:TXDataWebClient.Get overloaded method allows for passing an additional query string (to use $expand option for example).
Improved:TXDataServerModule.Create overload requires just BaseUrl - no database connection pool is needed. Useful for XData servers that do not connect to a database or have a specific database usage.
Improved: TMS Web Core-only TXDataConnection and TXDataDataset components have been renamed to TXDataWebConnection and TXDataWebDataset. This is a breaking change.
Fixed: Exceptions that were not inherited from EXDataHttpException were wrongly reporting an error code (regression).
Fixed: Memory leaks when using mobile/Linux compilers (when using automatic reference counting).
Version 2.9 (May-2018)
New:OnModuleException event allows for a more flexible custom error-handling processing of exception raised during XData processing request.
Fixed: OnEntityModifying event was being fired before merge operation thus not providing correct information about the object in manager and previous state. Breaking change that can be disabled by using _FixEntityModifyingOnUpsert := False.
Fixed: Deserialization of array of objects was keeping the same instance for all objects in the array.
Version 2.8 (Feb-2018)
New:TMS RADical WEB enabled! The TMS framework for front-end Web development; XData users now have a high-level framework to write Web clients, by using the new TXDataConnection, TXDataDataset and TXDataWebClient components to access XData servers.
New:TXDataClient.Count method. Allows retrieving the number of entities in a specific resource endpoint, optionally using a query filter:
- New:TQueryParser.AddMethod allows registering custom SQL Functions to be called from XData query API. Using TMS Aurelius you can add custom SQL functions to use from LINQ. You can now also register such a method in XData so clients can use such functions from the XData API:
Then use it from query API:
New:/$model built-in URL returns metadata for the whole XData API.
New:MultiTentant Demo included in distribution shows how to use XData with multi-tentant applications (multiple databases being accessed by the same server). The demo shows how to specify the tentant by different URL or by using a custom HTTP header.
Improved: A connection was being retrieved from the pool even when the context manager was not being used by a service operation.
Fixed: Service operations invoked via GET method using enumerated type parameters are now supported.
Version 2.7 (Oct-2017)
New:OpenAPI/Swagger support! XData servers provide a JSON file containing the OpenAPI Specification (OAS, formerly Swagger) for your whole server API. This opens up a lot of possibilities, usage of several tools of the OpenAPI ecosystem is now possible. Main one is the Swagger UI, a web front-end to describe and test your API.
New:Several new types supported in service operations. Lots of new Delphi types can now be (de)serialized to JSON, meaning that these types can be used in service operations, either as input parameters, or as function results, or even as properties of PODO objects sent/received. The new supported types include:
Generic arrays: values of type TArray<T>, where T can be any supported type;
Generics lists of primitive types: values of type TList<T>, where T can by any supported type. In previous versions only lists of objects were supported;
Sets: values of type 'set of T' where T is an enumerated type;
TStrings type.
New:Support for default parameter values in service operations. You can now specify default values as parameters in service operations, using the [XDefault] attribute, and make them not required when invoking the service operations from non-Delphi clients (default parameters were already supported in Delphi clients).
New:JsonInclude attribute in PODO classes. You can configure how properties/fields with default values will be serialized in PODO classes. This attribute makes it possible to have a smaller JSON representation, by removing properties which value is null, zero, empty string, etc. Usage example: [JsonInclude(TInclusionMode.NonDefault)].
New:JsonNamingStrategy attribute. Allows you to automatically define a strategy for naming the JSON properties based on the field/property names of the class. You can use several predefined strategies: default, identity, camelCase, snake_case, identityCamelCase, identity_snake_case.
New:JsonEnumValues attribute. You can use this attribute to specify different values when serializing enumerated values.
New:TXDataRequestHandler.ManagedObjects property. This property provides more flexibility when it comes to automatic memory management at server side, allowing you to add objects to that collection and don't worrying about destroyed them.
Fixed: Error when using params of type TDate (TDateTime was not affected) in service operations (Regression).
Fixed: Design-time wizard icon not showing correctly in Delphi 10.2 Tokyo.
Version 2.6 (Jul-2017)
New:XDataProperty and XDataExcludeProperty attributes. When converting Aurelius entities to/form JSON, by default XData serializes all (and only) fields/properties that are mapped using Aurelius attributes. You can now include other (transient) properties or fields in JSON by using XDataProperty attribute. You also have the option to exclude an existing mapped member by using XDataExcludeProperty attribute.
New:JsonProperty and JsonIgnore attributes. When serializing regular Delphi objects (DTO) to JSON, XData includes all class fields by default. You can use JsonProperty attribute to add properties to the JSON (and/or change their name in JSON object) and use JsonIgnore attribute to exclude fields from JSON.
New:Support for passing parameters by reference in service operations. You can now declare and use service operations (methods) that receive parameters by reference. A server method like Swap(var A, B: Integer) is now supported for both server-side and client-side (using TXDataClient or regular HTTP requests).
New:Filter functions startswith, endswith and contains. You can now perform $filter queries with those functions to search for substrings in entity fields. For example: ?$filter=contains(Name, 'Walker') or startswith(Name, 'John').
New:Filter function concat. You can now use concat function when performing queries to concatenate two or more strings. For example: ?$filter=concat(concat(FirstName, ' '), LastName) = 'James Smith'.
New:TXDataSeverModule.UnknownMemberHandling property. You can now optionally tell the server to ignore unknown JSON properties sent by the client (instead of raising an InvalidJsonProperty error).
Fixed: Using TStream as a parameter for service operations was causing 'JSON converter not found' error.
Version 2.5 (May-2017)
New:Linux support using Delphi 10.2 Tokyo and later. Using XData on Linux doesn't require any specific change in your XData-related code. All your Linux specific code relates to TMS Sparkle - creating an Apache module and configuring TMS Sparkle to respond to requests. Once you do that, you just add the XData module to the Sparkle dispatcher as usual.
Fixed: Location header of POST responses now uses host of the client request, not the host configured in XData module.
Previous Versions
Version 2.4 (Mar-2017)
New: Delphi 10.2 Tokyo Support.
Fixed: Server-side stack overflow when trying to load a proxy property sent by the client, if the parent entity of that proxy was merged into the current Object Manager.
Version 2.3 (Jan-2017)
New: Demo project showing authentication using JWT (JSON Web Token).
Fixed: Sporadic server error loading proxied lists sent by the client.
Fixed: JWT encoding not working on XE6.
Fixed: XData Server Wizard generating corrupted source code when TMS Component Pack was installed.
Version 2.2 (Aug-2016)
New: Url convention now allows $count path segment to retrieve number of entities in a resource.
Fixed: RefCount property was wrongly being serialized in PODO objects from mobile clients.
Fixed: TXDataClient.Service<T> failing for Android clients when compiling in Release config.
Version 2.1 (Jul-2016)
New: $expand query option allows clients to have full control on how associated entities appear in JSON response.
New: Support for entities that have associations in ID (primary key containing foreign keys).
New: Support for Variant-type parameters in service operations when using GET HTTP method.
New: Breaking change:TXDataServerModule.PutMode property controls how PUT will behave at server-side.
New: TXDataServerModule.SerializeInstanceRef property controls how instances of same object will be represented in JSON response.
New: TXDataServerModule.SerializeInstanceType property controls how xdata type metadata will appear in JSON response.
New: Support for Nullable<T> values in PODO classes.
Improved: Errors on query syntax now return http code 400 instead of 500.
Fixed: JSON Proxies (@xdata.proxy) sent by the client were not being solved when reading such properties at server-side.
Fixed: Association references (@xdata.ref) were not being solved when receiving entities in service operations parameters.
Version 2.0 (May-2016)
New: Service operations can now receive and return any type of object. This increases flexibility significantly as you can use any type of object for structure input/output parameters, or to send/receive DTO classes, etc.
New: Server-Side Events allow subscribing listeners events and perform additional server-side logic
New: JWT (Json Web Token) authentication and Basic authentication, thanks to new TMS Sparkle.
New: Authentication and authorization mechanism, based on TMS Sparkle.
New: Delphi 10.1 Berlin support.
New: Service operations can now receive and return TJSONAncestor objects (Delphi XE6 and up only). This allows full control over the JSON request and response.
New: Service operations can now receive and return TCriteriaResult objects, making it easy to return Aurelius query results that use projections.
New: $inlinecount query option allow retrieving the total number of entities when using paged results.
New: Method TXDataModelBuilder.RemoveEntitySet for more flexibility when building XData models.
New: TXDataServerModule.SetEntitySetPermissions allows configuring what operations are available in each resource type.
Improved: All server-side operation (entity CRUD, service operation execution) are now performed in database transactions.
Improved: TXDataOperationContext.Current now also available in entity resources.
Version 1.6 (Feb-2016)
New: Design-time wizard to create a XData Server with a few clicks.
Fixed: Service operation using enumerated types as parameters or function results not working properly.
Fixed: EntitySet requests were not taking xdata-expandlevel header into consideration. This is a breaking change.
Version 1.5.1 (Sep-2015)
- New: Delphi 10 Seattle support.
Version 1.5 (Aug-2015)
New: Several built-in functions available to increase flexibility when querying objects in REST requests. New available functions are Upper, Lower, Length, Substring, Position, Year, Month, Day, Hour, Minute and Second.
New: TXDataClient.HttpClient property provides low level access to the Http client and allows using OnSendingRequest events to customize requests.
New: TXDataOperationContext Request and Response properties gives full control for service implementations to customize the processing of client requests.
New: TXDataServerModule.DefaultExpandLevel allows defining the expand level of JSON responses when it's not defined by client request.
Fixed: TXDataClient Get, Delete, Patch and Put operations were broken when using entities with composite id.
Fixed: POST requests not working correctly with entities with composite key.
Fixed: Data Modification requests sending content-type header with parameter (for example, ';charset=UTF8') were causing errors.
Version 1.4 (Jun-2015)
New: HttpMethod attribute allows specifying the HTTP method a service operation should respond to.
New: URIPathSegment attribute allows specifying a different name for operation/service to be used in URL.
Fixed: GET requests with query order was sometimes causing the same column to appear multiple times in a 'ORDER BY' SQL clause.
Version 1.3.1 (Apr-2015)
- New: Delphi XE8 support.
Version 1.3 (Mar-2015)
- New: Support for CORS (Cross-origin resource sharing) preflighted requests.
Version 1.2 (Dec-2014)
New: TXDataClient methods Get, Post, Put, Delete and List allows easy and high-level access to XData server objects from Delphi clients.
New: Android and iOS support for XData client objects.
New: Server support for 'x-http-method-override' header (allowing clients to tunnel HTTP methods to server through POST requests).
Fixed: Issues with floating-point literals in Query URL with non-English server systems.
Fixed: Service operations returning nil entities should respond with status code 404.
Version 1.1 (Oct-2014)
New: Service Operations allow adding custom business logic to your server using interfaces and methods.
New: Multi-Model design makes it easy to create multiple servers with different mapping, types and service operations.
New: UserName and Password properties in TXDataServerModule for basic authentication protection.
Fixed: Malfunctioning with $skip and $top query options.
Version 1.0.1 (Sep-2014)
- New: Delphi XE7 support.
Version 1.0 (Aug-2014)
- First public release.
This chapter explains basic tasks you can do with XData in code. It basically explains how to setup and start the server and how to do some basic configuration using the available classes and interfaces. The following topics describe the most common XData programming tasks and main classes and interfaces.
Creating an XData Server
TMS XData Server is based on the TMS Sparkle framework. The actual XData Server is a Sparkle server module that you add to a Sparkle HTTP Server.
Please refer to the following topics to learn more about TMS Sparkle servers:
To create the XData Server, just create and add a XData Server Module (TXDataServerModule class, declared in unit XData.Server.Module
) to the Sparkle HTTP Server. The following code illustrates how to create and run the server. Note that the code that creates the XData server module is not displayed here. You should refer to the 'XData Server Module' topic to learn about how to create the module.
The code above will create and start an XData server that will receive and respond to HTTP requests at the address 'http://server:2001/tms/xdata'.
TXDataServerModule
To create an XData server, you need to add a TXDataServerModule object to the Sparkle HTTP Server. As with any Sparkle module, it will have a base (root) URL associated with it, and it will respond to requests sent to any URL which matches the root URL of the module.
The TXDataServerModule is the main XData class, because it is the one which receives and handles all HTTP requests. So in a way, that is the class that implements the XData server. Although it is a very important class, its usage is very simple. You need to create the class using one of the overloaded constructors (TXDataServerModule is declared in unit XData.Server.Module
):
In summary, you must provide the base URL and optionally an IDBConnectionPool interface so that the server can retrieve IDBConnection interfaces to operate with the database (if database connectivity is desired). For example:
The example above creates the server with the root URL 'http://server:2001/tms/xdata' providing a connection pool of a maximum of 50 simultaneous connections. The database connection used will be a FireDac TFDConnection component named FDConnection1, declared in a data module named TMyDataModule. That is all you need to set up for your XData server to run and to expose your Aurelius objects.
The first overloaded constructor, used in the previous example, takes just two parameters: the base url and the connection pool. The other overloaded versions are just variations that provide different settings.
If you have multiple Aurelius mapping models in your application, you can optionally use an entity model different from default, or explicitly build an entity model and provide it in the constructor for specific mapping. This allows for better control which classes and mapping settings are available from the XData server. If the model is not provided, XData uses the default entity model which in turn uses the default Aurelius model. Note that the model passed to the constructor will not be owned by the server module and must be destroyed manually. For example, the following code creates a module using the 'Sample' model:
There are also versions of the Create constructor that receive an IDBConnection interface instead of an IDBConnectionPool. Those are easy-to-use variations that internally create a connection pool with a single connection (no simultaneous connections available). It is an easy approach for testing and debug purposes, but should not be used in production environments because performance might not be ideal.
Properties
Name | Description |
---|---|
UserName: string Password: string | TXDataServerModule provides these properties to specify UserName and Password required by the server using Basic Authentication. By default, these values are empty which means no authentication is performed and any client can access server resources and operations. When basic authentication is used, be sure to use HTTP secure (HTTPS) if you do not want your user name or password to be retrieved by middle-man attacks. If you do not use it, both user name and password are transmitted in plain text in HTTP requests. These properties provide a very limited basic authentication mechanism. For a more advanced variant, you should use the TMS Sparkle built-in Basic Authentication mechanism. |
AccessControlAllowOrigin: string | Specifies the accepted client hosts for which CORS will be enabled. If you want to accept any client connection, set this property value to '*'. This will enable CORS in the server including proper responses to preflighted requests. |
DefaultExpandLevel: integer | Defines the minimum level that associated entities will be expanded (included inline) in JSON responses. Default value is 0 meaning that all associated entities will be represented as references unless specified otherwise. Clients can override this value by using xdata-expand-level header. |
Events: TXDataModuleEvents | Container for server-side events. |
PutMode: TXDataPutMode | Defines how PUT will be implemented at server side with Aurelius: Either TXDataPutMode.Update or TXDataPutMode.Merge method (default). You will rarely need to change this property unless to ensure backward compatibility with older versions. This property value can be overridden in a specific request by using xdata-put-mode HTTP Request header. |
SerializeInstanceRef: TInstanceRefSerialization | Controls how instance reference ($ref) will appear in JSON response. See below for options. This property value can be overridden in a specific request by using xdata-serialize-instance-ref HTTP Request header. |
SerializeInstanceType: TInstanceTypeSerialization | Controls whenever the entity/object type appears in the JSON response (property annotation 'xdata.type'). See below for options. This property value can be overridden in a specific request by using xdata-serialize-instance-type HTTP Request header. |
UnknownMemberHandling: TUnknownMemberHandling | Defines server behavior when receiving JSON from the client with a property that is not known for that request. For example, JSON representing an entity with a property that does not belong to that entity. See below for options. |
EnableEntityKeyAsSegment: Boolean | When True, it's possible to address single entities by using the URL format '/entityset/id' - in addition to the default '/entityset(id)'. Default is False. |
SwaggerOptions: TSwaggerOptions SwaggerUIOptions: TSwaggerUIOptions | Provide access to configure Swagger and SwaggerUI behavior. See more information at OpenAPI/Swagger Support. |
TInstanceRefSerialization
TInstanceRefSerialization.Always: $ref is always used if the same instance appears again in the JSON tree. This mode is more optimized for use with TXDataClient, and is the default option.
TInstanceRefSerialization.IfRecursive: $ref is only used if the instance appears as an associated object of itself. If the instance appears in a non-recursive way, $ref is not used and the instance is fully serialized inline instead. This mode is more suited for JavaScript and other non-Delphi clients so those clients do not need to resolve the $ref objects.
TInstanceTypeSerialization
TInstanceTypeSerialization.Always: The xdata.type annotation always appears in JSON responses.
TInstanceTypeSerialization.IfNeeded: The xdata.type annotation is only present if the entity/object type is a descendant of the expected type. For example, suppose a GET request is performed in url Customers. For any entity in JSON that is of type Customer, the annotation will not present. If the entity in JSON is a descendant of Customer (e.g., DerivedCustomer) then xdata.type apppears. Basically, it means that xdata.type is implicit when absent and is of the expected type of the request/specification.
TUnknownMemberHandling
TUnknownMemberHandling.Error: An InvalidJsonProperty error is raised if JSON contains an invalid property. This is the default behavior.
TUnknownMemberHandling.Ignore: Invalid properties in JSON will be ignored and the request will be processed.
Methods
Name | Description |
---|---|
procedure SetEntitySetPermissions(const EntitySetName: string; Permissions: TEntitySetPermissions) | Specify the permissions for a specified entity set. |
IDBConnectionPool Interface
The IDBConnectionPool interface is used by the XData server module to retrieve an IDBConnection interface used to connect to a database. As client requests arrive, the XData server needs an IDBConnection interface to connect to the database server and execute the SQL statements. It achieves this by trying to acquire an IDBConnection interface from the IDBConnectionPool interface. Thus, providing an IDBConnectionPool interface to the XData server module is mandatory for this to work.
The IDBConnectionPool interface is declared in the unit Aurelius.Drivers.Interfaces
and contains a single GetConnection method:
The easiest way to create an IDBConnectionPool interface is by using the TDBConnectionPool class which implements the IDBConnectionPool interface. To instantiate it, you need to call the Create constructor passing an IDBConnectionFactory interface which will be used by the connection pool to create a new connection if needed. Alternatively, you can pass an anonymous method that creates and returns a new IDBConnection interface each time it is called.
Also, you need to specify the maximum number of IDBConnection interfaces (database connections) available in the pool. Whenever a client request arrives, the XData server acquires an IDBConnection from the pool, does all the database processing with it, and then returns it to the pool. If many simultaneous requests arrive, the pool might run out of available connections when the number of acquired IDBConnection interfaces reaches the maximum number specified. If that happens, the client request will wait until a new connection is available in the pool. TDBConnectionPool class is declared in the unit XData.Aurelius.ConnectionPool
.
The following code illustrates how to create an IDBConnectionPool interface. It uses a function named CreateMyConnectionFactory which is not shown in this example. To learn how to create such interface, please refer to IDBConnectionFactory topic.
Alternatively, you can just provide an anonymous method that creates the IDBConnection instead of providing the IDBConnectionFactory interface:
If you do not need a pooling mechanism but just want one database connection to be created for each time someone asks for a connection from the pool, you can use the TDBConnectionFactory class. It also implements the IDBConnectionPool interface:
Xdata Driver Updater
IDBConnectionFactory Interface
The IDBConnectionFactory interface is used to create an IDBConnectionPool interface used by the XData module. As client requests arrive, the XData server needs to retrieve an IDBConnection interface from the IDBConnectionPool so it can perform operations on the database. The connection pool creates a new IDBConnection by calling IDBConnectionFactory.CreateConnection method.
The IDBConnectionFactory interface is declared in unit Aurelius.Drivers.Interfaces
, and it contains a single CreateConnection method:
The easiest way to create such an interface is using the TDBConnectionFactory class which implements the IDBConnectionFactory interface. To create a TDBConnectionFactory object, you just need to pass an anonymous method that creates and returns a new IDBConnection interface each time it is called. The TDBConnectionFactory class is declared in the unit Aurelius.Drivers.Base
.
The IDBConnection interface is part of the TMS Aurelius library used by XData. You can refer to the TMS Aurelius documentation to learn how to create the IDBConnection interface.
In the following example, the factory will create an IDBConnection pointing to a Microsoft SQL Server database using a dbExpress connection. You can connect to many other database servers (Oracle, Firebird, MySQL, etc.) using many different database-access components (FireDac, dbExpress, UniDac, ADO, etc.). Please refer to Database Connectivity topic on TMS Aurelius documentation to learn about all those options. Regardless of what you use, the structure of the following code will be the same. What will change only is the content of the function: IDBConnection.
It is possible that you already have your database-access component configured in a TDataModule and you do not want to create it in code. In this case, you can just create a new instance of the data module and return the associated IDBConnection to the component. But you must be sure to destroy the data module as well (not only the database-access component) to avoid memory leaks:
OpenAPI/Swagger Support
The XData server can optionally provide a JSON file containing the OpenAPI Specification (OAS, formerly Swagger) for your whole server API. This opens up a lot of possibilities; usage of several tools of the OpenAPI ecosystem is possible. The main one is Swagger UI: it is web front-end to describe and test your API.
Enabling support for OpenAPI (Swagger)
To enable OpenAPI support in your server, just set the property SwaggerOptions.Enabled to true in your TXDataServer component, either in object inspector or from code:
Alternatively, if you are using TXDataServerModule instead, you can just use the unit XData.OpenAPI.Service
and call the method RegisterOpenAPIService anywhere in your server application:
Retrieving the OpenAPI Specification (OAS) file
The OAS file is available through a GET request to the URL '/openapi/swagger.json' relative to your server root URL. For example, if your server root is http://server:2001/tms/xdata/, then you will be able to access the file from this URL:
Excluding methods from Swagger
You can flag some service contract methods to be excluded from Swagger document, by simply adding the [SwaggerExclude] attribute to the method:
In the example above, methods Add and Subtract will be added to the documentation, but method NotThisFunctionPlease will not appear.
Enabling Swagger UI
XData server can optionally publish and endpoint to provide a SwaggerUI web-based interface that works as both a full documentation of your API as well a test interface. Swagger UI is a web-based front-end to dynamically document and test your API. Quoting their website:
'Swagger UI allows anyone - be it your development team or your end consumers - to visualize and interact with the API's resources without having any of the implementation logic in place. It's automatically generated from your Swagger specification, with the visual documentation making it easy for back end implementation and client side consumption.'
To enable SwaggerUI support in your server, just set the property SwaggerUIOptions.Enabled to true in your TXDataServer component, either in object inspector or from code:
Alternatively, if you are using TXDataServerModule instead, you can just use the unit XData.SwaggeUI.Service
and call the method RegisterSwaggerUIService anywhere in your server application:
Using SwaggerUI
Once enabled, SwaggerUI is available in the address '/swaggerui' relative to your server base path. Just open your browser and go to the address:
http://server:2001/tms/xdata/swaggerui
It will display an interface like this:
Configuring Swagger (OpenAPI Specification)
For the Swagger specification, you can use SwaggerOptions property of either TXDataServer or TXDataServerModule to configure the specification returned by the server:
Only available property is AuthMode and options are TSwaggerAuthMode.Jwt or None. When Jwt is enabled, a new security definition named jwt requiring an Authorization header will be added to all requests.
You can also configure the specification by passing parameters in the query part of the URL, and they can be one of the following:
Name | Description |
---|---|
ExcludeEntities | Boolean parameter. Default is False. When True, the specification will not contain the automatic CRUD operations on entities provided automatically by XData (entity resources). Example: /openapi/swagger.json?ExcludeEntities=True |
ExcludeOperations | Boolean parameter. Default is False. When True, the specification will not contain any service operations. Example: /openapi/swagger.json?ExcludeOperations=True |
AuthMode | String parameter. Options are 'none' and 'jwt'. When jwt is specified, a new security definition named jwt requiring an Authorization header will be added to all requests. Example: /openapi/swagger.json?authmode=jwt |
Configuring SwaggerUI
The SwaggerUI interface can also be configured using the SwaggerUIOptions property of either TXDataServer or TXDataServerModule. Available properties are:
Name | Description |
---|---|
ShowFilter | Boolean parameter. Default is False. When True, the SwaggerUI will display a filter edit box to search for API operations. |
DocExpansion | Enumerated parameter. Specifies the default expand level of the listed API operations. Valid values are: TSwaggerUIExpansion = (List, None, Full) Default value is List. |
Examples:
Using XML Documentation with Swagger
A good (if not the best) way to document your source code is to use XML Documentation Comments. In the interfaces and methods that build your service contract, you can simply add specific XML tags and content, like this:
And Delphi IDE will automatically use it for Help Insight, showing you information about the method on-the-fly. For example, if some developer is trying to use the Sin method of your API, information will be conveniently displayed:
The good news is that, with XData, you can use such XML comments in the Swagger document and Swagger-UI that are generated automatically by XData, improving even more your REST API documentation. Since the API endpoints are generated directly from the interfaced and methods, XData knows exactly the meaning of each documentation and can map it accordingly to Swagger.
Enabling generation of XML documentation files
XData needs to read the XML files with the comments to import it into the Swagger document. You need to tell Delphi compiler to generate the XML documentation files.
In your project options (Delphi menu Project | Options, or Shift+Ctrl+F11), go to 'Building, Delphi Compiler, Compiling' (for Delphi 10.4.1 Sydney. Previous Delphi version might differ), then enable option 'Generate XML documentation'. You might also want to explicitly set the directory where the XML files will be generated, in option 'XML documentation output directory'. It's recommended to use '.$(Platform)$(Config)', this way the XML files will be in the same folder as the executable.
Importing XML documentation in Swagger
XML documentation usage in Swagger can be enabled with a single line of code:
Add the line at the beginning of your application, be it in your dpr file, or initialization section of some unit, or in the OnCreate event of your TDataModule that contains your XData/Sparkle components. In the first parameter you must provide the XData model you want to import XML files to. In the example above, XDataServer is a TXDataServer component. If you are using multi-model design, just provide the proper model there.
LoadXmlDoc will try to find the XML files in the same directory as your application is located. If the XML files are in a different folder, you can specify it explicitly using a second parameter:
Once you do that, if you check your Swagger documentation via Swagger-UI, you will see something like this:
Note how the content of summary tag goes directly at the right of the GET button, as a summary for the endpoint.
The content of remarks tag is the detailed description of the endpoint.
And the content of each param tag explains each respective parameter. Sweet!
Using different documentation for Help Insight and Swagger
Reusing the same XML comments is nice as you don't repeate yourself. Document your code just once, and the same documentation is used for documenting your Delphi interfaces (Delphi developments) and your REST API (API consumer development).
But, if for some reason you want to use different documentation content for Delphi developers and for REST API users, that's also possible. You can use the specific swagger tag to fill specific parts of the documentation. You then use the name attribute to differentiate between swagger tags.
For example, suppose the following documentation:
Note that tags summary (1) and param (2 and 3) are the regular XML documentation tags. They will be used for Help Insight:
And swagger tags with no name attribute (A), or name param-A (B), param-B (C) and remarks (D) will be used exclusively for Swagger documentation:
Customizing tags
You can also customize the tags in Swagger. Endpoints are grouped together inside a tag, which can have a name and description.
By default, the name of the tag will be path segment of the interface service. But you can change it using swagger tag with tag-name attribute.
The description of the tag by default is empty, but you can define it using the regular summary tag, or optionally using the swagger tag with tag-description attribute.
Consider the following documentation for both IArithmenticService and ITrigonometryService:
The above tags will generate the following output in Swagger UI:
Customizing document header and description
XData also takes the model name, version and description into account to build the final document. You can configure such settings directly by changing some properties of the XData model (remember that XDataServer in this example is a TXDataServer component):
Snowflake Cdata Driver
Note that you can use Markdown syntax to format the final text. Here is what it will look like: