#1 2012-10-10 20:33:47

paulh
Member
Registered: 2012-05-12
Posts: 44

How avoid "contract differs from client's" to allow updating?

Hi Arnaud, I'm trying to implement automatic updates to my client apps. I have a method the client calls to check if it needs to download an update. The problem is that when I make an update to my server version to add some new functionality, it breaks the clients from communicating with the server even though of course I ensure that my changes are only ever additive.

How do I turn off the checking of contract between client and server to allow the client make calls to a new server that has additional methods?

Thanks in advance

Paul

Debug Output: 21:25:23 294 Error in TClientToServer.doConnect: Server's ERefServerInterface contract differs from client's: expected ["107924CEE69317C3"], received ["4FD82C7AF11DB892"] Process eRefer.exe (4488)

Offline

#2 2012-10-11 06:15:59

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

Re: How avoid "contract differs from client's" to allow updating?

You have a aContractExpected optional parameter on both client and server sides constructors which allow a custom fixed signature like a version number.

It was designed for your exact purpose.

Offline

#3 2012-10-11 10:30:26

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

Hi Arnaud, thanks for the quick response.

That is great news that I can provide an optional parameter to override this default behaviour. I just want to double-check - I never want a client to get a rejection from a server as the server should always be backwards compatible so does that mean that I should just hard code a static value into that optional parameter and never change it? If I used a version number, I would have thought that when I update the version number of the server that any clients calling passing a different value in that optional parameter would fail is it does now if the interface is updated?

Also, I would like it if the server could support a test and production version of the interface concurrently. Can I configure a single service to support two interfaces concurrently or have two services running alongside each other on same IP and port but responding to different interfaces?

Regards

Paul

Offline

#4 2012-10-11 10:35:27

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

Re: How avoid "contract differs from client's" to allow updating?

Yes, in your case, the version number should be a "major" version number, which may break only in case of major change on the server interface, e.g. when it becomes non backwards compatible.

Interfaces are set on code level, from its type information.
So you would have to register two interfaces with diverse names and GUIDs on the same server.
Just rename one as "IMyInterfaceOld" or "IMyInterfaceDebug" and use it instead of "IMyInterface".
You can even inherit interfaces, so code duplication could be minimized: inheritance can be the lead to interface versioning.

Offline

#5 2012-10-11 10:51:44

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

Great, I'm sorted on the optional parameter - it must never be backwards compatible (or otherwise the client could never download the new version from the server) so I will make that parameter a constant value.

With the Production and Test versions, I think that gives me the information I need. I still need to ponder how best to use it to give me the functionality I require but as always you've given me the tools to implement what I need.

Regards

Paul

Offline

#6 2012-10-11 11:51:19

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

Re: How avoid "contract differs from client's" to allow updating?

paulh wrote:

as always you've given me the tools to implement what I need.

My pleasure!
big_smile

Offline

#7 2012-10-11 20:37:42

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

Arnaud, I have been able to add the ContractExpected parameter on the client side but I can't see how to specify it on the server side?

My server side is:


  aModel := TSQLModel.Create([],ROOT_NAME);
  try
    aServer := TSQLRestServerFullMemory.Create(aModel,FILE_NAME,false,true);
    try
      aServer.ServiceRegister(TServiceERefServer,[TypeInfo(IERefServerInterface)],sicShared);
      aHTTPServer := TSQLite3HttpServer.Create(COMMS_PORT,[aServer]);

How do I specify the ContractExpected on the server side?

Paul

Offline

#8 2012-10-12 04:31:45

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

Re: How avoid "contract differs from client's" to allow updating?

There is a property named as such.

Offline

#9 2012-10-12 06:04:13

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

Hi Arnaud, that's not that helpful sad
I spent an hour looking through the code for it last night - I wouldn't ask if I could just find the property and that is why I included the code I'm using. I can see there is a property for a different version of the ServiceRegister procedure but it is not present for the version I'm using here based on your example code.
Is this a new property you've added? The version of your code I have to use is about 6 months old.
If you can show me which server side method I need to use with the property I can move on with getting this project finished.
Thanks
Paul

Offline

#10 2012-10-12 08:06:20

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

Re: How avoid "contract differs from client's" to allow updating?

The property is in TServiceFactory.ContractExpected.
So when call aRestServer.ServiceRegister(....).ContractExpected := 'MyVersion';

I'll add the parameter at constructor level for all TServiceFactory.Create() versions, for consistency.
Thanks for your feedback.

Offline

#11 2012-10-13 11:23:56

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

Hi Arnaud, that is not working for me.

My Server code is:
        aServer.ServiceRegister(TServiceERefServer,[TypeInfo(IERefServerInterface)],sicShared).ContractExpected := CONTRACT_NAME;

My Server appears to be starting fine but when I call the following client method:
      FClient.ServiceRegister([TypeInfo(IERefServerInterface)],sicShared,CONTRACT_NAME);

It goes into the following and fails by raising the exception at the bottom of the code segment:
constructor TServiceFactoryClient.Create(aRest: TSQLRest;
  aInterface: PTypeInfo; aInstanceCreation: TServiceInstanceImplementation;
  const aContractExpected: RawUTF8);
var i, siz: integer;
    P: PCardinal;
    Error, RemoteContract: RawUTF8;
begin
  // extract RTTI from the interface
  if not aRest.InheritsFrom(TSQLRestClientURI) then
    EServiceException.CreateFmt('%s interface needs a Client connection',
      [aInterface^.Name]);
  inherited Create(aRest,aInterface,aInstanceCreation);
  // check if this interface is supported on the server
  if aContractExpected<>'' then
    fContractExpected := aContractExpected; // override default contract
  if not CallClient(SERVICE_PSEUDO_METHOD[imContract],@Error,'',@RemoteContract) then
    raise EServiceException.CreateFmt('"%s" interface or %s routing not supported by server%s',
      [fInterfaceURI,GetEnumNameTrimed(TypeInfo(TServiceRoutingMode),fRest.ServicesRouting),Error]);

The error message is:
'"ERefServerInterface" interface or REST routing not supported by server'

I suspect the problem is with the server because if I invoke the original call on the server:
        aServer.ServiceRegister(TServiceERefServer,[TypeInfo(IERefServerInterface)],sicShared);

Then it correctly reports that the contracts are different when I make the client call passing my constant as the ExpectedContract.

Any ideas?

Paul

Offline

#12 2012-10-13 11:29:32

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

Re: How avoid "contract differs from client's" to allow updating?

Try the latest version from fossil and use the new parameter at Create.

Offline

#13 2012-10-13 11:33:27

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

LOL - not sure why it happens but I have solved the problem.
I noticed that when it reported the error that the contracts were different, the hash code it said it was expecting had double quotes around it.
I changed the value of my ContractExpected constant to have double quotes around it - e.g. from 'synopse' to '"synopse"' and it works!
So there seems to be a 'feature' that the ContractExpected value must be enclosed with double quotes...

Offline

#14 2012-10-13 11:40:02

paulh
Member
Registered: 2012-05-12
Posts: 44

Re: How avoid "contract differs from client's" to allow updating?

I can't take the latest version from Fossil - this goes live next week and there would be too much regression testing to change the underlying code at this stage! However our posts crossed - I have this working for me now.

If I ever make any money out of this project, how can I remunerate you for this very useful software you provide?

Offline

#15 2017-08-08 12:47:45

M477h13u
Member
Registered: 2017-08-08
Posts: 11

Re: How avoid "contract differs from client's" to allow updating?

Hello there everyone!

I am having issue with fContractExpected. You're saying above that this variable can hold a version number.. and this variable is of type String.. so I was wondering if it could handle something else than just number i.e. letters or special caracters ?
So, I tried to give him a contract like 'ServiceProvider', but when I do, I get the following error : ''Invalid contract "" for TServiceParams: expected "ServiceProvider" '. What is odd is that the server's contract totally vanish in the maelstrom based on this message..
It is not specify in the documentation (Or I missed it.. yikes) whether it can only hold numeric caracters; that's why I am asking you this little question (:
Hope to read you promptly and thank you guys for this awesome work you're doing !!! big_smile

Offline

#16 2017-08-08 14:04:31

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

Re: How avoid "contract differs from client's" to allow updating?

The contract vanished on the client side: check your client code.

In fact, the contract is just a string, so if you put some number converted to text, it will work.

Offline

#17 2017-08-09 07:45:17

M477h13u
Member
Registered: 2017-08-08
Posts: 11

Re: How avoid "contract differs from client's" to allow updating?

Hello Arnaud!
Thanks for the quick answer !! (:

I should have precise that I am using TServiceClientAbstract class from SynCrossPlatformREST (V 1.18) as my Client is an Android one... I checked for the last release of your framework, and the variable has not vanished from SynCrossPlatform!
Were you talking about a none SynCross-Platform Client ?

Concerning the contents of the contract, it is only working when I put numbers .. and I wanted to put letters and special caracters.. but when I do, I get the error I wrote above..
For example, if I put "10.7" as a contract, the server side will interpret it as ''10,7" so I get the above error..

Thank you for your time big_smile

Last edited by M477h13u (2017-08-10 15:18:29)

Offline

Board footer

Powered by FluxBB