Board index » delphi » Problem with optional parameters in a remote function

Problem with optional parameters in a remote function


2007-07-02 10:59:42 PM
delphi268
I have a Web service client written in Delphi 2007 calling to a Web
service written in Java. Several of the Web service functions have
optional parameters.
I am attempting to call these functions without passing values to these
parameters. If I pass empty strings I get an ERemoteException with
message 'java.lang.NullPointerException'. I get this same exception if I
pass StringToOleStr('') in the optional parameters. Passing null
generates a local exception 'Could not convert variable of type (Null)
into type (OleStr)'.
The documentation I have been provided depicts the optional parameters in
the SOAP request using empty elements in some cases (<web:value/>), and
start/end element pairs with no element text (i.e.,
<web:value></web:value>).
These parameters are not the right-most in the function, and there are
no versions of these functions that do not include these optional
parameters. Unfortunately, I have not been able to communicate with the
developers who created this Web service so far.
Is there another way to pass a null value of some type to the optional
parameters, or does the remote exception suggest that the service is not
handling the null values well?
Any suggestions will be greately appreciated.
 
 

Re:Problem with optional parameters in a remote function

Hello Cary,
The issue of optional parameters (i.e. <element minOccurs="0" ...>) has
been an issue that we started tackling in D2007. In most cases the
"parameter" in question is part of a complex type; as of Delphi 2007 the SOAP
runtime/importer handle this case by tagging the property as follows
(example from Amazon's Web Service):
CartModifyRequestItem = class(TRemotable)
private
FAction: CartModifyRequestItemAction;
FAction_Specified: boolean;
published
property Action: CartModifyRequestItemAction Index (IS_OPTN) read
FAction write SetAction stored Action_Specified;
end;
The runtime/importer overload the meaning of 'Index' and store the IS_OPTN
bit there. The runtime invokes the 'stored' function to check if the
property was set. The setter sets a flag when the property is assigned a
value.
The above works find as long as the optional element is not a 'direct'
parameter of the webservice. In cases where the optional element is a member
of a request or response wrapper element then one of the solution is to not
unwrap the service when importing the WSDL. The programming model is not as
nice when the wrapper elements are not unwrapped but it allows the importer
to flag optional elements to the runtime. So instead of, say, a method that
reads:
function Authenticate(UserName, Password: WideString; AuthToken:
WideString): boolean;
you'll have something that reads:
function Authenticate(Request: AuthenticateRequest):
AuthenticateResponse;
'AuthenticateRequest' would contain the optional members 'UserName',
'Password', 'AuthToken' and 'AuthenticateResponse' would contain the
'boolean' return value.
Some services doe allow 'nil' when a parameter (xsd:string, xsd:dateTime,
etc) is optional. For that case, you can instruct the importer to use the
TXS types. For example, instead of using a 'WideString' for an optional
string, the importer will uses a TXSString. TXSString is just a string
wrapper but being a class, you can pass in 'nil'.
Let me know if I can provide more information about the above. it is an issue
that I have been monitoring as it is evident with interacting with CodeGear's
own services (such as EventCentral).
Cheers,
Bruneau.
 

Re:Problem with optional parameters in a remote function

Quote
I have a Web service client written in Delphi 2007 calling to a Web
service written in Java. Several of the Web service functions have
optional parameters.

I am attempting to call these functions without passing values to these
parameters. If I pass empty strings I get an ERemoteException with
message 'java.lang.NullPointerException'. I get this same exception if I
pass StringToOleStr('') in the optional parameters. Passing null
generates a local exception 'Could not convert variable of type (Null)
into type (OleStr)'.

The documentation I have been provided depicts the optional parameters in
the SOAP request using empty elements in some cases (<web:value/>), and
start/end element pairs with no element text (i.e.,
<web:value></web:value>).

These parameters are not the right-most in the function, and there are
no versions of these functions that do not include these optional
parameters. Unfortunately, I have not been able to communicate with the
developers who created this Web service so far.

Is there another way to pass a null value of some type to the optional
parameters, or does the remote exception suggest that the service is not
handling the null values well?

Any suggestions will be greately appreciated.
Title: Consuming ASP.NET 2.0 Web Services in Delphi for Win32
Author: Bob Swart
Posted: 2/5/2007 10:04:56 AM (GMT+1)
Content: A couple of years ago I wrote an article Consuming C# Web Services with Delphi 7 Professional, and while the information in the article is still correct, it is no longer complete, because ASP.NET 2.0 changed the rules a little bit.
Even if you follow the examples exactly on creating the web service in C# and in creating the consuming application in Delphi for Win32, no matter what you try to echo, the result will always come back as 0 for numbers or as an empty string for strings.
This is due to the fact that the C# web service is deployed on an ASP.NET 2.0 machine (which changed some of the ways WSDL was published compared to .NET 1.1).
The problem is caused by the fact that any .NET Web Service is using the document|literal binding. With ASP.NET 1.x Web Services, this was specified using element, but with ASP.NET 2.0 Microsoft has changed that and now specifies the style in the operation input and output nodes instead of the binding element. The Delphi Win32 WSDL Importer is not able to recognise this, and as a result the generated import unit is using the (for Delphi default) binding type of RPC instead of the .NET document|literal binding type.
CodeGear is aware of the situation, and is already working on fixing the problem in the Win32 WSDL Importer. In the meantime, there is a workaround available that you can use, namely manually specifying the ioDocument as InvokeOptions for the SOAP interface type, as follows:
InvRegistry.RegisterInvokeOptions(TypeInfo(xxx), ioDocument);
Where xxx is the name of your SOAP interface type.
This line of code needs to be added to the initialization section of the generated Win32 import unit, and will make sure the parameters and result types are no longer empty when Win32 clients are talking to ASP.NET 2.0 Web Services.
BizTalk Utilities - Frustration free BizTalk Adapters
www.topxml.com/biztalkutilities