Services

Services are the core elements that make up your Remoting SDK servers. Any server will have at least one service with at least one exposed method (lest it be a rather useless server).

Essentially, a service is a class you write yourself to implement the logic or functionality you want to expose to clients. In its simplest form, it can be a plain class with nothing but the methods that you want to provide:

[Service]
public class MyService
{
    [ServiceMethod]
    public string DoSomethingCool()
    {
        // Do something cool
    }
}
[Service]
MyService = public class(Service)
  [ROServiceMethod]
  method DoSomethingCool: String;
end;
@Service public class MyService {
    @ServiceMethod public func DoSomethingCool() -> String {
        // Do something cool
    }
}
<Service> _
Public Class MyService
    Inherits Service

    <ServiceMethod> _
    Public Function DoSomethingCool() As String
        ' Do something cool
    End Function

End Class
[ROService]
TMyService = class(TROService)
  [ROServiceMethod]
  function DoSomethingCool(): String;
end;

Through the magic that is Remoting SDK, that class will automatically be made accessible over the network so that client applications can call into it. Just how this is done we'll explore next.

Publishing a Service

Of course you don't just want any class and any method in your server application to be published and accessible over the network. There are two ways to make a class a "service", and only classes (and methods) explicitly marked for publication will be available to clients.

Code-First Servers

The new and modern way to create services is through what we call Code-First Servers. Code first services, as the name implies, allow you to create services simply by writing code, and annotating it with attributes.

Any class that directly or indirectly descends from Service (.NET) or TROService (Delphi) has the potential to be a service. To publish it, simply attach the Service (.NET) or ROService (Delphi) attribute to the class, and the ServiceMethod (.NET) or ROServiceMethod attribute to any method you want to make available, and Remoting SDK will take care of the rest. It's that simple.

RODL-Based Servers

Traditionally, and this option remains available in Remoting SDK 9, services were defined visually in a tool called Service Builder that creates an XML-based description of what the service and its surrounding types look like. From this ".RODL File", the IDE Integration will create class stubs for the service that you can then fill with your implementation.

With RODL-based Services, the canonical definition of what your services' API looks like is in the .RODL file, and it (as well as helper code generated from it) drives public access to your service.

.RODL Files

.RODL files play an important role even in Code-First servers, as they are used by the client tools to let the client know what services are available and what they look like. But with Code-First, rather than maintaining the RODL file and starting from there, the server will generate the RODL at runtime, when a client (or more likely an IDE where a client is being developed in) requests it.

  • You can and should read more about .RODL-Files here, as well as
  • check out the Connect to Server topics in the IDEs section.

Statelessness, Sessions and Scalability

By default, services are "stateless", that means every time they receive a call from a remote client, they retain no knowledge of previous calls. In fact, multiple subsequent calls from a single client could be served by different instances of the same service class, and a single instance will serve calls from random clients.

While Remoting SDK has ways to change that behavior, it is one of the core tenets of what makes servers scalable (that is, capable of serving a lot of clients with the least amount of overhead and server hardware), so in general you should try your best to implement your services within this model and keep them stateless.

Of course it is still possible and can often be important to maintain information about individual clients, from one request to the next. Remoting SDK uses the concept of a "Session" to allow a service to store data pertaining to a client during one call, and retrieve this information again during the next. Sessions are handled easily and seamlessly by the Remoting SDK infrastructure, and they can be local to a single server, or distributed in order to let your application scale out across multiple servers.

Security and Login

Also by default, any published service is accessible publicly and without requiring any form of authentication. Sometimes that is fine, but more often than not, you will want client applications to authenticate themselves before accessing the server – be it to just make sure it is a valid client application, or more commonly so that the server knows which end user is invoking actions.

This is achieved in two steps.

  1. A service can be marked as requiring an already active Session, by either setting its RequireSession property to true, or attaching the ServiceRequiresSession attribute (.NET) to it. Any calls to such a service will be rejected by Remoting SDK if no valid session is found for the client.

  2. Commonly, a single service will be left open for public access, and this service will implement a method for clients to authenticate themselves. When a client calls this "Login Service", your code will validate it against whatever rules are appropriate (for example against usernames in a database or an LDAP Directory). If authentication succeeds, you will create a session, thus granting the client subsequent access to the other services.

Authentication and Login is an optional step and only very loosely defined on Remoting SDK level, giving you a lot of flexibility in implementing it exactly as you see fit for your server. Nevertheless, it is an important topic, and thus warranted for coverage here.