I now have another problem. I can either have the correct WSDL generated or I can have working code, but not both…
In order to generate the correct WSDL I have to add the following to the RODL file
here is the correct WSDL.
If I leave out the Anonymous tag I get incorrect WSDL.
When I use the app with the Correct WSDL there is an error raised when a response is sent from server to client. The xml seems corrupt.
I have found that if I make a change to uROXMLSerializer then all appears to work correctly. I’m not entirely sure why but it seems that ‘Anonymous’ and ‘IsSimpletypeExtension’ are incompatible when ro is writing to a complex type.
procedure TROXMLSerializer.WriteStruct(const aName: string; const Ref; aClass: TClass;
ArrayElementId: integer);
var
obj : TROComplexType absolute Ref;
LevelRef: IXmlNode;
id : string;
lAnon, lNil: Boolean;
refnode : IXMLNode;
//xsiattr : IXMLNode;
lSaveNs, lName: String;
i: integer;
lAtributes: string;
lPrefix: string;
begin
LevelRef:=fNode;
if (aclass = XsDateTime) then begin
if (XsDateTime(Obj) <> nil) then
WriteXsDateTime(aName, XsDateTime(Obj), ArrayElementId)
else
AddNode(fNode, aName, ArrayElementId <> -1);
exit;
end;
try
IsAnonymous(TROComplexTypeClass(aClass), lAnon, lNil);
lanon := false ; <<<<<<<>>>>>>>>>>>>>>***********
lName := '';
lAtributes := fAttributes.CommaText;
With the fix, everything seems to work.
Please could you look into this. I’m now getting into hot water with a client because remobjects keeps throwing up silly bugs which are apparently the result of insufficient testing.
On a general note I’m getting very concerned about the apparent fall in quality of remobjects for delphi. I have not seen a release in quite a while where something is not broken or suffering from some trivial bug that was not picked up in testing. I have spent several days hunting around in the source code looking for bugs. As a paying customer this is not something that I should have to do.
You are right, wsdl generation was broken. But no need add “Anonymous” attribute, here is small fix for unit uRODLToWSDL:
procedure TRODLToWSDL.WriteStruct(const aLibrary: TRODLLibrary; aStruct: TRODLStruct);
var
i : integer;
lLax: Boolean;
lRet: TRODLStruct;
begin
if fExternalTypesAsReferences and (aStruct.Attributes.Values['ImportedFromUrl'] <> fTargetXSD) then exit;
if aStruct.Attributes.Values['Anonymous'] = '1' then exit;
Write(Format('', [Unprefix(aStruct.Name)]), 9);
WriteAnnotation(aStruct.Documentation, 9); {Giovanni}
if fUseDocument then begin
if aStruct.Ancestor <> '' then begin
write(Format('', [ExtSOAPDataType(aLibrary, aStruct.Ancestor)]), 9);
end;
end;
Write('', 12);
lLax := aStruct.Attributes.Values['lax'] = '1';
while Assigned(aStruct) do begin
for i := 0 to aStruct.Count-1 do
with aStruct.Items[i] do begin
lRet := aLibrary.FindStruct(DataType);
if (lRet <> nil) and (lRet.Count = 1) and ((lRet.Attributes.Values['Anonymous'] = '1') or (lRet.Attributes.Values['IsSimpleTypeExtension'] = '1')) then begin
if lRet.Attributes.Values['Nillable'] = '1' then
Write(Format('', [Unprefix(Name), ExtSOAPDataType(aLibrary, lRet.Items[0].DataType)]), 15)
else
Write(Format('', [Unprefix(Name), ExtSOAPDataType(aLibrary, lRet.Items[0].DataType)]), 15);
end else begin
Write(Format('', [Unprefix(Name), ExtSOAPDataType(aLibrary, DataType)]), 15);
end;
WriteAnnotation(Documentation, 15); {Giovanni}
Write('',15);
end;
if fUseDocument then break;
if aStruct.Ancestor <> '' then begin
aStruct := aLibrary.FindStruct(aStruct.Ancestor)
end
else begin
aStruct := nil;
end;
end;
if lLax then
Write('', 15);
Write('', 12);
if fUseDocument then begin
if aStruct.Ancestor <> '' then
write('', 9);
end;
Write('', 9);
end;
This happens because trick with nillable wrappers usually is used for RemObjects clients which work with third-party SOAP services. Actually In RemObjects SDK RODL nillable simple types are absent and need some magic with custom attributes to implement this.
Thanks,
I have applied the fix and it works fine. I did add an extra line of code because my SimpleTypeExtentions were showing up in the WSDL. Didn’t do any harm but they are unnecessary.
On a slightly different note it would be really good to see nillable types native in RO. As a lot of my work involves databases I’m frequently having to use suboptimal workarounds to support nillable values.
Regards,
Will.
procedure TRODLToWSDL.WriteStruct(const aLibrary: TRODLLibrary; aStruct: TRODLStruct);
var
i : integer;
lLax: Boolean;
lRet: TRODLStruct;
begin
if fExternalTypesAsReferences and (aStruct.Attributes.Values['ImportedFromUrl'] <> fTargetXSD) then exit;
if aStruct.Attributes.Values['Anonymous'] = '1' then exit;
if aStruct.Attributes.Values['IsSimpleTypeExtension'] = '1' then exit; << ADD THIS
Write(Format('', [Unprefix(aStruct.Name)]), 9);
WriteAnnotation(aStruct.Documentation, 9); {Giovanni}
You are right nillable wrappers no need to expose in wsdl, we will include this fix in the next release.
About “native” implementation of nillable simple types, I can’t imagine anything instead of using classes. Of course is not optimal to create class for some simple value but what can be alternative?