Skip to Content
Author's profile photo Former Member

Consuming a Web Service with Powerbuilder 12.5 Classic

“Preliminary” steps in Powerbuilder

This section describes the steps to follow in order to invoke a Web Service.

  • Create a new PBL to hold the objects that will be created, especially if you just want to “play around”. In this example it will be SAPDS.PBL.
  • Create a new object: on the “Project” tab, select “Web Service Proxy Wizard”
    /wp-content/uploads/2015/04/image1_698519.png
  • Check the “Use .Net Engine” checkbox, click Next.
    /wp-content/uploads/2015/04/imag2_698521.png
  • Indicate the WSDL file URL (see above) and the Assembly Name (e.g. SAPDataServices_Server.dll), then click NEXT.
    Note that the Windows SDK for .Net Framework 4.0 must be installed on your system. If that is not the case, you have to do that first:
    /wp-content/uploads/2015/04/image3_698522.png
    /wp-content/uploads/2015/04/image4_698523.png
    See the Troubleshooting section further down, if you have issues with this step.
  • Select a Service, e.g. “WebService.connection_Operations, click Next
    /wp-content/uploads/2015/04/image5_698524.png
  • In the next step, you may set the prefix for the proxy.
    The wizard says that by default, it is the portname for each port, but you may leave it empty. In the near future we may decide to set up a naming convention rule for this step.
  • Specify the project name and the library where it will be stored:
  • You may verify your settings on the “Ready to Create Proxy” window before hitting Finish:
    Note that the documentation states that “the assembly is generated in the current target directory”.


  • After that, the proxy should be created. Clicking on the “Services…” button opens a window showing the services and structures.

  • In the PBL, right-click the generated proxy (e.g. p_ws_sapds) and select “Deploy” to generate the Services and Structures in the PBL:
    /wp-content/uploads/2015/04/image6_698525.png
    Invoking Web services through SOAP requires serialization and deserialization of datatypes, and the building and parsing of XML-based SOAP messages. The pbwsclient125.pbx file contains objects for the .NET Web service engine that enable you to perform these tasks without extensive knowledge of the SOAP specification and schema, the XML Schema specification, or the WSDL specification and schema. You can use these objects after you import the extension file into a PowerBuilder Web service application.
  • At this point it might be necessary to import a Powerbuilder extension file that should be located in “C:\Program Files (x86)\Sybase\Shared\pbwsclient125.pbx“.
    Right-click the PBL, select “Import PB Extension…” and select the PB extension file indicated above.
    /wp-content/uploads/2015/04/image7_698526.png
    If you’re getting an error message saying that the file is not a valid dll or pbx file you may have an old version of the file “libeay32.dll” loaded.
    /wp-content/uploads/2015/04/image8_698527.png

    In my case, through a search with Process Monitor, it appeared that the file libeay32.dll was loaded from C:\Windows\SysWOW64 – but it was a very old version (from 2005).
    After deleting it, the import process was successful (after the 2nd try) and the following NVOs were generated:
    /wp-content/uploads/2015/04/image9_698528.png

    These NVOs are needed, so there’s no point in continuing if this step fails!

    The above are necessary “preliminary” steps, next we’ll look at the Powerbuilder code needed to actually invoke a Web Service.

Powerbuilder code to invoke a Web Service

In order to verify the above steps, i.e. to test the Web Service(s), I created a function (f_ws_logon) in a new NVO (n_sap_ds_func) that is invoked through a button click in a very basic window (w_sapds_main).
These objects can be found in the attached PBL (the code was created just to prove the concept, so no need to discuss the naming nor code quality).

sapds.pbl

In the next section, the code is presented and some additional information given.

Variable declarations, object instantiation

connection_operations                       lnv_conn

session                                     lnv_ws_session

logonrequest                                lnv_log_req

runbatchjobrequest                          lnv_runbatchjobreq

batchjobresponse                            lnv_batchjobresp

batch_job_admin                             lnv_batch_jobadm

batch_jobs                                  lnv_batch_jobs

soapconnection                              lnv_soap_conn

soapexception                               lnv_soap_exc

runbatchjobrequestvariable                  lnv_runbatchreqvar

job_webservice_call_poc_globalvariables     lnv_globvar

integer                                     li_val, li_val2, li_val3

boolean                                     lb_sess

//

lnv_batch_jobadm = CREATE batch_job_admin

lnv_batch_jobs = CREATE batch_jobs

lnv_log_req = CREATE logonrequest

lnv_runbatchjobreq_HED = CREATE runbatchjobrequest

lnv_runbatchjobreq_DDO = CREATE runbatchjobrequest

lnv_batchjobresp_HED = CREATE batchjobresponse

lnv_batchjobresp_DDO = CREATE batchjobresponse

lnv_globvar = CREATE job_webservice_call_poc_globalvariables

Next, set some values and the Web Service parameters

Set values and Web Service parameters

// set values

lnv_log_req.username = '!@$%'

lnv_log_req.password = '@!%$#!%$^#@'

lnv_log_req.cms_authentication = 0              // secEnterprise = 0, secLDAP = 1, secWinAD = 2, secSAPR3 = 3,

lnv_log_req.cms_system = 'srv01'

// sample Web Service

lnv_runbatchjobreq_DDO.jobname = "JOB_WEBSERVICE_CALL"

lnv_runbatchjobreq_DDO.reponame = "BOXI_DS4_LOCAL"

lnv_globvar.g_countermax = "2000000"          // at test revealed that the web services are apparently executed asynchronously

Finally, the Web Service is called.

As noted in the comment above, the Web Service is apparently called asynchronously (the fact that there is a “cancelasync” method further supports this assumption).

Note the comments in the code, as they provide some important additional information!

Finally, the Web Service is called.

Invoke Web Service and handle results, resp. errors

As noted in the comment above, the Web Service is apparently called asynchronously (the fact that there is a “cancelasync” method further supports this assumption).

/ call the Web Service

TRY

    li_val = lnv_soap_conn.createinstance(lnv_conn, "connection_operations")

    li_val2 = lnv_soap_conn.createinstance(lnv_batch_jobadm, "batch_job_admin")     

    li_val3 = lnv_soap_conn.createinstance(lnv_batch_jobs, "batch_jobs")         

    IF li_val = 0 THEN                              // 0 means OK (in this example li_val, li_val2 and li_val3 all returned 0)

        // OK

        lnv_ws_session = lnv_conn.logon(lnv_log_req)                                    // log on to get session

        lb_sess = lnv_batch_jobadm.setsessionvalue(lnv_ws_session)                      // set the session value for the next call(s)

        lnv_batchjobresp = lnv_batch_jobadm.run_batch_job(lnv_runbatchjobreq) 

      

        // display error message

        IF lnv_batchjobresp.pid = -1 THEN

            Messagebox("Web Service error", lnv_batchjobresp_HED.errormessage + ', repository name: ' + lnv_batchjobresp_HED.reponame)

        END IF   

    ELSE

        // Not OK

        // (add appropriate error handling)

    END IF

CATCH (runtimeerror exc)

    MessageBox ("WS Runtime Error", exc.text)

FINALLY

//      Messagebox("try... catch", "finally clause", Information!, OK!)

END TRY

The remaining code doesn’t add much (destroying the created objects), so it’s been left out for better lisibility.

Below we have 2 examples of responses with and without ErrorMessage

/wp-content/uploads/2015/04/image10_698529.png

/wp-content/uploads/2015/04/image11_698530.png

The LOGON call was obviously successful as it returned the needed session ID.

Session ID

If the session Id is not provided when calling an SAP Data Service Web Service, the following error message will be displayed (see the CATCH clause):

/wp-content/uploads/2015/04/image12_698537.png

Debugging a Web Service

I’ve been using SOAPUI or Fiddler.

Troubleshooting

Installation of the “Windows SDK for Windows 7 and .NET Framework 4” failed on my system for no apparent reason:

/wp-content/uploads/2015/04/image13_698538.png

/wp-content/uploads/2015/04/image14_698539.png

/wp-content/uploads/2015/04/image15_698543.png

The indicated file “Samples\Setup\HTML\ConfigDetails.htm” was not available. In fact, nothing remained after the failed installation, apparently the installation process deleted all copied/installed files.

The solution was to install the freely available “Microsoft Visual Studio 2010 Express”, because that installs the needed .NET framework.

Assigned Tags

      22 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Thank you Rolf Andre Klaedtke for the help

      Author's profile photo Former Member
      Former Member

      What a surprise to find "my" article on the SAP Developer network...

       

      I'd recommend at least to remove/correct the link to the Glencore WIKI in the Section "Debugging a Web Service using Fiddler"...

      Author's profile photo Former Member
      Former Member

      Well explained !! Thanks Nuno Madeira. I had the problem .Net SDK that was not detected by PB. I installed the latest version of the SDK on my windows 7 (windows 8 -> SDK 4.5) and still PB complained. It was looking specifically for .Net SDK 4.0 for windows 7. But I could install the .Net 4.0 SDK as I got the same error as indicated in your email. After much search I found a comment on SCN about un-installing the exisitng visual C++ compiler (one installed with .net 3.5) before running the .net SDK 4.0 installation for Windows 7. This solved the problem.

      Author's profile photo Former Member
      Former Member

      Hi  Nuno,

      Could you please share the pbl you referring to, and the wsdl if possible. My service's WSDL employs ws security, but does not generate session, header etc. objects, but only service methods.

      I tried in PB. NET as well, creating WS client, but the project fails to generate proxy, returning exception "Object reference not set to an instance of an object"

       

      PB12.6 4058

       

      Thanks

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Hi Arthur,

      Did you do "In the PBL, right-click the generated proxy (e.g. p_ws_sapds) and select "Deploy" to generate the Services and Structures in the PBL" step ?


      Can you try to debug your service with soapui tool ?

      Do you see the connection/Session objects ?

      /wp-content/uploads/2015/06/ws_testing_723885.png

      Nuno

      Author's profile photo Former Member
      Former Member

      Hi, Nuno

      I most certainly did generate the proxy objects from the WSDL i need to implement the service for. The issue is my WSDL is not for salesforce, and does not explicitly define objects and methods to address the header of the SOAP envelope. I got my hands on a sample Salesforce WSDL, and created a proxy for it. That one does indeed generate header nvo and method to change it. Now I need to come up with the way to sneak in these definitions in the WSDL I need to implement  . anyway I was hoping the example -generated objects would help me to understand how the header is represented in Soapconnection's proxy.

       

      Thanks

      Author's profile photo Former Member
      Former Member

      Hi ,

       

      I consume a web service which works fine on some pc's , but on one of my customer's pc

      I got an error : Dot net engine can not be start.

       

      Any idea why ?

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Check the .NET version on that PC. IF the SDK (Windows SDK for Windows 7 and .NET Framework 4) fails to install, Try to install Microsoft Visual Studio 2010 Express which should install the right .NET version.

      Author's profile photo Former Member
      Former Member

      Hi,

      I'm using PB 12.5 Classic and I have to consume the web service (https://www.sunat.gob.pe:443/ol-ti-itcpgem-beta/billService?wsdl), the problem is that I have to connect with that services with the next Soap:

       

      <endpoint address="https://www.sunat.gob.pe:443/ol-ti-itcpgem-beta/billService"

                      binding="basicHttpBinding" bindingConfiguration="BillServicePortBinding"

                      contract="DocumentosElectronicoSunat.billService" name="BillServicePort" >

                    <headers>

                      <wsse:Security mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">

                        <wsse:UsernameToken Id="ABC-123">

                          <wsse:Username>MODDATOS</wsse:Username>

                          <wsse:Password>moddatos</wsse:Password>

                        </wsse:UsernameToken>

                      </wsse:Security>

                    </headers>

                  </endpoint>

      is it possible to do in PB12.5 Classic ? how I could send the variable "UsernameToken" to the webservice?

      help me please

      Thank you

      Author's profile photo Former Member
      Former Member

      Hi,

       

      You should able to use OLEObject.

       

      1. Create you request and save it is a variable say ls_your_request)

      2. Create an instance like: OLEObject PBObject

      3. PBObject.ConnectToNewObject("Msxml2.XMLHTTP.4.0")

      4. PBObject.OPEN ("POST" , ls_your_url,FALSE)

      5.  PBObject.send(ls_your_request_text)

      6. Capture your response

       

      Thanks

      Ramendra

      Author's profile photo Bruce Armstrong
      Bruce Armstrong

      Your service has WS-Security headers.  The web service client in PowerBuilder classic can't support that as it's based on the older ASP web services technology.

       

      You could create a client using PowerBuilder.Net or Visual Studio.Net that uses WCF, which does support WS-Secuirty.  You'd then have to access that client through a COM Callable Wrapper.  I demonstrate the technique here:

       

      PowerBuilder.TV - Creation and Consumption of Web Services with PowerBuilder

       

      Alternatively, you could create a web service in PowerBuilder.Net or Visual Studio.Net that uses a WCF client to talk to that service and then exposes a non WS-Security enabled web service for PowerBuilder Classic to support.

      Author's profile photo Former Member
      Former Member

      Hi Bruce

       

      The above steps are from real life example and in production.

       

      It's in PB11.5 but I don't think it make any difference because it's using MSXMLHTTP request.

       

      I may not able to share the complete source code but if someone can share a webservice with the request header, I should able to create an application.

       

      Thanks

      Ramendra

      Author's profile photo Bruce Armstrong
      Bruce Armstrong

      You're calling a web service that implements WS-Security using OLE automation?

      Author's profile photo Former Member
      Former Member

      Hi Bruce

       

      Do to my limited knowledge about the type of web services, I am not very sure if that has WS-Security but my header looks like below :

       

      SOAP-ENV:Envelope xmlns:SOAP-ENV='http://www.w3.org/2003/05/soap-envelope' xmlns:

       

      Is this means it's don't have WS-Security?

       

      Thanks

      Ramendra

      Author's profile photo Bruce Armstrong
      Bruce Armstrong

      No.  WS-Security headers were included in the post you responded to:

       

                     <wsse:Security mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">

                        <wsse:UsernameToken Id="ABC-123">

                          <wsse:Username>MODDATOS</wsse:Username>

                          <wsse:Password>moddatos</wsse:Password>

                        </wsse:UsernameToken>

                      </wsse:Security>

      Author's profile photo Former Member
      Former Member

      Thanks Bruce for correcting my mistake and sharing the info..

       

      Regards

      Ramendra

      Author's profile photo Former Member
      Former Member

      Thanks Bruce and Ramendra for sharing your knowledge.

      I could connect with this code in a test server, but in other test server (there is two test server)I can't.

       

      SoapConnection conn // Define SoapConnection 

      billservice proxy_obj // Declare proxy 

       

      conn = create SoapConnection //Instantiated connection  

      lLog = conn.SetOptions("UserID='20116320682MODDATOS',Password='MODDATOS'")

      rVal = Conn.CreateInstance(proxy_obj, "billservice") 

       

      Bruce I'll do your suggestion.

      Author's profile photo Former Member
      Former Member

      Hi All, How can help me for problem with Android, please!

      1)  I have write Android app connect to web Service Powerbuilder 12.5 classic. I created function   get_list_name(string name_for_search), method return string datatype.

      But when I call method and addProperty to request (I used ksoap2 library for Android) then response return NULL.

      I have test web service  in asp.net, jsp/servlet its run. But with powerbuilder then problem.

      2) How to can create function return resultset data like List<Object> in C#, Java.

      Follow my code in Android:

      =============================================================================

      public final String METHOD_NAME = "getListName";
      public final String WSDL_TARGET_NAMESPACE = "http://tempuri.org/";
      public final String SOAP_ADDRESS = "http://192.168.0.167/appTestWS/StockService.asmx";
      public final String SOAP_ACTION = "http://tempuri.org/getListName";
      
      public List<String> Call()
      {
          String err = "";
          SoapPrimitive response = null;
          List<String> list = new ArrayList<String>();
      
          SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE, METHOD_NAME);
          request.addProperty("name_for_search", "hoa");
          SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
          envelope.dotNet = true;
          envelope.setOutputSoapObject(request);
      
          HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS);
          try
          {
              httpTransport.call(SOAP_ACTION, envelope);
              response = (SoapPrimitive)envelope.getResponse();
              list = getLStaff(response);
          }
          catch (Exception exception)
          {
              err = exception.getMessage();
          }
          return list;
      }

       

      Author's profile photo Former Member
      Former Member

      Nice article and discussion !! 🙂

       

      I have question about debugging.  I have implemented Web Service using .Net Engine.

      How can I verify what is request sent to Server from PB ?

      Is there any way so I can check what XML is being sent by PB while calling WebService ?

       

      Any pointers will be helpful.

       

      Thanks,

      Devang Modi.

      Author's profile photo Former Member
      Former Member

      when I am calling a webservice from the PB 11.5 , In my request XML header tag is missing.

      can you please help me.

       

      Author's profile photo Former Member
      Former Member

      I call ws and issue error  "Unexpected wrapper element ..." Help me!

      Author's profile photo Former Member
      Former Member

      email tuvan712@gmail.com