Converting a Delphi Server to Code-First
Note that for Delphi, Code-First servers require version XE4 or later, as Code-First relies on attributes and enhanced RTTI support introduced in this version. They are also supported for Delphi-language servers only, not for C++Builder, since the latter does not support attributes.
Mind you, you don’t have to convert your servers to Code-First. RODL-based servers are still and will continue to be fully supported. Still, converting to the new model will make development so much easier going forward.
There are really just four steps involved in making the switch, all of them simple, and two of them automated by the IDE:
- Adjust your existing Service implementations
- Convert your auxiliary types, such as structs and enums
- Remove your
.RODLfile and the auto-regenerating
- Add one statement of code to configure your server for Code-First
Adjusting Your Existing Services
While Remoting SDK has always auto-generated service stubs for you from the .RODL, once you add code to those files, it considers them “yours”, and the RO toolchain won’t touch them again. In the past, that was one of the annoyances when adding new methods to a service, as you had to edit both the .RODL and the implementation.
For that same reason, the IDEs won’t auto-convert your service implementations for you – but making the switch is easy. For each of your services, you just do three things:
- Add the new
[ROService]attribute to your service class.
- Remove the service interface from the ancestor list.
- Change the invoker class of your service to
- To each of the methods you want to expose publicly, add the
In essence, you’d go from something like
TMyService = class(TROService, IMyService) //... fClassFactory := TROClassFactory.Create('MyService', Create_MyService, TMyService_Invoker);
[ROService] TMyService = class(TSimpleMyService) //... fClassFactory := TROClassFactory.Create('MyService', Create_MyService, TRORTTIInvoker);
Converting Auxiliary Types
Next, let's look at all the additional types you may have defined in the RODL to help your services. Enums, Structs, Exceptions or Arrays (although Arrays defined in RODL don’t really reflect in generated code).
In code, these all are contained in the _Intf file that you normally don’t touch, because it gets updated from the RODL when that changes. Since the RODL is going away, this auto-updating won’t happen anymore, so you are, in a way, “taking ownership” of these classes now.
You could just keep the _Intf file around, but there’s a ton of extra crud in there that you no longer need, and that would make it hard to maintain/update in the future. So really, it makes sense to clean that up, and we have automated that for you with a small IDE wizard that takes care of this and the next step. We’ll get to that in a second.
Remove the RODL and Auto-Generated Code
Once the auxiliary types are taken care of, the RODL file and the three source files generated from it (but not the services!) can simply be removed from the server project and deleted.
Bye bye RODL, it was nice to have known you.
The “Convert to Code-First” Wizard
To automate the above two steps, we’ve added a small helper wizard to the Delphi IDE. Read more about how this works here.
When you invoke this conversion, the IDE will do two things:
It will generate a new code file in your projects’s language, named after the RODL file, but with a
_RodlTypessuffix using your project's main language (Swift, C# or Oxygene). This file will contain all auxiliary types from your
.RODL– in essence it will be the same as the previous `_Intf' file, but without all the extra crud.
Once done, you can rename the
_RodlTypes file to anything you like, or even move the types in it around into different source files (for example into the same file as their related service) as you see fit for the structure of your projects. These are now “your” types. If you need to make changes to them for new versions of our server, you simply change them in code.
The syntax for event sinks has changed slightly for Code-First servers, replacing the auto-generated sink-specific Writer with the new generic
IROEventWriter<T>. So your event sink code changes from this:
var chateventswriter: IHTTPChatEvents_Writer; .. chateventswriter := (EventRepository as IHTTPChatEvents_Writer); chateventswriter.OnSendMessage(Session.SessionID, thisuserid, aMessageText, aDestination <> '');
var chateventswriter: IROEventWriter<IHTTPChatEvents>; .. chateventswriter := EventRepository.GetWriter<IHTTPChatEvents>(Session.SessionID); chateventswriter.Event.OnSendMessage(thisuserid, aMessageText, aDestination <> '');
Note: The old syntax is still supported for event sinks defined in RODL.
Optionally, Configure Code-First
As a last step, there’s two lines of code you might want to add to your server, in order to control the “name” of your server as exposed externally (in the RODL that clients will download):
Add these lines among the startup code of your server:
uRORTTIServerSupport.RODLLibraryName := 'MyServer';
If you don't add this lines, Remoting SDK will use reasonable defaults derived.
Adding new Services
As you can imagine, adding new services to a Code-First server will be super easy with the new model. Simply add a new class, attach the
[ROService] attribute, and mark the methods you want published with
[ROServiceMethod]. Done. If you need new structs or enums, simply define them in code.
Converting a Server Partially
Note that you don’t necessarily need to convert all services to be Code-First in one go. You can start by converting some of your services and deleting them manually from the RODL, and leaving others RODL-based. Of course in that case you will want to delay removing the RODL file and converting the classes from the
_Intf, until you're all done.
At runtime, Remoting SDK will take care of merging what’s in your RODL and what’s defined “Code-First” and make sure it all works together.