Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/SOAP/Components    [ Add a report in this area ]  
Report #:  104511   Status: Closed
[MacOS] TRemotable.ObjectToSoap calls throws exception
Project:  Delphi Build #:  16.0.4429.46931
Version:    16.4 Submitted By:   etax DWS
Report Type:  Crash / Data loss / Total failure Date Reported:  3/29/2012 6:41:09 PM
Severity:    Critical / Show Stopper Last Updated: 8/19/2012 8:52:01 PM
Platform:    All Mac platforms Internal Tracking #:   27609
Resolution: Test Case Error (Resolution Comments) Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
Target Platform - Mac OS X

The TRemotable.ObjectToSoap calls throws the following exception:
ENamespace_Err with message 'Namespace Error.'

The class we're converting has nothing special, just a class inheriting from TRemotable.

This code works perfectly for Windows.

Steps to Reproduce:
1. Create a class inherting from TRemotable

  TMyRemotable = class(TRemotable)
  private
    FFieldDouble: Double;
    FFieldBoolean: Boolean;
  published
    property FieldDouble: Double read FFieldDouble write FFieldDouble;
    property FieldBoolean: Boolean read FFieldBoolean write FFieldBoolean;
  end;

2. Instantiate and then serialize the class into XML

var
  converter: TOPToSoapDomConvert;
  Xdoc: IXMLDocument;
  Root: IXmlNode;
  Namespace, TypeName, RefId: String;
  IsScalar: Boolean;
  AObject : TMyRemotable;
begin
  AObject := TMyRemotable.Create;
  AObject.FieldDouble :=1;
  AObject.FieldBoolean := true;

  converter := TOPToSoapDomConvert.Create(nil);
  converter.Options := [TSOAPConvertOption.soTryAllSchema, TSOAPConvertOption.soCacheMimeResponse, TSOAPConvertOption.soUTF8EncodeXML];
  try
    Xdoc := NewXMLDocument();
    Root := Xdoc.AddChild('Root');

    RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName, IsScalar);
    AObject.ObjectToSOAP(Root, Root, converter, TypeName, Namespace, '', [], RefId);
  finally
    FreeAndNil(converter);
  end;

end
Workarounds
None
Attachment
XML.zip
Comments

Tomohiro Takahashi at 3/29/2012 7:19:57 PM -
I deleted QC#104512. Please do not post same repots.

etax DWS at 4/3/2012 7:18:41 PM -
Sorry about the double post, I was getting the hang of QC Windows Client.

Anyways, I've attached a sample project, which basically contains the code I described in Steps.  

Tomohiro Takahashi at 3/29/2012 7:21:14 PM -
Could you please attach sample project(s) to reproduce your issue?
Please use Windows Native QC Client to attach a .zip file to this repor. The standalone client comes with Delphi.

etax DWS at 4/3/2012 8:02:51 PM -
If it helps, the error is thrown in the Xml.adomxmldom, in the following method:

        procedure Tox4DOMNode.CheckNamespaceDeclaration(xdnChild: TDomNode);

at the following lines:

        if ChildPrefix = '' then
          // Attributes cannot have default namespace.
          raise ENamespace_Err.Create('Namespace error.');

etax DWS at 4/10/2012 6:35:16 PM -
Hi,

Could I get an update on where you are up to with the resolution of this defect and scheduling information?

Many thanks,

Ben

Jean-Marie Babet at 5/3/2012 7:37:41 PM -
Hello,

I took a peek at this today and it's unfortunately a testcase error. Let me explain.

For historical reasons, the SOAP Object Converter defaults to "Section-5" encoding. That's the old standard that SOAP initially used, that was XML format but not XML encoding. IOW, the generated XML did not follow the rules of a schema but rather some custom rules on how to serialize data described in Section 5 of the SOAP spec (hence the name "Section-5" encoding). You can find quite a bit about "Section-5" by running a google search for "Section-5" Encoding. For example:

http://www.thearchitect.co.uk/weblog/archives/2002/11/the_death_of_so.html
http://msdn.microsoft.com/en-us/library/ms995710.aspx

And of course the spec itself:

http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383512

Even though the testcase you provided works in Windows, a quick peek at the generated XML will show that it's invalid XML (also known as Literal) encoding:

{code}
<?xml version="1.0"?>
<Root xmlns:NS1="urn:TestConsole" xmlns:NS2="http://www.w3.org/2001/XMLSchema">
  <NS1:TMyRemotable type="NS1:TMyRemotable">
    <FieldDouble type="NS2:double">1</FieldDouble>
    <FieldBoolean type="NS2:boolean">true</FieldBoolean>
  </NS1:TMyRemotable>
</Root>
{code}

Specifically, the type="NS2:double" and type="NS2:boolean" attributes are incorrecct/wrong.

The reason is that we are emitting using Section-5 encoding rules but have not created a document for Section-5. Your goal, I assume, is to generate an XML representation of the object, using XML/Literal encoding. To do that you must enable the 'soDocument' option. Here's the comment in the source for that option:

// Soap.OPConvert.pas
soDocument,  { Don't use sect5 Encoding; use Literal/XML encoding }

Once you do that, the Windows XML changes to this:

{code}
<?xml version="1.0"?>
<Root>
  <NS1:TMyRemotable xmlns:NS1="urn:TestConsole">
    <FieldDouble>1</FieldDouble>
    <FieldBoolean>true</FieldBoolean>
  </NS1:TMyRemotable>
</Root>
{code}

... which looks better. And when switching to OSX, we get the same output and no Exception thrown.

Below is the console testcase that I used to print the XML generated. It includes the addition of the required "TSOAPConvertOption.soDocument".

If your goal was to generate the old style Section-5 style packet, you'll need to imitate the way the SOAP logic creates the Envelope node. I can expand if necessary.

Cheers,

Bruneau


program TestConsole;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Soap.InvokeRegistry,
  OPConvert,
  OPToSOAPDomConv,
  XmlIntf,
{$IFDEF WIN32}
  ActiveX,
{$ENDIF}
  XMLDoc;

type
  TMyRemotable = class(TRemotable)
  private
    FFieldDouble: Double;
    FFieldBoolean: Boolean;
  published
    property FieldDouble: Double read FFieldDouble write FFieldDouble;
    property FieldBoolean: Boolean read FFieldBoolean write FFieldBoolean;
  end;


procedure Test;
var
  converter: TOPToSoapDomConvert;
  Xdoc: IXMLDocument;
  Root: IXmlNode;
  Namespace, TypeName, RefId: String;
  IsScalar: Boolean;
  AObject : TMyRemotable;
begin
  AObject := TMyRemotable.Create;
  AObject.FieldDouble :=1;
  AObject.FieldBoolean := true;

  converter := TOPToSoapDomConvert.Create(nil);
  converter.Options := [TSOAPConvertOption.soTryAllSchema,
                        TSOAPConvertOption.soCacheMimeResponse,
                        TSOAPConvertOption.soUTF8EncodeXML,
                        TSOAPConvertOption.soDocument];
  try
    Xdoc := NewXMLDocument();
    Root := Xdoc.AddChild('Root');

    RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName, IsScalar);
    AObject.ObjectToSOAP(Root, Root, converter, TypeName, Namespace, '', [], RefId);
    Write(FormatXMLData(Xdoc.XML.Text));
  finally
    FreeAndNil(converter);
  end;
end;

begin
{$IFDEF WIN32}
  CoInitialize(0);
  try
{$ENDIF}
    try
      Test;
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
{$IFDEF WIN32}
  finally
    CoUninitialize;
  end;
{$ENDIF}
end.



etax DWS at 5/7/2012 6:20:01 PM -
I've tried the suggestion and it partially works.  When one of object’s property is set to Nil, the ObjectToSoap method still fails with the namespace exception.

Here is the stack trace, if it helps:

:00016654 @DbgExcNotify
:000167f3 NotifyReRaise + $13
Xml.adomxmldom.Tox4DOMNode.CheckNamespaceDeclaration($DB76C0)
Xml.adomxmldom.Tox4DOMElement.setAttributeNS('http://www.w3.org/2001/XMLSchema-instance','nil','true')
:002fd9be TXMLNode.SetAttributeNS + $132
:003d3e0c CreateNilNode + $88
:003d50bb TSOAPDomConv.ObjInstanceToSOAP + $A8F
:003e1be1 TRemotable.ObjectToSOAP + $7D
Unit6.TForm6.Button1Click($4270400)
:0024a8eb TControl.Click + $33
:000ee90e TCustomButton.MouseUp + $AA
:0025f5ed TCommonCustomForm.MouseUp + $BD
:001ed8b9 TFMXViewBase.mouseUp + $13D
:001603e6 DispatchToDelphi + $26
:905608af ; AppKit
:904f86ff ; AppKit
:90489c82 ; AppKit
:001605af DispatchToImport + $37
:001eb13f TPlatformCocoa.Run + $CF
XML.XML

Jean-Marie Babet at 5/17/2012 12:17:31 PM -
I'm sorry to report but that's another test-case error. The converter generates XML assuming it's writing to a SOAP Envelope. The envelope declares some basic namespace. You are bypassing the TSoapEnvelope class. That's OK, but you must make sure that you declare the same namespaces the converter assumes. To fix the code submitted, you could do something like this:

{code}
procedure DeclareDefaultNS(Root: IXMLNode; Options: TSOAPConvertOptions);
begin
  Root.DeclareNamespace(SXMLSchemaNameSpacePre, XMLSchemaNameSpace);
  Root.DeclareNamespace(SXMLSchemaInstNameSpace99Pre, XMLSchemaInstNameSpace);
end;


procedure Test;
var
  converter: TOPToSoapDomConvert;
  Xdoc: IXMLDocument;
  Root: IXmlNode;
  Namespace, TypeName, RefId: String;
  IsScalar: Boolean;
  AObject : TMyRemotable;
begin
  AObject := TMyRemotable.Create;
  AObject.FieldDouble :=1;
  AObject.FieldBoolean := true;
  AObject.SubRemotable := nil;

  converter := TOPToSoapDomConvert.Create(nil);
  converter.Options := [TSOAPConvertOption.soTryAllSchema,
                        TSOAPConvertOption.soCacheMimeResponse,
                        TSOAPConvertOption.soUTF8EncodeXML,
                        TSOAPConvertOption.soDocument];
  try
    Xdoc := NewXMLDocument();
    Root := Xdoc.AddChild('Root');
    DeclareDefaultNS(Root, converter.Options);

    RemClassRegistry.ClassToURI(AObject.ClassType, Namespace, TypeName, IsScalar);
    AObject.ObjectToSOAP(Root, Root, converter, TypeName, Namespace, '', [], RefId);
    Write(FormatXMLData(Xdoc.XML.Text));
  finally
    FreeAndNil(converter);
  end;
end;
{code}

The above should generate the following:

{code}
<?xml version="1.0"?>
<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <NS1:TMyRemotable xmlns:NS1="urn:TestConsole">
    <FieldDouble>1</FieldDouble>
    <FieldBoolean>true</FieldBoolean>
    <SubRemotable xsi:nil="true"/>
  </NS1:TMyRemotable>
</Root>
{code}

Tomohiro Takahashi at 5/7/2012 7:04:14 PM -
Could you please put new QC report about your case?

Tomohiro Takahashi at 5/3/2012 7:48:32 PM -
Babet-san
> I took a peek at this today and it's unfortunately a testcase error. Let me explain.
Sould I close this report as 'Test Case Error'?

Tomohiro Takahashi at 4/11/2012 12:55:21 PM -
As you know, QualityCentral is not technical support service.
So, if you need more intensive support adn official reply from Embarcadero, please contact technical support. Sorry for the inconvenience.
http://support.embarcadero.com/

Server Response from: ETNACODE01