Quantcast
Viewing all articles
Browse latest Browse all 1008

TMS XData Service Operations

The latest TMS XData 1.1 version introduces a major feature: Service Operations. In addition to having your objects published as REST resources automatically, you can now add server-side logic in a very easy and straightforward way.

Service operations are defined as interfaces. Any interface can become a set of operations, all you need to do is add the [ServiceContract] attribute to the interface:

type
  [ServiceContract]
  IMyService = interface(IInvokable)
  ['{BAD477A2-86EC-45B9-A1B1-C896C58DD5E0}']
    function HelloWorld: string;
    function FindOverduePayments(CustomerId: integer): TList<TPayment>;
  end;
The nice thing is that in addition to sending and receiving values of scalar types, you can also send and receive Aurelius entities. You can also use TStream for low-level operations.

The next step is to write the server logic, which is done just by implementing the interface in some class, and adding the attribute [ServiceImplementation] to that class:
type
  [ServiceImplementation]
  TMyService = class(TInterfacedObject, IMyService)
  private
    function HelloWorld: string;
    function FindOverduePayments(CustomerId: integer): TList<TPayment>;
  end;
 
implementation
 
function TMyService.HelloWorld: string;
begin
  Result := 'Hello, World';
end;

function TMyService.FindOverduePayments(CustomerId: integer): TList<TPayment>;
begin
  Result := TXDataOperationContext.Current.GetManager.Find<TPayment>
    .CreateAlias('Customer', 'c')
    .Where(TLinq.Eq('c.Id', CustomerId) and TLinq.LowerThan('DueDate', Now))
    .List;
end;
And that's it. When you create the XData server module, it will find the interfaces and implementations automatically through the attributes, and will make the operations available through the server.

The FindOverduePayments method implementation illustrates how smooth is the integration with TMS Aurelius. The TXDataOperationContext class provides you with some useful properties to implement your server logic. The main property is GetManager, which provides you with an Aurelius TObjectManager.

All you have to do is use the manager to persist objects, or to query objects using the Aurelius full query API. When implementing the server logic, you don't have to deal with database connections (XData uses its connection pool), you don't need to instantiate the object manager, you don't need to deal with memory management and also with JSON serialization.

To invoke the service operation from any client using HTTP, you just POST to the operation address, passing the parameters in JSON format:
POST /tms/xdata/MyService/FindOverduePayments HTTP/1.1
 
{
  "CustomerId": 10
}
XData will parse the parameters, invoke your method, which in turn will use Aurelius to query the database, retrieve all TPayment objects that match the criteria, and return a plain JSON array with the payment objects in JSON format.

Another great thing is if your client is written in Dephi, you can use the TXDataClient class. You can then benefit from the interface you declared and use it at client side as well. Use the TXDataClient to retrieve the interface, and call the interface method. XData will do all the HTTP requesta and JSON conversion for you, and will give you the TPayment objects:
var
  Client: TXDataClient;
  MyService: IMyService;
  Payments: TList<TPayment>;
begin
  Client := TXDataClient.Create;
  Client.Uri := 'http://myserver/tms/xdata';
  MyService := Client.Service<IMyService>;
  Payments := MyService.FindOverduePayments(10);
  // add your logic that deals with TPayment objects
end;
You can even pass your Payments list to a TAureliusDataset to easily show them in a TDBGrid or any other control that is data aware or using Live Bindings.

You can learn more about XData using the official online documentation. Or you can refer directly to the Service Operations chapter.


Viewing all articles
Browse latest Browse all 1008

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>