It’s quite easy to guess purpose of these fields… to collect and adjust parameters for messages marshalled over HTTP transports. Probably, variables are handled well, like in the TROSoapMessage.Initialize method…
if (fSoapAction = '') and (not fActionIsCustom) then
fSoapAction := Format('urn:%s-%s#%s', [LibraryName, anInterfaceName, aMessageName]);
Http_Headers.Values['SOAPAction'] := '"'+fSoapAction +'"';
end;
if xsoSoap12 in SerializationOptions then
fhttp_ContentType := 'application/soap+xml; charset=utf-8; action=' + fSoapAction
else
fhttp_ContentType := DataFormatXml;
…but… as I can search over all RO source files… there is NO SINGLE PLACE where these parameters are applied to related HTTP transport object… no single call for uROHTTPTools.SetHTTPInfo() found over whole library. As a result of this, Content-Type param of outgoing HTTP response is always set to default
Content-Type: text/html; charset=ISO-8859-1
It is invalid for XML formatted responses, typically SOAP responses, where
Content-Type: text/xml; charset=utf-8
…is expected.
It seems that there is something forgotten in this concept, something planned but finally unfinished…
…just to be sure… Im talking about server-side message handling, when server outgoing response is assembled. On the client side, there is point in source code where IROMessage.ApplyAttributes2_Transport method is called… mean this:
This is fragment of my version MegaDemoLibrary_Invk.pas:
procedure TMegaDemoService_Invoker.Invoke_EchoPerson(const __Instance: IInterface; const __Message: IROMessage; const __Transport: IROTransport; out __oResponseOptions: TROResponseOptions);
var
l_aPerson: MegaDemoLibrary_Intf.TPerson;
l_anotherPerson: MegaDemoLibrary_Intf.TPerson;
__lObjectDisposer: TROObjectDisposer;
__lintf: MegaDemoLibrary_Intf.IMegaDemoService;
begin
CheckRoles(__Instance, GetDefaultServiceRoles());
__Message.SetAttributes(__Transport, ['EA_Model'], ['C:\Dev\ROSDK3\Tests\MegaDemo\NewLibrary.eap']);
l_aPerson := nil;
l_anotherPerson := nil;
try
if not Supports(__Instance, IMegaDemoService, __lintf) then begin
raise EIntfCastError.Create('Critical error in TMegaDemoService_Invoker.Invoke_EchoPerson: __Instance does not support MegaDemoService interface');
end;
__Message.Read('aPerson', System.TypeInfo(MegaDemoLibrary_Intf.TPerson), l_aPerson, []);
__lintf.EchoPerson(l_aPerson, l_anotherPerson);
__Message.InitializeResponseMessage(__Transport, 'MegaDemoLibrary', 'MegaDemoService', 'EchoPersonResponse');
__Message.Write('anotherPerson', System.TypeInfo(MegaDemoLibrary_Intf.TPerson), l_anotherPerson, []);
__Message.Finalize();
__Message.UnsetAttributes(__Transport);
finally
__lintf := nil;
__lObjectDisposer := TROObjectDisposer.Create(__Instance);
try
__lObjectDisposer.Add(l_aPerson);
__lObjectDisposer.Add(l_anotherPerson);
finally
__lObjectDisposer.Free();
end;
end;
end;
No occurence of “ApplyAttributes2_Transport” found… just as all other “Invoke_xxx” methods in this unit.
Additionaly, I’d check content of “…\CodeGen\uRODLToPascalInvk.pas” unit… the same… no single mention about using of “ApplyAttributes2_Transport” method…
Ok, I’ll prepare simple testcase, to reproduce and present this issue…
Ok, I’ll try… does it means that CODEGEN1 is obsolete and unmaintained… from what time? Was this fact published and underlined somewhere?
If I can consider… starting with r.1517 there is functional discrepancy between code, generated using CODEGEN1 and CODEGEN2… resulting to invalid/different code behavior in CODEGEN1 units?
Codegen4 was created 5 years ago. We have switched to it in that time. Codegen1 isn’t updated for such time too.
it wasn’t removed 5 years ago for maintaining generation of unit in Lazarus for non-windows platforms.
I’ve logged an issue (#19142) for removing Codegen1 from installation for preventing such misunderstanding.
if you are using cmd line compilation, you can [re]generate units with rodl2code.exe.
also you can use the rocg4_helper program. I’ve already posted it at this forum.
it’s a simple wrapper for the uROCodegen4Helper.pas unit that allows to generate files too and used by our IDE packages for generating files inside Delphi IDE.
Ok, thanks for explanation… I’ll re-generate all our RODL’s using CODEGEN4.
Btw, we are still using classic, old-fashioned server design, based on RODLs… CodeFirst concept is not suitable for us, for many reasons (strict separation between library definition and implementing code, mainly…)… is there a certainty that RODL-based server design will be preserved and still maintained in future?
Good to hear from you, thanks. Btw, have you any knowledge or estimate which server design concept is preferred by customers… RODL vs CodeFirst? I must say that strict separation between library definition and implementing code is - in common meaning - more usable, better to maintain… in compliance with classical time proven concepts like TLB, IDL… and RODL, of course.
It doesn’t have any influence to be honest. both types of servers work equally.
one group of users like RODL-based servers, other group - CodeFirst-based servers.
Initial developing can be more easier in Service Builder, because codegen will create automatically _impl for you from template.
Note: Service Builder allows to select some options that are used for generation of Delphi units.
Note2: RODL-based server can be converted to CodeFirst-based server in any time.
from maintaining sight:
RODL-based server generates _Intf at compiling stage. in CodeFirst-based server you should start server and generate _Intf from started server.
I just tried to generate CODEGEN source files for MegaDemo project, using Service Builder (r.1517, of course)… and there is some strange thing I cannot quite understand:
…inside of Service_Invoker.Invoke_xxx methods depends on library custom attributes, defined in RODL. Say other way - if there is at least one custom library attribute defined in RODL, generated code contains lines for setting transport parameters, like this:
Hm… regardless of anything said here up to now, regardless of using CODEGEN4 instead CODEGEN1… the problem applying transport parameters adjusted in message STILL REMAINS in release 1517.
See this… snapshot of SoapUI, capturing SOAP call against my server… where simple SOAP service “Server_CustomAction” with one method “Execute” is implemented, just as echo… passing back incoming parameters:
As You can see, value of string parameter is interpreted as corrupted. Inspecting response as raw HTTP confirms, that “Content-Type” is set to “´text/html; charset=ISO-8859-1” instead of righ “text/xml;charset=UTF-8” value.
Let’s come on… see auto-generated invoker code for this call:
stage 1, RED - yep… parameters are applied from message to transport…
stage 2, GREEN - call is finished, response message is going to be assembled… and… RIGHT HERE, inside of __Message.InitializeResponseMessage, HTTP parameters for HTTP response (!) are adjusted and set. In releases before 1517, HTTP parameters were set directly to transport, inside message code, using SetHTTPInfo… it worked well. Now… just internal message variables are set, with no impact to transport.
stage 3, BLUE - this is the place, where transport parameters must be applied again… otherwise, HTTP transport parameters are set to default values.
just additional notice… as I observed, behavior is a bit different in dependence on component platform on which server is built. Using IndyHTTPServer, behavior is worst… “Content-Type” value is never set to transport, default value “text/html; charset=ISO-xxx” is always applied. This issue is - by my opinion - caused by implementation of IROHTTPTransport.GetContentType method in class uROIndyHTTPServer.TIndyHTTPTransport…
function TIndyHTTPTransport.GetContentType: string;
begin
result := fResponseInfo.ContentType;
end;
Im pretty sure, that value must be fetched from fRequestInfo instead of fResponseInfo.
In case of TROWinHTTPServer, TROSynapseHTTPServer, behavior is a bit better… HTTP parameters, applied at beginning of “_Invoker.Invoke_xxx” code using ApplyAttributes2_Transport are preserved during whole execution… but, if there is need to change/add some parameters inside response message preparation, those will be never applied to transport… and this is common conceptual behavior.