Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

WSDL import problem

145 views
Skip to first unread message

Anders Gustavsson

unread,
Mar 27, 2008, 1:26:30 PM3/27/08
to
Hi,

Doing my first real steps in the webservice world I have got a WSDL
document, that seems to confuse the Delphi importer (D2007 - december
update done). The document declares a base message that the Delphi
imports as an ERemotableException. The compiler then gets problem with
FSerializationOptions, that is not a member of ERemotableException, so
it seems, somewhere the interpretation should really be a TRemotable.

The WSDL file declares a few operations like this where a ErrorMessage
type is used for fault operation:


<wsdl:operation name="FK.TV.TestConnectivity.Test">
<wsdl:input message="tns:TestConnectivityRequestMessage"/>
<wsdl:output message="tns:TestConnectivityResponseMessage"/>
<wsdl:fault name="error" message="tns:ErrorMessage"/>
</wsdl:operation>

Going backwards, it seems this ErrorMessage inherits the general
messagetype, that thus has to be interpreted as an exception type?

Right now it seems ok to change the datatype of the base message in the
file, but I guess I will have problems later with faults. So what can I
do?

The service isn't in production yet, so I have very limited
possibilities to test it, but I need to be prepared.

If anyone is interested in trying this out, I would be happy to send
you the files.

/Anders

Jean-Marie Babet

unread,
Apr 1, 2008, 3:27:33 PM4/1/08
to
Hello,

Thanks for the post. Yes, I'd like to investigate. Please email me a copy of
the WSDL when time allows: bbabet @ codegear dot com.

Cheers,

Bruneau


Anders Gustavsson

unread,
Apr 1, 2008, 4:12:06 PM4/1/08
to
Files sent!

/Anders

Jean-Marie Babet

unread,
Apr 2, 2008, 3:39:00 PM4/2/08
to
Thank you for the files.

I've investigated and found the problem to be tied to some logic that
handles object hierarchies. The fix will require a little investigation
because the issue boils down to the fact that the Delphi SOAP runtime
detects fault (and header) types by the fact that they derive from
ERemotableException (and TSOAPHeader) but the XML schema also dictates its
own hierarchy. When these two cross, we have problems.

From the XML we see the following.

FK_TV_ErrorResponse_Test ->ErrorResponseType->ResponseType->TandenMessageTyp
e->(TRemotable).

The TRemotable above is implied. The issue is that the importer then detects
that FK_TV_ErrorResponse_Test is a fault type. It knows it must inject
ERemotableException in that hierarchy at some point. It does that at the
point that does not compromise what the XML dictates - which is that
FK_TV_ErrorResponse_Test is a TandenMessageType. But the latter is a base
type for non-fault types...

Clearly that's a tricky problem as there's no multiple inheritance...

I've often wanted to remove the TRemotable requirements from the SOAP
runtime. From a client point of view it's very doable. (Servers rely more on
TRemotable for cleanup [i.e. DataContext] and the virtual constructor). But
that's an involved change...

You're right that switching the base to TRemotable will cause problems for
faults later. It's a smaller problem though. Basically you won't get the
richer error/fault information granted by a fault type. Rather you'll get
the generic fields described by the standard (fault string, code and actor)
and you'll have to crack the details yourself instead of having the runtime
deserialize it into fields of a fault type. There will be no data loss but
very tedious work involving cracking the xml.

For now, I'll add logic to refrain from injecting ERemotableException if the
most-base type of the fault type is also the base type of non-fault types.

When time allows, would you mind opening a QC on this issue? I have it noted
down and will be giving it some thought. However, from a logistics point of
view it would be best that I have an actual customer report if I opt to go
to management and ask for some time to rework some of the hierarchy
assumptions made by the framework.

Cheers,

Bruneau

PS: The same issue occurs with headers. If the schema dictates a base type
for a header type, the importer will make that base type derive from
TSOAPHeader. You won't get the compiler error but there are undesirable
runtime ramifications if that basetype is base to non header types. :(

Anders Gustavsson

unread,
Apr 2, 2008, 5:11:51 PM4/2/08
to
A question more of the principles: Would it be possible (if I were the
designer of the WSDL) to change the design to split faults and
non-faults i the WSDL definition? Is there any "big" idea behind having
a common ancestor in the design?

/Anders

Anders Gustavsson

unread,
Apr 2, 2008, 4:59:32 PM4/2/08
to
Thanks for your answer. QC report 60318. Hope I explained enough - a
bit difficult to get the terms right being non-english-speaking.

Do you have any idea about the timeframe for a solution?

/Anders

Jean-Marie Babet

unread,
Apr 2, 2008, 5:40:18 PM4/2/08
to
Thank you for the report. And no worries about the description: while I
struggle with English also, I can manage to add some comments if necessary,
once someone in QA promotes the QC (I'm sending an email requesting that
right now).

Preventing the incorrect setting of ERemotableException is easy but that's
not a final solution. I can't quite assess the time as I have not yet
settled on the final solution. An overhaul of the system obviating the need
for TRemotable is ambitious. I'm cogitating a solution whereby the importer
would collapse the exception hierarchy in case of conflict.

CommonBaseType
Elements: Name, Id
|
|
----------------------
| |
ExceptionType NonFault-Type
Elements:Errors


In the case above, ExceptionType would derive from ERemotableException
directly but it would contain properties for all of its inherited elements:
Name, Id and Errors. This would allow fault serialization to work.

The drawback is that Delphi code won't be able to treat ExceptionType as a
CommonBaseType. However, I think that would be acceptable as it's a common
for Delphi object hierarchies to have Exception at the root of the exception
hierarchy and something like TObject, TPersistent or TComponent at the root
of the application object model. The importer would also emit a warning
about the hierarchy collapse.

If anyone has feedback or suggestions, please let me know. I'll investigate
this approach and report on my findings within a day or two.

Cheers,

Bruneau.


Jean-Marie Babet

unread,
Apr 2, 2008, 5:47:22 PM4/2/08
to
I suspect the common ancestor is a reflection of the inner workings of the
platform/framework backing that service. You could never expose such a WSDL
with Delphi because we have separate exception and remotable roots. However,
with Delphi, the issue could show up with headers.

The design probably allows code reuse - I'd guess.

From a schema/wsdl point of view, it's perfectly valid... hence I need a
solution.

Cheers,

Bruneau.

PS: About the headers, yes, I definitely plan to investigate this issue with
a Delphi server


Anders Gustavsson

unread,
Apr 8, 2008, 11:55:04 AM4/8/08
to
Jean-Marie Babet wrote:

> I'll investigate
> this approach and report on my findings within a day or two.

Any news?

/Anders

Jean-Marie Babet

unread,
Apr 13, 2008, 2:29:14 PM4/13/08
to
Hello,

Thank you for the reminder. The demands of another milestone on the
next-version product took its toll. I came in today to try to make up on my
newsgroup duties.

More later - hopefully!

Bruneau.


brun...@gmail.com

unread,
Apr 14, 2008, 2:39:22 AM4/14/08
to
Hello,

I started working on this today but had to leave before I had time to
post more... I'm planning to collapse Exception hierarchies. I'll post
more tomorrow.

Cheers,

Bruneau

Jean-Marie Babet

unread,
Apr 14, 2008, 5:46:46 PM4/14/08
to
Hello,

I have changed the importer to collapse exception types with base types.
With the update, TandenMessageType now derives from TRemotable:

//
************************************************************************ //
// XML : TandenMessageType, global, <complexType>
// Namespace : http://fk.se/SHS/xsd/tanden
//
************************************************************************ //
TandenMessageType = class(TRemotable)
private
Forganization_number: OrganizationIDType;
Forganization_number_Specified: boolean;
Frequest_id: RequestIDType;
procedure Setorganization_number(Index: Integer; const
AOrganizationIDType: OrganizationIDType);
function organization_number_Specified(Index: Integer): boolean;
public
destructor Destroy; override;
published
property organization_number: OrganizationIDType Index (IS_ATTR or
IS_OPTN) read Forganization_number write Setorganization_number stored
organization_number_Specified;
property request_id: RequestIDType Index (IS_ATTR) read
Frequest_id write Frequest_id;
end;


And the main fault type goes directly to ERemotableException:

//
************************************************************************ //
// XML : FK.TV.ErrorResponse.Test, global, <element>
// Namespace : http://fk.se/SHS/xsd/tanden
// Info : Fault
// Base Types: TandenMessageType, ResponseType, ErrorResponseType
//
************************************************************************ //
FK_TV_ErrorResponse_Test = class(ERemotableException)
private
Forganization_number: OrganizationIDType;
Forganization_number_Specified: boolean;
Frequest_id: RequestIDType;
Ferror: Array_Of_ErrorType;
procedure Setorganization_number(Index: Integer; const
AOrganizationIDType: OrganizationIDType);
function organization_number_Specified(Index: Integer): boolean;
public
destructor Destroy; override;
published
property organization_number: OrganizationIDType Index (IS_ATTR or
IS_OPTN) read Forganization_number write Setorganization_number stored
organization_number_Specified;
property request_id: RequestIDType Index (IS_ATTR) read
Frequest_id write Frequest_id;
property error: Array_Of_ErrorType Index (IS_UNBD) read
Ferror write Ferror;
end;

NOTE that I list the Base Types in the comments to indicate that this type
was collapsed.

I plan to commit the changes and have the importer run though the unit
tests. If nothing breaks I'll be happy to make this available to you.

More as soon as the changes have run through the tests.

Cheers,

Bruneau.

PS: I'll need to confirm whether any of our tests have a complex hierarchy
of faults to test this. Upon visual inspection, the changes are as I would
expect. However, I'd rather have something a littl more structured to test
this out.


Anders Gustavsson

unread,
Apr 15, 2008, 2:47:53 PM4/15/08
to
Jean-Marie Babet wrote:

> I plan to commit the changes and have the importer run though the unit
> tests. If nothing breaks I'll be happy to make this available to you.
>
> More as soon as the changes have run through the tests.

Very promising! Thank you!

/Anders

Jean-Marie Babet

unread,
Apr 16, 2008, 2:26:13 PM4/16/08
to
Hello,

Nothing new broke in the unit tests but I noticed that the collapsing is a
little too simplistic. My logic was to collapse any fault with base types.
Sometime this yields less than ideal results. Google's CampaignService
[https://adwords.google.com/api/adwords/v10/CampaignService?wsdl] is a good
example. The 'fault' type derives from 'ApiError'. The latter is not a base
to any other types. Before we generated:

//
************************************************************************ //
// XML : ApiException, global, <complexType>
// Namespace : https://adwords.google.com/api/adwords/v8
// Info : Fault
//
************************************************************************ //
ApiException = class(ERemotableException)
private
Fcode: Integer;
Ferrors: Array_Of_ApiError;
Finternal: Boolean;
Fmessage_: WideString;
Ftrigger: WideString;


public
destructor Destroy; override;
published

property code: Integer read Fcode write Fcode;
property errors: Array_Of_ApiError Index (IS_UNBD or IS_NLBL) read
Ferrors write Ferrors;
property internal: Boolean read Finternal write Finternal;
property message_: WideString Index (IS_NLBL) read Fmessage_
write Fmessage_;
property trigger: WideString Index (IS_NLBL) read Ftrigger
write Ftrigger;
end;

//
************************************************************************ //
// XML : fault, global, <element>
// Namespace : https://adwords.google.com/api/adwords/v8
// Info : Fault
//
************************************************************************ //
fault = class(ApiException)
private
published
end;

With my change we now generate:

//
************************************************************************ //
// XML : fault, global, <element>
// Namespace : https://adwords.google.com/api/adwords/v10
// Info : Fault
// Base Types: ApiException
//
************************************************************************ //
fault = class(ERemotableException)
private
Fcode: Integer;
Ferrors: Array_Of_ApiError;
Finternal: Boolean;
Fmessage_: WideString;
Ftrigger: WideString;


public
destructor Destroy; override;
published

property code: Integer read Fcode write Fcode;
property errors: Array_Of_ApiError Index (IS_UNBD or IS_NLBL) read
Ferrors write Ferrors;
property internal: Boolean read Finternal write Finternal;
property message_: WideString Index (IS_NLBL) read Fmessage_
write Fmessage_;
property trigger: WideString Index (IS_NLBL) read Ftrigger
write Ftrigger;
end;

//
************************************************************************ //
// XML : ApiException, global, <complexType>
// Namespace : https://adwords.google.com/api/adwords/v10
//
************************************************************************ //
ApiException = class(TRemotable)
private
Fcode: Integer;
Ferrors: Array_Of_ApiError;
Finternal: Boolean;
Fmessage_: WideString;
Ftrigger: WideString;


public
destructor Destroy; override;
published

property code: Integer read Fcode write Fcode;
property errors: Array_Of_ApiError Index (IS_UNBD or IS_NLBL) read
Ferrors write Ferrors;
property internal: Boolean read Finternal write Finternal;
property message_: WideString Index (IS_NLBL) read Fmessage_
write Fmessage_;
property trigger: WideString Index (IS_NLBL) read Ftrigger
write Ftrigger;
end;


The above is less than ideal as 'fault' and 'ApiException' are identical but
ApiException is no longer based on ERemotableException.

I think my changes can be released but I'd like to work on adding proper
detection of conflict rather than blindly flattening fault hierarchies when
time allows. I need to merge my changes to the D2007 tree because I have
some changes that target the upcoming version of Delphi (mainly, the
importer now uses scoped enumerations, something that only the new compiler
supports). I'll merge the changes this afternoon and should have something
ready to test this afternoon.

Cheers,

Bruneau.


Anders Gustavsson

unread,
Apr 23, 2008, 7:49:09 AM4/23/08
to
Hi,

How is the outcome of this? Will there be anything I can use with Delphi
2007 soon? Or can I use your ideas for manual changes? My timeframe is
closing in.

Regards,
Anders


"Jean-Marie Babet" <bba...@borland.com> skrev i meddelandet
news:480643cc$1...@newsgroups.borland.com...
> Hello,

Anders Gustavsson

unread,
Apr 23, 2008, 8:37:35 AM4/23/08
to
Actually, I now tried it manually myself:

Hope this is correct:
1. I broke the inheritance chain by inheriting the error message type from
ERemotableException instead of the common message type.
2. I copied all fields, properties and methods from the common message type
to this "new" error message class, implementing everything so to say in an
identical way a second time here.

Did I understand it correctly? It compiled at least :-)

/Anders


"Jean-Marie Babet" <bba...@borland.com> skrev i meddelandet
news:480643cc$1...@newsgroups.borland.com...

Jean-Marie Babet

unread,
Apr 23, 2008, 11:49:32 AM4/23/08
to
Hello,

Yes, you did this correctly. I assume you had already fixed the base-most
type that had been incorrectly derived from ERemotableException.

The reason for my delay is because since I was dealing with exception/fault,
I wanted to fix couple of more issues before posting an update. However, I
can email you an updated importer. If you'd like to proceed with this idea
just email me at "bbabet at codegear dot com" and I'll forward you a copy of
the updated WSDLImp.exe (alternatively, I can also give you the sources if
you're interested in rebuilding the importer yourself; with D2007 we started
shipping the source code to the command line importer).

Cheers,

Bruneau


0 new messages