cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Problem with webservice with nested objects in parameter

Former Member
0 Likes
2,061

Hello I'm using PB 12.1 6639 / Win 7 64


Today I have a Problem consuming a webservice using the .NET engine.


The corresponding WSDL and XSD definitions can be found here:


https://finanzonline.bmf.gv.at/fonws/ws/regKasseService.wsdl

https://finanzonline.bmf.gv.at/fonws/ws/regKasseWs.xsd

https://finanzonline.bmf.gv.at/fonws/ws/regKasse.xsd


I try to call the function rkdb and get an exception with the short error message 'Validation error'.


To get closer Information I used Fiddler to look at the produced Soap envelope. Please see the attached file for the SOAP-Message.


From this I can see that the SOAP-message does not contain the full parameter information that I pass to it.

Have a look at the code I use to call the webservice:

// *** Start of code ***

rkdbrequest l_request

rkdbresponse l_response

registrierung_kasse l_kasse

try l_request = create rkdbrequest

l_request.tid = "ws_account"

l_request.benid = "ws_user1

l_request.id = "xau390xkie234AAb"

l_request.erzwinge_asynchron = false

l_request.erzwinge_asynchronspecified = true

l_request.art_uebermittlung = 0

l_kasse = create registrierung_kasse

l_kasse.satznr = as_satznr

l_kasse.kundeninfo = "John Doe"

l_kasse.kassenidentifikationsnummer = "1"

l_kasse.anmerkung = "Cashbox 1"

l_kasse.benutzerschluessel = "xe45...66==" // AES-KEY (Base64-encoded)

l_request.ws_rkdb = create rkdb

l_request.ws_rkdb.ts_erstellung = datetime(today(), now())

l_request.ws_rkdb.items[1] = l_kasse

l_response = l_rkdbservice.rkdb(l_request) // WS-Call to rkdb()

catch (soapexception e1)

Messagebox("e1", "Fehler während der Ausführung der Webservice-Funktion '" + ls_function + "' (Soapexception: '" + e1.text + "')!")

exit

end try

// *** End of code ***

As you can see, the whole information is passed in one object (l_request), that holds an array of any's (named 'items') in the member 'l_request.ws_rkdb'. I assign the object 'l_kasse' to the first item of the items-array. Now the whole information of 'l_kasse' is missing in the soap message.

In debugmode I can see all objects created well and filled with the correct values. I have also attached an Image of the imported webservice types (nvo's).

I really hope someone can help me to find the mistake! Thank you in advance

Regards Martin

Accepted Solutions (0)

Answers (2)

Answers (2)

ricardojasso
Participant
0 Likes

I suspect that the problem is with the items property of type any. It should be of type registrierumg_kasse. This way the engine knows how to generate the proper xml statements. Maybe you can change it with the source code editor or modify the wsdl file before importing the definition. By the way, how is the items property defined in the wsdl file/source?

Former Member
0 Likes

If you're seeing property types of any it may indicate the whoever wrote the service is using platform specific data types (i.e., .Net data types).  You may need to communicate with the vendor of the service to request that they use platform agnostic data types for the service.

See mistake number one on the following:  Amol Kulkarni : Techno-Domain: Top 5 Web Service Mistakes…revisited

Former Member
0 Likes

The Background for the any datatype is the fact, that there are several different possible calls to the very same webservice function (i mean the any items[]-Array cannot only be filled with objects of type Registrierung_kasse, but also other types). The webservice then does different things, depending on the type.

My first idea on this is, to create the Parameter nvo's manually, one per object in item[] and define item[] not as any but of the appropriate type).

Then i can use the specific type to call the webservice.

I will try that, do you think this is the proper way?

I don't think, I can effect a modification by the vendor (government/fiscal) ...

Former Member
0 Likes

Hi Martin;

  If Bruce's hunch is correct and the ANY data type is indeed a .Net Class - there is nothing you can do about it in PB as it only supports standard C data types. Similarly, the same would be true if the WS author wrote the service in Java and passed back a Java Class as the any data type. Your PB application will be in the same predicament.

  It might be prudent to contact the web service author and get a better description of what data elements are actually being passed back from the WS. If indeed, they using a Have or .Net Class ... then another approach could be:

1) create a .net Assembly in VS to broker the interaction with the WS.

2) create a Java application and instantiate that from your PB application using the CreateJVM() method to broker communication to the WS.

3) create your own WS to broker the communication to the WS you need. Then call the broker WS from your PB application.

HTH

Regards ... Chris

Former Member
0 Likes

According to Ricardo's post, I tried to change the items[] datatype in the rkdb type

from:

string fastnr

string paket_nr

datetime ts_erstellung

any items[]

to:

string fastnr

string paket_nr

datetime ts_erstellung

registrierung_kasse items[]

On execution I got an exception saying 'Soapexception: The Definition of the method  signature in Web Service Proxy is wrong -- the data doesn't match the parameter'.

So definitely not a solution too.

In Chris and Bruce's post i'm not sure if I understand everything. I'm not sure which .NET datatype could be used in the webservice (must be a complex type?), since if you look at the WSDL and the used XSD-File, you can see that the type Registrierung_kasse just contains 5 strings.

I'm almost still thinking, that there is an error in the creation of the Soap-message.

Do you have another suggestions, how to find out or work around this.

Chris Workarounds are surely good ones, but are the last one to go for me, since there would be much more complexity in development and deploying ...

Former Member
0 Likes

I tried to create a client using the wsdl/xsd you posted and couldn't.  The request parameter isn't defined.

wsdl regKasseService.wsdl regKasse.xsd regKasseService.

wsdl

Microsoft (R) Web Services Description Language Utility

[Microsoft (R) .NET Framework, Version 2.0.50727.3038]

Copyright (C) Microsoft Corporation. All rights reserved.

Error: Unable to import binding 'rkdbServiceBinding' from namespace 'https://fin

anzonline.bmf.gv.at/rkdb'.

  - Unable to import operation 'rkdb'.

  - The element 'https://finanzonline.bmf.gv.at/rkdb:rkdbRequest' is missing.

If you would like more help, please type "wsdl /?".

It sounds like you're trying to overload the web service method.  SOAP doesn't support that.  About the best you can do is create a declaration for each anticipated use and use a different MessageName on each one.

Former Member
0 Likes

I tried to use the wsdl.exe Utility, and got the same error.

I can't read out much of the error, because I'm not familiar with this tool.

I think it does almost the same as the PB WS Proxy Import Wizard does.

Bruce, could you try to Import the wsdl in PB (see the attached file for the wsdl-Location i used).

By the way, thank you very much for your time.

Maybe you get a closer look of the imported types, and what the Problem could be ... Martin

ricardojasso
Participant
0 Likes

I downloaded the wsdl and xsd files and tried to create a ws proxy with PB12.5 using the ws proxy generator but with no success. Then I tried using the wsdl url address directly and suceeded. All function definitions and structures where imported the same as you show.

After analyzing the xsd documents I noticed that the element rkdb uses the choice indicator with several elements to choose from, one which is of type registrierung_kasse. This element is translated by the proxy generator to a variable named “ítem[]” of type any.

<xs:element name="rkdb">

  <xs:complexType>

    <xs:sequence>

      <xs:element minOccurs="0" ref="fastnr"/>

      <xs:element ref="paket_nr"/>

      <xs:element ref="ts_erstellung"/>

      <xs:choice>

        <xs:element maxOccurs="2000" ref="registrierung_se"/>

        <xs:element maxOccurs="4000" ref="registrierung_kasse"/>

        <xs:element maxOccurs="2000" ref="registrierung_ggs"/>

        <xs:element maxOccurs="4000" ref="ausfall_se"/>

        <xs:element maxOccurs="4000" ref="wiederinbetriebnahme_se"/>

        <xs:element maxOccurs="4000" ref="ausfall_kasse"/>

        <xs:element maxOccurs="4000" ref="wiederinbetriebnahme_kasse"/>

        <xs:element maxOccurs="4000" ref="ausfall_ggs"/>

        <xs:element maxOccurs="4000" ref="wiederinbetriebnahme_ggs"/>

        <xs:element ref="belegpruefung"/>

      </xs:choice>

    </xs:sequence>

  </xs:complexType>

</xs:element>

PB is recognizing the choice indicator and using it to create the structure with the “items[]” variable. The problem seems to be when it tries to create the xml elements in the request function after initializing the items[] variable. If the type is “any” then it should see what the actual type is at runtime and use the corresponding structure to properly create the xml request document. Apparently it is not doing so.


I’m not an expert on this but I believe the WS implementation in PB is not thorough enough as it cannot handle this particular situation which is a valid definition for a schema document. I experienced a similar situation in the past where I had to manually tweak the wsdl and xsd documents so PB could handle them. I was hoping that by just changing the items[] variable type to registrierung_kasse in the imported sctructure at least it’ll work for the example provided but apparently it doesn’t. It seems you'll need to change the wsdl file to make it work.

If you can download and use the wsdl and xsd files locally you could change its definition in such a way that it still works for at least one example and then work from there. For example you could strip the choice indicator and use one fixed type and try to see if it works:

<xs:element name="rkdb">

  <xs:complexType>

    <xs:sequence>

      <xs:element minOccurs="0" ref="fastnr"/>  

      <xs:element ref="paket_nr"/>

      <xs:element ref="ts_erstellung"/>

      <xs:element ref="registrierung_kasse"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>

This will still generate a valid xml request document according to the wsdl definition.


I hope this issue gets resolved in future version of PB now that Appeon has taken over.


Former Member
0 Likes

PowerBuilder uses the WSDL utility to create it's proxy.  I run it directly against wsdl files where there are problems because you get more detailed error information that way.

Former Member
0 Likes

I ran WSDL directly against that url.  The rkdbRequest class that was created was defined as:

public partial class rkdbRequest {

   

    private string tidField;

   

    private string benidField;

   

    private string idField;

   

    private art_uebermittlung art_uebermittlungField;

   

    private bool erzwinge_asynchronField;

   

    private bool erzwinge_asynchronFieldSpecified;

   

    private rkdb rkdbField;

The art_uebermittlung is an enumeration, so that shouldn't be a problem.  However, the rkdb class got defined as:

ublic partial class rkdb {

   

    private string fastnrField;

   

    private string paket_nrField;

   

    private System.DateTime ts_erstellungField;

   

    private object[] itemsField;

The ts_erstellungField field may be an issue, the itemsField field definitely is.

Former Member
0 Likes

I then ran SOAPUI against that wsdl location.  SOAPUI was able to better parse out what the request is supposed to be.

      <rkdb:rkdbRequest>

         <rkdb:tid>?</rkdb:tid>

         <rkdb:benid>?</rkdb:benid>

         <rkdb:id>?</rkdb:id>

         <rkdb:art_uebermittlung>?</rkdb:art_uebermittlung>

         <!--Optional:-->

         <rkdb:erzwinge_asynchron>?</rkdb:erzwinge_asynchron>

         <rkdb:rkdb>

            <!--Optional:-->

            <rkdb:fastnr>?</rkdb:fastnr>

            <rkdb:paket_nr>?</rkdb:paket_nr>

            <rkdb:ts_erstellung>?</rkdb:ts_erstellung>

            <!--You have a CHOICE of the next 10 items at this level-->

            <!--1 to 2000 repetitions:-->

            <rkdb:registrierung_se>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:art_se>?</rkdb:art_se>

               <rkdb:vda_id>?</rkdb:vda_id>

               <!--You have a CHOICE of the next 2 items at this level-->

               <rkdb:zertifikatsseriennummer hex="?">?</rkdb:zertifikatsseriennummer>

               <rkdb:zertifikat>?</rkdb:zertifikat>

            </rkdb:registrierung_se>

            <!--1 to 4000 repetitions:-->

            <rkdb:registrierung_kasse>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:kassenidentifikationsnummer>?</rkdb:kassenidentifikationsnummer>

               <!--Optional:-->

               <rkdb:anmerkung>?</rkdb:anmerkung>

               <rkdb:benutzerschluessel>?</rkdb:benutzerschluessel>

            </rkdb:registrierung_kasse>

            <!--1 to 2000 repetitions:-->

            <rkdb:registrierung_ggs>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:art_ob>?</rkdb:art_ob>

               <rkdb:ob>?</rkdb:ob>

               <!--Optional:-->

               <rkdb:zusatz_ob>?</rkdb:zusatz_ob>

               <rkdb:art_se_ggs>?</rkdb:art_se_ggs>

               <!--You have a CHOICE of the next 2 items at this level-->

               <rkdb:public_key>?</rkdb:public_key>

               <rkdb:zertifikat>?</rkdb:zertifikat>

            </rkdb:registrierung_ggs>

            <!--1 to 4000 repetitions:-->

            <rkdb:ausfall_se>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:zertifikatsseriennummer hex="?">?</rkdb:zertifikatsseriennummer>

               <!--You have a CHOICE of the next 2 items at this level-->

               <rkdb:ausfall>

                  <rkdb:begruendung>?</rkdb:begruendung>

                  <rkdb:beginn_ausfall>?</rkdb:beginn_ausfall>

               </rkdb:ausfall>

               <rkdb:ausserbetriebnahme>

                  <rkdb:begruendung>?</rkdb:begruendung>

               </rkdb:ausserbetriebnahme>

            </rkdb:ausfall_se>

            <!--1 to 4000 repetitions:-->

            <rkdb:wiederinbetriebnahme_se>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:zertifikatsseriennummer hex="?">?</rkdb:zertifikatsseriennummer>

               <rkdb:ende_ausfall>?</rkdb:ende_ausfall>

            </rkdb:wiederinbetriebnahme_se>

            <!--1 to 4000 repetitions:-->

            <rkdb:ausfall_kasse>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:kassenidentifikationsnummer>?</rkdb:kassenidentifikationsnummer>

               <!--You have a CHOICE of the next 2 items at this level-->

               <rkdb:ausfall>

                  <rkdb:begruendung>?</rkdb:begruendung>

                  <rkdb:beginn_ausfall>?</rkdb:beginn_ausfall>

               </rkdb:ausfall>

               <rkdb:ausserbetriebnahme>

                  <rkdb:begruendung>?</rkdb:begruendung>

               </rkdb:ausserbetriebnahme>

            </rkdb:ausfall_kasse>

            <!--1 to 4000 repetitions:-->

            <rkdb:wiederinbetriebnahme_kasse>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:kassenidentifikationsnummer>?</rkdb:kassenidentifikationsnummer>

               <rkdb:ende_ausfall>?</rkdb:ende_ausfall>

            </rkdb:wiederinbetriebnahme_kasse>

            <!--1 to 4000 repetitions:-->

            <rkdb:ausfall_ggs>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:art_ob>?</rkdb:art_ob>

               <rkdb:ob>?</rkdb:ob>

               <!--Optional:-->

               <rkdb:zusatz_ob>?</rkdb:zusatz_ob>

               <!--You have a CHOICE of the next 2 items at this level-->

               <rkdb:ausfall>

                  <rkdb:begruendung>?</rkdb:begruendung>

                  <rkdb:beginn_ausfall>?</rkdb:beginn_ausfall>

               </rkdb:ausfall>

               <rkdb:ausserbetriebnahme>

                  <rkdb:begruendung>?</rkdb:begruendung>

               </rkdb:ausserbetriebnahme>

            </rkdb:ausfall_ggs>

            <!--1 to 4000 repetitions:-->

            <rkdb:wiederinbetriebnahme_ggs>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:art_ob>?</rkdb:art_ob>

               <rkdb:ob>?</rkdb:ob>

               <!--Optional:-->

               <rkdb:zusatz_ob>?</rkdb:zusatz_ob>

               <rkdb:ende_ausfall>?</rkdb:ende_ausfall>

            </rkdb:wiederinbetriebnahme_ggs>

            <rkdb:belegpruefung>

               <rkdb:satznr>?</rkdb:satznr>

               <!--Optional:-->

               <rkdb:kundeninfo>?</rkdb:kundeninfo>

               <rkdb:beleg>?</rkdb:beleg>

            </rkdb:belegpruefung>

         </rkdb:rkdb>

      </rkdb:rkdbRequest>

The problem is the CHOICE options.  WSDL doesn't handle them well, which is why you ended up with an array of object.   See this thread for example that discusses the same problem that C# developers have:

xs:choice not imported correctly from WSDL

Former Member
0 Likes

Hi,

thanks for all that Input.

Seems that really the CHOICE-Element is a Problem.

What I now tried, is to follow Ricardo's Suggestion to store the wsdl and xsd-files locally and modify them.

In the regKasse.xsd I removed the Choice-Section and only let the one option 'registrierung_kasse' in the surrounding element 'rkdb'.

I then imported the wsdl in PB from the local files.

Looking at the imported objects i can see, that the rkdb type contains the specific type (Array of 'Registrierung_kasse'). - see attachment 1

When I call the Webservice and look at the produced SOAP-message with Fiddler, I can see that the data of the 'Registrierung_kasse' is included correct in the XML. - see attachment 2

Anyway I get an exception saying 'Validation error' - see attachment 3.

Does that mean, that any of the values sent to the webservice aren't OK? (I backchecked my test data to fit the XSD and cannot see any Errors). Is this a message that Comes from PB or already from the webservice itself?

I also ask myself, how to Import the wsdl file multiple times (one Import per manually changed type), since the Name of the imported objects will be always the same.

ricardojasso
Participant
0 Likes

Now that we know that substituting the any items[] element for the actual type generates the required XML request document you could try modifying the rkdb element by stripping only the choice indicator but adding a minOccurs="0" in each of the options elements so they can be optional:

<xs:element name="rkdb">

  <xs:complexType>

    <xs:sequence>

      <xs:element minOccurs="0" ref="fastnr"/>

      <xs:element ref="paket_nr"/>

      <xs:element ref="ts_erstellung"/>

      <xs:element minOccurs="0" maxOccurs="2000" ref="registrierung_se"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="registrierung_kasse"/>

      <xs:element minOccurs="0" maxOccurs="2000" ref="registrierung_ggs"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="ausfall_se"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="wiederinbetriebnahme_se"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="ausfall_kasse"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="wiederinbetriebnahme_kasse"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="ausfall_ggs"/>

      <xs:element minOccurs="0" maxOccurs="4000" ref="wiederinbetriebnahme_ggs"/>

      <xs:element minOccurs="0" ref="belegpruefung"/>

    </xs:sequence>

  </xs:complexType>

</xs:element>


But now you have to be careful not to initialize but one of the imported structure properties, the ones that where originally inside the Choice indicator, when filling the structure for the request function. This way only that element will be included in the request XML.


For the validation error message I believe it is a message that comes from the WS itself but you could try calling the web service directly from Fiddler using the generated request XML to verify this.


Former Member
0 Likes

Here's and update!

Looks like I've got a working solution.

1) I followed Ricardo's suggestion to eliminate the CHOICE Elements

     First I saved the WSDL and XSD-Files locally, then I changed the location of the XSD-files like this: 

     <xs:include schemaLocation="file://c:/tmp/webservice/regKasse.xsd"/>

     <xs:include schemaLocation="file://c:/tmp/webservice/verfification.xsd"/>

     Then I edited the regKasse.xsd to delete all the surrounding CHOICE-Elements and adding the attribute minOccurs="0" to each element of the      options     in the CHOICE.   

     Imported this in PB and called the webservice.

2) I found the reason of the 'Validation error'

     Fiddler was my friend here after I found out that the response of the post of the SOAP-message is wonderful displayed in detail (look at the      Inspectors tab bottom window and choose SyntaxView or XML.

    

     The response contained a detailed errormessage from the webservice. In fact it was an optional parameter 'fastner' which PB assigned to blank and      produced the SOAP-message . But only [0-9] is allowed according to XSD.

     I solved this by setting fastner to NULL and got my first positive response from the webservice.

    

So I'm happy to have at least a solution and again want to thank all the writers here!

The disadvantage of this is that I have to do this process all the time the Webservice gets changed by the vendor, but maybe PB can handle the CHOICE element in the future...

Kind Regards, Martin

ricardojasso
Participant
0 Likes

I think minOccurs="0" is the default value for that parameter so you might not need it. Also the web service request will eventually be validated by the production schema documents so the goal here is to be able to produce a xml document that will pass those validations. In short, what we are interested in is enabling PB to import the wsdl and xsd documents in such a way that it can produce a valid ws request so the modifications to these documents are for that purpose only.

I suspected the reason of the error message was the blank elements but was not sure. I had the same issue with a similar web service where in the schema files some elements were defined as optional so if they are not going to be filled then the whole elements should collapse which means they should not be included, not just opening and closing the element (e.g. <fastnr/> or <fastnr></fastnr>) but omitting them completely from the request.

Glad we could be of help!

Former Member
0 Likes

Hi Martin;

  Can you tell us ...

1) I assume that your using PB Classic vs PB.Net?

2) What version of MS-Windows are you using?

3) Have you tried your WS call using PB 12.6 (ie download a trial copy)?

4) Is this problem new? That is, did it work before & now just stop working?

5) I assume that your are using the .NET client in your PB Classic application (pbwsclient120.pbd)?

Regards ... Chris

Former Member
0 Likes

Hi Chris,

1,2) Yes, correct I use PB Classic on Windows 7 64bit.

3) I didn't try with PB 12.6 (don't have it on my PC), but anyway I have to get it to run in PB 12.1.

4) The webservice is new and my implementation of calling it is new, so it never worked before.

Do you have any idea?

Former Member
0 Likes

   Since you say your using the .Net implementation (which is great) and your TRY..CATCH is catching the "Validation Error" (which seems reasonable) condition ... my guess at this point is that there is a missing or invalid setting inside of L_Request or L_Kasse structures that the rkdb ( ) method is objecting to.

Are you using Fiddlier or the newer version Fiddiler2?

Former Member
0 Likes

I'm even using Fiddler 4 (latest).

Chris, thank you for that Input, but I don't think, that the values itself in l_kasse-object are the Problem, but that These values are not delivered to the webservice-function, because of they are missing in the SOAP-message (look at the attachment of the message).

In the XML - file you can see, that the members 'fastnr', 'paket_nr' and ts_'erstellung' are included under the rkdb-Tag, but the items-object is missing.

And of course, the Webservice Returns the Validation error, because it doesn't get the enough Input Parameters.

So I would say, the Problem is around PB / .Net-Engine generating the Soap-message. But i have no idea what could be wrong.

Regards Martin