#1 2015-05-13 09:39:55

lele9
Member
Registered: 2011-10-28
Posts: 170

EInterfaceFactoryException when call interface service proc on client

Hi,
i write my first interface service method.

define the interface

IServiceDocumento = interface(IInvokable)['{6B7E89EC-34B0-43A6-9C81-86A324FC1DF9}']
   function EmettiDocumento(aDocumento: TSQLDocumento): Integer;
   function AnnullaDocumento(aDocumento: TSQLDocumento): Integer;
   function ModificaDocumento(aDocumento: TSQLDocumento): Integer;
end;

implement the service in the server

TServiceDocumento = class(TInterfacedObject, IServiceDocumento)
public
   function EmettiDocumento(aDocumento: TSQLDocumento): Integer;
   function AnnullaDocumento(aDocumento: TSQLDocumento): Integer;
   function ModificaDocumento(aDocumento: TSQLDocumento): Integer;
end;

register services on server and on client

self.Server.ServiceRegister(TServiceDocumento, [TypeInfo(IServiceDocumento)], sicSingle);
self.Client.ServiceRegister([TypeInfo(IServiceDocumento)], sicSingle);

use the service on client side

procedure TSQLDocumento.ComputeFieldsBeforeWrite(aRest: TSQLRest;
  aOccasion: TSQLEvent);
var I: IServiceDocumento;
begin
   inherited;
   if aRest.Services['ServiceDocumento'].Get(I) then
   begin
      case aOccasion of
         seAdd: I.EmettiDocumento(self);
         seUpdate: I.ModificaDocumento(self);
         seDelete: I.AnnullaDocumento(self);
      end;
   end;
end;

error:
TInterfacedObjectFakeClient.FakeCall(IServiceDocumento.EmettiDocumento) failed
errorCode: 400
errorText: SingleExecution Failed (probably due to bad input parameters) for IServiceDocumento.EmettiDocumento

where i mistake?
thanks,
Emanuele

Offline

#2 2015-05-19 09:48:46

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

anyone can help me to solve this problem?
thanks

Offline

#3 2015-05-19 10:43:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

Does the debugger reach TServiceDocumento.EmettiDocumento() implementation methods?

Is authentication enabled?

Offline

#4 2015-05-19 11:49:12

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

hi ab,
no, the debugger don't reach  TServiceDocumento.EmettiDocumento() implementation methods.
authentication is enabled, i use setUser on client side.

Offline

#5 2015-05-19 11:56:07

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

Put a breakpoint in TSQLRestRoutingREST.ExecuteSOAByInterface
and try to find out what occurs.

Also enable the logs on client and server side, and check them.
You would definitively find useful information in the logs.

Offline

#6 2015-05-19 12:28:29

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

i try to find in TSQLRestRoutingREST.ExecuteSOAByInterface but i don't know what to search...

this is the log

TSynLog 1.18.1341 FTS3 2015-05-19T14:22:41

20150519 14224114 EXC   EInterfaceFactoryException ("TInterfacedObjectFakeClient.FakeCall(IServiceDocumento.ModificaDocumento) failed: '{\r\n\"errorCode\":400,\r\n\"errorText\":\"Single execution failed (probably due to bad input parameters) for IServiceDocumento.ModificaDocumento\"\r\n}'") at 007D229F  stack trace API 006BB508 006BB530 0040AB04 76FF0083 76FF07FF 007D229F 007D2563 007D303E

can help you to help me?

Offline

#7 2015-05-19 12:47:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

What is the log on the server side? with detailed map debugging information enabled, if possible.

Use step by step debugging in TSQLRestRoutingREST.ExecuteSOAByInterface:
- does it reach  TSQLRestServerURIContext.InternalExecuteSOAByInterface?
- what is the ServiceMethodIndex value?
- does it reach TServiceFactoryServer.ExecuteMethod?

BTW, why are you using sicSingle, and not sicShared as interface execution type?

Offline

#8 2015-05-19 13:02:18

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

how can enabled map debugging information?

the step by step reach TSQLRestServerURIContext.InternalExecuteSOAByInterface
ServiceMethodIndex is 0
the debugger reach TServiceFactoryServer.ExecuteMethod until

if not fInterface.fMethods[Ctxt.ServiceMethodIndex].InternalExecute(
            [PAnsiChar(Inst.Instance)+entry^.IOffset],Ctxt.ServiceParameters,
             WR,Ctxt.Call.OutHead,Ctxt.Call.OutStatus,
             fExecution[Ctxt.ServiceMethodIndex].Options,
             Ctxt.ForceServiceResultAsJSONObject,
             {$ifdef LVCL}nil{$else}fBackgroundThread{$endif},
             Ctxt.ExecuteCallback) then begin
          Error('execution failed (probably due to bad input parameters)');
          exit; // wrong request
        end;

i try with sicShared with the same result.

Offline

#9 2015-05-19 13:51:05

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

And within the InternalExecute() ?

Do Ctxt.ServiceParameters content seems correct?

You enable the detailed map debugging in formation from the Project / Options.

Offline

#10 2015-05-19 15:14:47

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

Ctxt.ServiceParameters contains the TSQLRecord as Json, i think its correct.

Offline

#11 2015-05-19 15:53:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

And then... when does it stop parsing the JSON ?

Offline

#12 2015-05-19 17:00:57

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

i think the problem is here...
in the function TServiceMethod.InternalExecute

case ValueType of
        smvObject: begin
          Par := JSONToObject(Objects[IndexVar],Par,valid);    <---- is not valid!! why?!
          if not valid then
            exit;
          IgnoreComma(Par);
        end;

any idea?

Offline

#13 2015-05-19 17:25:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

What is the JSON?
And the TSQLRecord definition?

Offline

#14 2015-05-19 17:52:28

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

step by step parsing properties i found that the error is in RiepilogoIVA property.

this is the Json value

'{"ID":0,"CodiceDocumento":"","TipoDocumento":"","Numero":"","Data":135243497472,"CedentePrestatore":{"RagioneSociale":"","CodiceFiscale":"","PartitaIva":"","RegimeFiscale":"","Indirizzo":"","NumeroCivico":"","CAP":"","Comune":"","Provincia":"","Nazione":"","UfficioREA":"","NumeroREA":"","CapitaleSociale":0,"SocioUnitco":"","StatoLiquidazione":"","Telefono":"","Fax":"","eMail":""},"CessionarioCommittente":{"RagioneSociale":"","CodiceFiscale":"","PartitaIva":"","Indirizzo":"","NumeroCivico":"","CAP":"","Comune":"","Provincia":"","Nazione":""},"RagioneSociale":"","CodiceFiscale":"","PartitaIva":"","Indirizzo":"","NumeroCivico":"","CAP":"","Comune":"","Provincia":"","Nazione":"","TipoRitenuta":"","ImportoRitenuta":0,"AliquotaRitenuta":0,"CausalePagamento":"","BolloVirtuale":"","ImportoBollo":0,"PercentualeScontoMaggiorazione":0,"ImportoScontoMaggiorazione":0,"Arrotondamento":0,"CausaleDocumento":"","Art73":false,"Vettore":{"RagioneSociale":"","CodiceFiscale":"","PartitaIva":"","Indirizzo":"","NumeroCivico":"","CAP":"","Comune":"","Provincia":"","Nazione":"","NumeroLicenzaGuida":""},"MezzoTrasporto":"","CausaleTrasporto":"","NumeroColli":0,"AspettoColli":"","UnitaMisuraPesoColli":"","PesoColli":0,"DataOraRitiro":127489671168,"DataInizioTrasporto":127489671168,"IndirizzoConsegna":"","NumeroCivicoConsegna":"","CAPConsegna":"","ComuneConsegna":"","ProvinciaConsegna":"","NazioneConsegna":"","DataOraConsegna":127489671168,"CondizioniPagamento":"","DettagliPagamento":[],"RigheDocumento":[],"RiepilogoIVA":[],"Imponibile":0,"Imposta":0,"Totale":0,"DataCreazione":135243570155,"CreatoDa":"Admin","UltimaModifica":135243570155,"ModificatoDa":""}]'

and this is the TSQLRecord Definition

TSQLDocumento = class (TSQLBase)
  private
    FTipoDocumento: RawUTF8;
    FCedentePrestatore: TAnagraficaCedentePrestatore;
    FCessionarioCommittente: TAnagraficaCessionarioCommittente;
    FNumero: RawUTF8;
    FData: TTimeLog;
    FCodiceDocumento: RawUTF8;
    FTipoRitenuta: RawUTF8;
    FAliquotaRitenuta: Double;
    FImportoRitenuta: Double;
    FCausalePagamento: RawUTF8;
    FBolloVirtuale: RawUTF8;
    FImportoBollo: Double;
    FPercentualeScontoMaggiorazione: Double;
    FImportoScontoMaggiorazione: Double;
    FArrotondamento: Double;
    FCausaleDocumento: RawUTF8;
    FArt73: Boolean;
    FVettore: TAnagraficaVettore;
    FMezzoTrasporto: RawUTF8;
    FCausaleTrasporto: RawUTF8;
    FNumeroColli: Integer;
    FAspettoColli: RawUTF8;
    FUnitaMisuraPesoColli: RawUTF8;
    FPesoColli: Double;
    FNazioneConsegna: RawUTF8;
    FComuneConsegna: RawUTF8;
    FNumeroCivicoConsegna: RawUTF8;
    FProvinciaConsegna: RawUTF8;
    FDataOraRitiro: TTimeLog;
    FCAPConsegna: RawUTF8;
    FIndirizzoConsegna: RawUTF8;
    FDataOraConsegna: TTimeLog;
    FCondizioniPagamento: RawUTF8;
    FDettagliPagamento: TDettagliPagamento;
    FRigheDocumento: TRigheDocumento;
    FDataInizioTrasporto: TTimeLog;
    function getRiepilogoIVA: TRiepilogoIVA;
    function getImponibile: Double;
    function getImposta: Double;
    function getTotale: Double;
    //function getRagioneSociale: RawUTF8;
  public
     procedure ComputeFieldsBeforeWrite(aRest: TSQLRest; aOccasion: TSQLEvent); override;
  published
     property CodiceDocumento: RawUTF8 index 4 read FCodiceDocumento write FCodiceDocumento;
     property TipoDocumento: RawUTF8 index 40 read FTipoDocumento write FTipoDocumento;
     property Numero: RawUTF8 index 30 read FNumero write FNumero;
     property Data: TTimeLog read FData write FData;
     property CedentePrestatore: TAnagraficaCedentePrestatore read FCedentePrestatore write FCedentePrestatore;
     property CessionarioCommittente: TAnagraficaCessionarioCommittente read FCessionarioCommittente write FCessionarioCommittente;
     property RagioneSociale: RawUTF8 read FCessionarioCommittente.RagioneSociale write FCessionarioCommittente.RagioneSociale;
     property CodiceFiscale: RawUTF8 read FCessionarioCommittente.CodiceFiscale write FCessionarioCommittente.CodiceFiscale;
     property PartitaIva: RawUTF8 read FCessionarioCommittente.PartitaIva write FCessionarioCommittente.PartitaIva;
     property Indirizzo: RawUTF8 read FCessionarioCommittente.Indirizzo write FCessionarioCommittente.Indirizzo;
     property NumeroCivico: RawUTF8 read FCessionarioCommittente.NumeroCivico write FCessionarioCommittente.NumeroCivico;
     property CAP: RawUTF8 read FCessionarioCommittente.CAP write FCessionarioCommittente.CAP;
     property Comune: RawUTF8 read FCessionarioCommittente.Comune write FCessionarioCommittente.Comune;
     property Provincia: RawUTF8 read FCessionarioCommittente.Provincia write FCessionarioCommittente.Provincia;
     property Nazione: RawUTF8 read FCessionarioCommittente.Nazione write FCessionarioCommittente.Nazione;
     property TipoRitenuta: RawUTF8 index 4 read FTipoRitenuta write FTipoRitenuta;
     property ImportoRitenuta: Double read FImportoRitenuta write FImportoRitenuta;
     property AliquotaRitenuta: Double read FAliquotaRitenuta write FAliquotaRitenuta;
     property CausalePagamento: RawUTF8 index 2 read FCausalePagamento write FCausalePagamento;
     property BolloVirtuale: RawUTF8 index 2 read FBolloVirtuale write FBolloVirtuale;
     property ImportoBollo: Double read FImportoBollo write FImportoBollo;
     property PercentualeScontoMaggiorazione: Double read FPercentualeScontoMaggiorazione write FPercentualeScontoMaggiorazione;
     property ImportoScontoMaggiorazione: Double read FImportoScontoMaggiorazione write FImportoScontoMaggiorazione;
     property Arrotondamento: Double read FArrotondamento write FArrotondamento;
     property CausaleDocumento: RawUTF8 read FCausaleDocumento write FCausaleDocumento;
     property Art73: Boolean read FArt73 write FArt73;
     property Vettore: TAnagraficaVettore read FVettore write FVettore;
     property MezzoTrasporto: RawUTF8 index 80 read FMezzoTrasporto write FMezzoTrasporto;
     property CausaleTrasporto: RawUTF8 index 100 read FCausaleTrasporto write FCausaleTrasporto;
     property NumeroColli: Integer read FNumeroColli write FNumeroColli;
     property AspettoColli: RawUTF8 index 100 read FAspettoColli write FAspettoColli;
     property UnitaMisuraPesoColli: RawUTF8 index 10 read FUnitaMisuraPesoColli write FUnitaMisuraPesoColli;
     property PesoColli: Double read FPesoColli write FPesoColli;
     property DataOraRitiro: TTimeLog read FDataOraRitiro write FDataOraRitiro;
     property DataInizioTrasporto: TTimeLog read FDataInizioTrasporto write FDataInizioTrasporto;
     property IndirizzoConsegna: RawUTF8 read FIndirizzoConsegna write FIndirizzoConsegna;
     property NumeroCivicoConsegna: RawUTF8 read FNumeroCivicoConsegna write FNumeroCivicoConsegna;
     property CAPConsegna: RawUTF8 read FCAPConsegna write FCAPConsegna;
     property ComuneConsegna: RawUTF8 read FComuneConsegna write FComuneConsegna;
     property ProvinciaConsegna: RawUTF8 read FProvinciaConsegna write FProvinciaConsegna;
     property NazioneConsegna: RawUTF8 read FNazioneConsegna write FNazioneConsegna;
     property DataOraConsegna: TTimeLog read FDataOraConsegna write FDataOraConsegna;
     property CondizioniPagamento: RawUTF8 index 4 read FCondizioniPagamento write FCondizioniPagamento;
     property DettagliPagamento: TDettagliPagamento read FDettagliPagamento write FDettagliPagamento;
     property RigheDocumento: TRigheDocumento read FRigheDocumento write FRigheDocumento;
     property RiepilogoIVA: TRiepilogoIVA read getRiepilogoIVA;
     property Imponibile: Double read getImponibile;
     property Imposta: Double read getImposta;
     property Totale: Double read getTotale;
end;

and the RiepilogoIVA definition

TDettaglioIVA = record
   Aliquota: Double;
   Imponibile: Double;
   Imposta: Double;
   Totale: Double;
end;
TRiepilogoIVA = array of TDettaglioIVA;

and the getRiepilogoIVA implementation detail

function TSQLDocumento.getRiepilogoIVA: TRiepilogoIVA;
var
  I, J: Integer;
  rIVA: TDynArray;
  dIVA: TDettaglioIVA;
begin
   setLength(result, 0);
   rIVA.Init(TypeInfo(TRiepilogoIVA), result);
   //ciclo tutte le righe del documento
   for I := 0 to High(self.FRigheDocumento) do
   begin
      dIVA.Aliquota := self.FRigheDocumento[i].Aliquota;
      dIVA.Imponibile := self.FRigheDocumento[i].getImponibile;
      dIVA.Imposta := self.FRigheDocumento[i].getImposta;
      dIVA.Totale := self.FRigheDocumento[i].getTotale;
      //verifico aliquota iva
      //se nuova inserisco riga
      J := rIVA.FindAndAddIfNotExisting(dIVA, nil, SortDynArrayDouble);
      //altrimenti la sommo a quella presente
      if (J > -1) then
      begin
         TDettaglioIVA(rIVA.ElemPtr(J)^).Imponibile := TDettaglioIVA(rIVA.ElemPtr(J)^).Imponibile + self.FRigheDocumento[i].getImponibile;
         TDettaglioIVA(rIVA.ElemPtr(J)^).Imposta := TDettaglioIVA(rIVA.ElemPtr(J)^).Imposta + self.FRigheDocumento[i].getImposta;
         TDettaglioIVA(rIVA.ElemPtr(J)^).Totale := TDettaglioIVA(rIVA.ElemPtr(J)^).Totale + self.FRigheDocumento[i].getTotale;
      end;
   end;
end;

Offline

#15 2015-05-19 19:13:38

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

You have no setter for the properties...
So serialization cannot work!

Use plain read and write on a true field, or even better do not include them as published property but as public property.

Offline

#16 2015-05-20 06:38:29

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

it works!!!
thanks ab for the step by step help smile
another question, you ask me for the sicSingle/sicShared interface service.
In this case i use the service to update other table/tsqlRecord when add/update/delete a TSQLDocumento so i use sicSingle.
What do you think is the best instance implementation for this case?

Offline

#17 2015-05-20 09:42:52

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

I suspect sicShared would be enough, and using a little less resources.

With sicSingle, a TServiceDocumento instance would be created for every request, which is a bit overkill IMHO.

Offline

#18 2016-03-18 09:53:11

lele9
Member
Registered: 2011-10-28
Posts: 170

Re: EInterfaceFactoryException when call interface service proc on client

hi ab,
i'm testing this code

procedure TSQLDocumento.ComputeFieldsBeforeWrite(aRest: TSQLRest;
  aOccasion: TSQLEvent);
var I: IServiceDocumento;
begin
   inherited;
   if aRest.Services['ServiceDocumento'].Get(I) then
   begin
      case aOccasion of
         seAdd: I.EmettiDocumento(self);
         seUpdate: I.ModificaDocumento(self);
         seDelete: I.AnnullaDocumento(self);
      end;
   end;
end;

and i see that seDelete Occasion never happen!
when i delete a record seem do not enter in ComputeFieldsBeforeWrite.
how can manage this case?
thanks

Offline

#19 2016-03-18 14:31:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: EInterfaceFactoryException when call interface service proc on client

ComputeFieldsBeforeWrite is not called before deletion.
Its purpose is not to be a notification callback, but to modify the fields on the fly - as its name states.

So before a deletion, there is no field to be computed, since the fields would be deleted with the corresponding record/object.

Try to use the TSQLRestServer.OnBeforeURI event instead.

Offline

Board footer

Powered by FluxBB