More problems with Nillable types

After the last issue with namespacing in the xml serializer
http://connect.remobjects.com/discussion/714/soap-nillable-types-in-remobjects-soap-server

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.

Regards,
Will.

Hi Will.

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}

Hi.

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?