Skip to content
Luca Minuti edited this page Apr 26, 2024 · 2 revisions

Introduction

One of the main features of WiRL is the fact that you can use any class to build your resources, there's no need to inherit from a specific class. But sometimes can be useful to ask WiRL some objects to work with, the first two examples that come to mind are the HTTP request and the HTTP response. As always you can give instructions to WiRL using attributes.

The following example shows how to inject the request and the response to a resource, in this case the attribute is Context.

type
  [Path('/myresource')]
  TMyResource = class
  private
    [Context] Application: TWiRLApplication;
  public
    [GET]
    [Produces(TMediaType.APPLICATION_JSON)]
    function List([Context] Request: TWiRLRequest; [Context] Response: TWiRLResponse): string;
  end;
 

The Context attribute can be used to decorate instance variables, properties and method parameters. WiRL provides to inject the correct object to your variables before the resource method is invoked. WiRL matches the right object by its class. These are the class that you can inject:

  • TWiRLServer: the WiRL server
  • TWiRLEngine: the WiRL engine
  • TWiRLApplication: the current WiRL application
  • TWiRLRequest: the current HTTP request
  • TWiRLResponse: the current HTTP response
  • TWiRLURL: the parsed URL of the HTTP request
  • TWiRLAuthContext: this object is used to work with the JWT token
  • TWiRLSubject: the JWT claims

These objects can be injected into different classes:

  • Resources (as in the example)
  • Message body reader
  • Message body writer
  • Filters

Custom injection

In addition to the standard WiRL classes, it is possible to inject custom classes. Objects created this way will be tied to a single HTTP request and WiRL will take care of the entire life-cycle. For example, by injecting a class into a filter and a resource, the injected instance will be the same. At the end of the HTTP call WiRL will free up the class and, in subsequent calls, a new one will be created. Objects created in this way can have several uses:

  • An object/data module that implements the business logic
  • An object that parses HTTP headers
  • An object that carries information from the resource to the filters
  • Customize a behavior depending on a configuration

To create the object to be injected it is necessary to register a factory that implements the IContextObjectFactory interface. Interestingly, the factory could also instantiate a different object based on some parameter, this way it is possible to differentiate a behavior based on the environment (development, production) or the customer.

Let's see a basic example:

interface

uses
  System.Classes, System.SysUtils, System.Rtti,
  WiRL.Core.Context,
  WiRL.Core.Injection;

type
  // Class to be injected
  TMyClass = class
  private
    FValue: Integer;
  public
    property Value: Integer read FValue write FValue;
    constructor Create(AValue: Integer);
  end;

  // The class factory is responsable to create the context.
  // It will be released by the system unless it's annotated
  // with the Singleton attribute
  TMyClassFactory = class(TInterfacedObject, IContextObjectFactory)
  public
    function CreateContextObject(const AObject: TRttiObject;
      AContext: TWiRLContextBase): TValue;
  end;

implementation

{ TMyClassFactory }

function TMyClassFactory.CreateContextObject(const AObject: TRttiObject;
  AContext: TWiRLContextBase): TValue;
begin
  Result := TMyClass.Create(42);
end;

{ TMyClass }

constructor TMyClass.Create(AValue: Integer);
begin
  FValue := AValue;
end;

initialization
  TWiRLContextInjectionRegistry.Instance.RegisterFactory<TMyClass>(TMyClassFactory);

So you need to define your class, a factory that is capable of creating the class and register both classes. The interesting part is that in the CreateContextObject method of the factory you have a reference to TWiRLContextBase, so basically you have access to the HTTP request (and much more information) and you can create the class accordingly.

Clone this wiki locally