Search code examples
javadelphisoapwsdldelphi-7

'Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'XXXXX'. One of '{XXXXX}' is expected


Hi i am loading java webservice to Delphi 7 through WSDL.when i call a web service from delphi i am getting below error. i am Stuck here without any clue.

'Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'XXXXX'. One of '{XXXXX}' is expected

Using WSDL delphi is generating below code. i have removed many methods in below code.

   // ************************************************************************ //
// The types declared in this file were generated from data read from the
// WSDL File described below:
// WSDL     : http://localhost/protectappws/services/ProtectappwsImpl?wsdl
// Encoding : UTF-8
// Version  : 1.0
// (3/5/2016 5:55:17 AM - 1.33.2.5)
// ************************************************************************ //

unit ProtectappwsImpl;

interface

uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns;

type

  // ************************************************************************ //
  // The following types, referred to in the WSDL document are not being represented
  // in this file. They are either aliases[@] of other types represented or were referred
  // to but never[!] declared in the document. The types from the latter category
  // typically map to predefined/known XML or Borland types; however, they could also 
  // indicate incorrect WSDL documents that failed to declare or import a schema type.
  // ************************************************************************ //
  // !:string          - "http://www.w3.org/2001/XMLSchema"
  // !:boolean         - "http://www.w3.org/2001/XMLSchema"
  // !:int             - "http://www.w3.org/2001/XMLSchema"

  Encrypt              = class;                 { "http://dsws.org/protectappws/" }
  Decrypt              = class;                 { "http://dsws.org/protectappws/" }


   // ************************************************************************ //
  // Namespace : http://dsws.org/protectappws/
  // Serializtn: [xoLiteralParam]
  // ************************************************************************ //
  Encrypt = class(TRemotable)
  private
    Fusername: WideString;
    Fpassword: WideString;
    Fkeyname: WideString;
    Fkeyiv: WideString;
    Ftransformation: WideString;
    Fplaintext: WideString;
  public
    constructor Create; override;
  published
    property username: WideString read Fusername write Fusername;
    property password: WideString read Fpassword write Fpassword;
    property keyname: WideString read Fkeyname write Fkeyname;
    property keyiv: WideString read Fkeyiv write Fkeyiv;
    property transformation: WideString read Ftransformation write Ftransformation;
    property plaintext: WideString read Fplaintext write Fplaintext;
  end;

  EncryptResponse =  type WideString;      { "http://dsws.org/protectappws/"[L] }


  // ************************************************************************ //
  // Namespace : http://dsws.org/protectappws/
  // Serializtn: [xoLiteralParam]
  // ************************************************************************ //
  Decrypt = class(TRemotable)
  private
    Fusername: WideString;
    Fpassword: WideString;
    Fkeyname: WideString;
    Fkeyiv: WideString;
    Ftransformation: WideString;
    Fciphertext: WideString;
  public
    constructor Create; override;
  published
    property username: WideString read Fusername write Fusername;
    property password: WideString read Fpassword write Fpassword;
    property keyname: WideString read Fkeyname write Fkeyname;
    property keyiv: WideString read Fkeyiv write Fkeyiv;
    property transformation: WideString read Ftransformation write Ftransformation;
    property ciphertext: WideString read Fciphertext write Fciphertext;
  end;

  DecryptResponse =  type WideString;      { "http://dsws.org/protectappws/"[L] }


   // ************************************************************************ //
  // Namespace : http://dsws.org/protectappws/
  // soapAction: http://dsws.org/protectappws/%operationName%
  // transport : http://schemas.xmlsoap.org/soap/http
  // style     : document
  // binding   : protectappwsSOAP
  // service   : protectappws
  // port      : protectappwsSOAP
  // URL       : http://localhost/protectappws/services/ProtectappwsImpl
  // ************************************************************************ //
  protectappws = interface(IInvokable)
  ['{EAB73212-14C4-1A41-ABFA-F106C8EB9965}']
    function  Encrypt(const parameters: Encrypt): EncryptResponse; stdcall;
    function  Decrypt(const parameters: Decrypt): DecryptResponse; stdcall;
  end;

function Getprotectappws(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): protectappws;


implementation

function Getprotectappws(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): protectappws;
const
  defWSDL = 'http://localhost/protectappws/services/ProtectappwsImpl?wsdl';
  defURL  = 'http://localhost/protectappws/services/ProtectappwsImpl';
  defSvc  = 'protectappws';
  defPrt  = 'protectappwsSOAP';
var
  RIO: THTTPRIO;
begin
  Result := nil;
  if (Addr = '') then
  begin
    if UseWSDL then
      Addr := defWSDL
    else
      Addr := defURL;
  end;
  if HTTPRIO = nil then
    RIO := THTTPRIO.Create(nil)
  else
    RIO := HTTPRIO;
  try
    Result := (RIO as protectappws);
    if UseWSDL then
    begin
      RIO.WSDLLocation := Addr;
      RIO.Service := defSvc;
      RIO.Port := defPrt;
    end else
      RIO.URL := Addr;
  finally
    if (Result = nil) and (HTTPRIO = nil) then
      RIO.Free;
  end;
end;




constructor Encrypt.Create;
begin
  inherited Create;
  FSerializationOptions := [xoLiteralParam];
end;

constructor Decrypt.Create;
begin
  inherited Create;
  FSerializationOptions := [xoLiteralParam];
end;

initialization
  InvRegistry.RegisterInterface(TypeInfo(protectappws), 'http://dsws.org/protectappws/', 'UTF-8');
  InvRegistry.RegisterDefaultSOAPAction(TypeInfo(protectappws), 'http://dsws.org/protectappws/%operationName%');
  InvRegistry.RegisterInvokeOptions(TypeInfo(protectappws), ioDocument);
  InvRegistry.RegisterInvokeOptions(TypeInfo(protectappws), ioLiteral);
  RemClassRegistry.RegisterXSInfo(TypeInfo(EncryptResponse), 'http://dsws.org/protectappws/', 'EncryptResponse');
  RemClassRegistry.RegisterXSInfo(TypeInfo(DecryptResponse), 'http://dsws.org/protectappws/', 'DecryptResponse');
  RemClassRegistry.RegisterXSClass(Encrypt, 'http://dsws.org/protectappws/', 'Encrypt');
  RemClassRegistry.RegisterSerializeOptions(Encrypt, [xoLiteralParam]);
  RemClassRegistry.RegisterXSClass(Decrypt, 'http://dsws.org/protectappws/', 'Decrypt');
  RemClassRegistry.RegisterSerializeOptions(Decrypt, [xoLiteralParam]);

end.

Below is my Delphi 7 code to call Webservice.

unit Client;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ProtectappwsImpl, StdCtrls, Buttons, InvokeRegistry, Rio,
  SOAPHTTPClient;

type
  TForm1 = class(TForm)
    memResponse: TMemo;
    memErrors: TMemo;
    btnProcess: TBitBtn;
    procedure btnProcessClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnProcessClick(Sender: TObject);
var
  ECrypt : Encrypt;
  objService : protectappws;
  wsResponse : WideString;


  ProtectApp : protectappws;
begin
  memResponse.Lines.Clear;
  memErrors.Lines.Clear;
  memResponse.Refresh;
  memErrors.Refresh;
  try
    ECrypt :=  Encrypt.Create;


    ECrypt.username := 'kenwhite';
    ECrypt.password := 'kenwhite';
    ECrypt.keyname := 'MYKEY';
    ECrypt.plaintext := 'Hi';


    objService := Getprotectappws(True,EmptyStr,nil);

    wsResponse :=  objService.Encrypt(ECrypt);


  except
    on E: Exception do
    begin
       showmessage(e.Message);
    end;
  end;
end;

end.

when i run above delphi code i am getting below error

'Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'username'. One of '{username}' is expected

Delphi is sending below request to java web service

<?xml version="1.0"?>

-<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">


-<SOAP-ENV:Body>


-<Encrypt xmlns="http://dsws.org/protectappws/">

<username>kenwhite</username>

<password>kenwhite</password>

<keyname>MYKEY</keyname>

<keyiv/>

<transformation/>

<plaintext>Hi</plaintext>

</Encrypt>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

but webservice is Expecting below request.

<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prot="http://dsws.org/protectappws/"><soapenv:Header/>
   <soapenv:Body>
         <prot:Encrypt><username>kenwhite</username>
         <password>kenwhite</password>
         <keyname>MYKEY</keyname>
         <!--Optional:-->
         <keyiv/>
         <!--Optional:-->
         <transformation/>
         <plaintext>Hi</plaintext>
      </prot:Encrypt>
   </soapenv:Body>
</soapenv:Envelope>

why there is a difference in delphi generated request and client is expecting different request.

i tried removing ioDocument from below code and keeping ioLiteral and vise versa

  InvRegistry.RegisterInvokeOptions(TypeInfo(protectappws), ioDocument);
  InvRegistry.RegisterInvokeOptions(TypeInfo(protectappws), ioLiteral);

Delphi 7 is generating soap request with SOAP-ENV and java is expecting soapenv. i am really confused and stuck with this.


Solution

  • To fix this issue I have modified soap request.

    There was a bug in Delphi 7 so it was not allowing me to change soap request. To fix this i have downloaded Soapfix from embarcadero and change the soap request onbeforeExecute event of HTTPRIO component and it started working. :)

    before modifying request we just need to know what web service is expecting and change the request.

    from my request XML i just removed name space from Encrypt node and it's working.

    <Encrypt xmlns="http://dsws.org/protectappws/">
    

    My modified request xml

    <?xml version="1.0"?>
    
    -<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    
    -<SOAP-ENV:Body>
    
    -<Encrypt>
    
    <username>kenwhite</username>
    
    <password>kenwhite</password>
    
    <keyname>MYKEY</keyname>
    
    <keyiv/>
    
    <transformation/>
    
    <plaintext>Hi</plaintext>
    
    </Encrypt>
    
    </SOAP-ENV:Body>
    
    </SOAP-ENV:Envelope>