MARS-Curiosity: new features! DI, FireDAC, records and more

I know, everybody is looking at the new Linux support in Delphi 10.2 Tokyo but I think this post has to come before the one about Linux support for MARS-Curiosity (spoiler: a penguin has been spotted on MARS 🙂 ).

On February, 18th I released v1.1 of MARS-Curiosity library and started adding a bunch of new functionalities in the develop branch of the repository. Today I am happy to release these features to the master branch!

During these weeks I worked a lot on making MARS a better REST library, easy to use for every Delphi developer (letting the developer to focus on application code rather than on middleware concepts), trying to take advantage of all the most modern language features and techniques. A special mention goes for the new Dependency Injection mechanism, used internally to provide context-related values to resources but also extendible so each developer can add its own injection services that may be useful in the application code (think about third party DAC libraries, ORMs, document engines, and whatever may be needed to accomplish client’s requests).

Since the beginning of this project, my main aim has always been to build a Delphi library that is feature rich, easy to use, easy to extend (to be paired with other existing Delphi technologies/libraries) but lightweight (avoiding to force you to embrace a single philosophy or some other frameworks/dependencies).

The list of the new features is long (with 70+ commits) and I also had a chance to refactor some parts of the codebase I wanted to improve. Just let me mention the additions to the FireDAC support that makes it easier to perform queries against databases (including capability of handling multiple connection definitions, embedded rightly into MARS configuration files, and transaction support) and the new features related to record types (including generic MessageBodyReader and MessageBodyWriter implementations).

Here is a first list of the new features available in MARS master branch. In the next weeks more blog posts will follow to cover the more relevant topics:

  • added an extendible Dependency Injection mechanism
    • generic mechanism to inject values into resources (application code)
    • used internally to provide context (Request, Response, Application, Engine, URL, URL prototype, Token, …)
      [Context] FMyObj: TMyObject;
      [Context] FMyVal: Integer;
      [Context] FMyIntf: IMyInterface;
  • refactoring Token management
    • removed unnecessary dependencies
    • now pluggable (use it if you needed, use a better implementation if available)
    • optimizations (performance) and improvements
  • improved FireDAC support
    • added a specific injection service implementation
      [Context] FConnection: TFDConnection;
      [Context] F: TMARSFireDAC;
    • connection definitions can now be embedded into engine/application configuration
    • TMARSFireDAC helper class
      • injectable where needed
      • greatly simplifies data access from resources
        • Query data (with transaction support)
        • Execute commands (with transaction support)
        • Life cycle management support for involved objects
        • multiple connection sources
        • params and macro automatically filled with context-aware values
        • F.Query('select * from ITEMS where ID = :PathParam_id and OWNER_ID = :Token_Claim_ACCOUNT_ID');
  • added pervasive support for records (JSON ToRecord/FromRecord serialization/deserialization support, generic MessageBodyWriter and MessageBodyReader for records, dataset related utilities, TRecord<R>, ToJSONFilter mechanism, TArray<record> handling…)
    • TRecord<TToDoItem>.FromDataSet(LToDoItem, LQuery);
      (...)
      LArray := TRecord<TTodoItem>.DataSetToArray(LDataSet);
  • MessageBodyWriter mechanism is now enabled for all data types (no more restricted to classes)
  • MessageBodyReader mechanism is now enabled for all data types (no more restricted to classes)
  • added TMARSActivation.Before/AfterInvoke mechanism
    • perfect for logging/intercept all requests
  • fixed resource’s instance creation mechanism (now looks for a proper constructor and added support for TDataModule and descendants)
  • improved TValue support in TJSONObjectHelper (including better support for DateTime values)
  • improved client-side error handling on ApplyUpdates for TMARSFDResource.Post (error informations were already available but not enforced automatically)
  • simplification of IMessageBodyReader and IMessageBodyWriter interfaces (better context informations, less sparse parameters)
  • refactoring RequestParamAttribute(s) (PathParam, QueryParam, BodyParam… now uses injection services to be context-aware and MessageBodyReaders to parse values)
  • refactoring to keep all serialization code inside MessageBodyWriters/Readers classes
  • removed some memory leaks and improved error handling in general

I want to publicly thank Stefan Glienke and Nando Dessena who always lend me wise suggestions and hints. And of course my customers who acts both as sponsors and beta testers for this library.

Hope you will find these improvements and changes useful as they seems to me and stay tuned for other content about the MARS-Curiosity REST Library. 🙂

Andrea

3 thoughts on “MARS-Curiosity: new features! DI, FireDAC, records and more

  1. Claudio Piffer says:

    Hi Andrea,

    only a word: wow!!

  2. Flavio Basile says:

    Great work!
    Thamks Andrea!

  3. Jean Vandromme says:

    Hi Andrea,

    Thanks for the new capabilities you’re worked on !
    I am looking a little deeper in your FireDacBasic demo and have some questions:
    If I have more than one dataset in the server.maindata, I get all data from all queries even if I link only one dataset to a MARSFDResource. How can we access only to one FDQuery ? How can I use subresources ? When I use the code in comment like [GET, Path(‘/standard’)] function StandardDataSet: TArray or TDataset; I get a XML file which can not be typecasted in a MARSFDResourceDataset. The global GET server response is crypted even if we don’t use any token, the subresource (ie /standard) is not. I hope my question is understandable !

    Thanks

    Jean

Leave a Reply

Your email address will not be published. Required fields are marked *