Archived

This forum has been archived. Please start a new discussion on GitHub.

Javascript bidding is failing. Getting an implementation expecting an interface Error at runtime.

All:
The below slice sniped describe 4 entities (RangerAccessResource, RangerMutableResource, RangerAccessResourceImp , RangerAccessRequest). I am getting the below error only when using the javascript biddings. Java, C#, and Python are all fine.

Error:
LocalException [Error]
....
at InputStream.readValue (/Users/achouic/node_modules/ice/src/Ice/Stream.js:1828:35) {
reason:
"expected element of type `::com::morningstar::entitlement::neti::generated::RangerAccessResource'

but received `::com::morningstar::entitlement::neti::generated::RangerAccessResourceImp'",

type: '::com::morningstar::entitlement::neti::generated::RangerAccessResourceImp',
expectedType: '::com::morningstar::entitlement::neti::generated::RangerAccessResource'

interface RangerAccessResource {
string getOwnerUser();
RangerAccessResource getReadOnlyCopy();
}

interface RangerMutableResource extends RangerAccessResource {
void setOwnerUser(string ownerUser);
}

class RangerAccessResourceImp implements RangerMutableResource {
string ownerUser;
AccessResourceElements elements;
}

interface RangerAccessRequest {
RangerAccessResource getResource();
string getAccessType();
RangerAccessRequest getReadOnlyCopy();
}

Tagged:

Comments

  • xdm
    xdm La Coruña, Spain

    Hi,

    What Ice version are you using?

  • Hi xdm:
    This is the version: 3.7.5

  • xdm
    xdm La Coruña, Spain

    Hi,

    did you rebuild your Slice definitions with slice2js 3.7.5, seems to me they were generated with an older version of the compiler.

    You can check the header of the generated file to see what version of slice2js was used, it should be something like

    //
    // Copyright (c) ZeroC, Inc. All rights reserved.
    //
    //
    // Ice version 3.7.5
    
  • Hi xdm:
    Yes it was built with 3.7.5 as shown below. any suggestion how to go about to troubleshoot this issue? Thanks much for your help.

    //
    // Copyright (c) ZeroC, Inc. All rights reserved.
    //
    //
    // Ice version 3.7.5
    //
    //
    //
    // Generated from file `neti.ice'
    //
    // Warning: do not edit this file.
    //
    //
    //

    /* eslint-disable /
    /
    jshint ignore: start */

  • xdm
    xdm La Coruña, Spain

    Hi,

    I don't understand why this is not working in your case, I tried to reproduce the problem with a small example but seems to be working.

    See https://github.com/pepone/interface-test

    Run the server using:

    dotnet restore /p:Configuration=Debug /p:Platform="Any CPU"
    dotnet run /p:Configuration=Debug /p:Platform="Any CPU"
    

    And the Client:

    npm install
    node Client.js
    

    Maybe you can modify this example to reproduce the problem or provide a complete example we can use to reproduce it?.

    Cheers,
    Jose

  • Will do thank you very much! I will report on my run.

  • Hi xdm:

    I got your github project, tried to build it, it is asking for .NetFramework Version 5.0, see below. went to this url (https://docs.microsoft.com/en-us/dotnet/framework/deployment/deployment-guide-for-developers), found only 4.5 to 4.8. I am not a .net guy. Thanks for the help.

    Severity Code Description Project File Line Suppression State
    Error MSB3644 The reference assemblies for .NETFramework,Version=v5.0 were not found. To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application. You can download .NET Framework Developer Packs at https://aka.ms/msbuild/developerpacks Server C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets 1177

  • xdm
    xdm La Coruña, Spain
  • Hi xdm:
    I did tweak your slice file to make it show the error for javascript biddings. See below for slice file, server, servant and the js client. Thanks for your help!

    module Test
    {
    interface RangerAccessResource
    {
    }
    class RangerAccessResourceImp implements RangerAccessResource
    {
    string ownerUser;
    }
    interface RangerAccessRequest
    {
    RangerAccessResource getResource();
    }
    class RangerAccessRequestImpl implements RangerAccessRequest
    {
    RangerAccessResource resource;
    }
    class RangerAccessResult
    {
    RangerAccessRequest request;
    }
    // This is the servant
    interface Authorizer
    {
    RangerAccessResult authorize();
    }
    }

    //Java Server:

    public class AuthorizerI implements Test.Authorizer {

    public RangerAccessResult authorize(Current current) {
    return new RangerAccessResult(new RangerAccessRequestImpl(new RangerAccessResourceImp("Owner1")));
    }
    }

    //Java Servant

    public class AsyncServerTest {
    private AuthorizerI authorizerServant;

    public void start() {
        try(com.zeroc.Ice.Communicator communicator = com.zeroc.Ice.Util.initialize(new String[0]))
        {
            com.zeroc.Ice.ObjectAdapter adapter = communicator.createObjectAdapterWithEndpoints(test, "tcp -p 10000");
            com.zeroc.Ice.Object object = authorizerServant;
            adapter.add(object, com.zeroc.Ice.Util.stringToIdentity("test"));
            adapter.activate();
            communicator.waitForShutdown();
        }
    }
    

    }

    //JS client

    const Ice = require("ice").Ice;
    const Test = require("/Users/achouic/workspace/neti/neti-slice/neti-slice-js/test").Test;

    (async () =>
    {
    let communicator;
    try
    {
    communicator = Ice.initialize(process.argv);
    const hello = await Test.AuthorizerPrx.checkedCast(communicator.stringToProxy("test:tcp -h localhost -p 10000"));
    const response = await hello.authorize();
    console.log("ok");
    }
    catch(ex)
    {
    console.log(ex.toString());
    process.exitCode = 1;
    }
    finally
    {
    if(communicator)
    {
    await communicator.destroy();
    }
    }
    })();

  • xdm
    xdm La Coruña, Spain

    Hi,

    I see, seems this is a bug in the slice2js generated code that doesn't correctly handle interface by value data members.

  • Being new to ice/slice, is there a work around like declaring this interface ( I thing it is within the class "RangerAccessResult") as a reference like:

    class RangerAccessResult
    {
    RangerAccessRequest* request;
    }

  • xdm
    xdm La Coruña, Spain

    Hi,

    You are relying upon two deprecated features, classes implementing interfaces and passing interfaces by value. If this is a new project the best would be to refactor the Slice definitions to not use these deprecated features.

    interface RangerAccessResource
    {
    }
    
    class RangerAccessResourceImp implements RangerAccessResource
    {
        string ownerUser;
    }
    

    You should avoid this, classes should not implement interfaces, this is deprecated.

    class RangerAccessResult
    {
        RangerAccessRequest request;
    }
    

    And also avoid this, using an interface as a data member is deprecated too.

    In general, you should only use interfaces to define the client-server contract, where each interface operation represents a remote procedure, or in other words, a method that a client can invoke on a server, then you use classes, struct, sequences, and other Slice types to define the data that is used by the operations.

    class RangerAccessResult
    {
    RangerAccessRequest* request;
    }
    

    This is different, here request is a proxy calling getResource will make a remote invocation to get the resource, getResource returns an interface by value, also deprecated as mentioned earlier but not affected by this bug.

    The major difference between the two approaches is that in the second you will make two remote procedure calls, one to get RangerAccessResult and a second to get the RangerAccessResource, with the original RangerAccessResult already contain RangerAccessResult, anyway as stated above interfaces by value are deprecated and for new projects is best to not use them.

    You should review the doc corresponding to these features, especially:
    * https://doc.zeroc.com/ice/3.7/the-slice-language/classes
    * https://doc.zeroc.com/ice/3.7/language-mappings/javascript-mapping/client-side-slice-to-javascript-mapping/javascript-mapping-for-classes

    If you need to interoperate with an older version, the best is to fix slice2js I added a bug into our GitHub project to fix this, https://github.com/zeroc-ice/ice/issues/1271

  • Thank you for the explanation and the creation of a bug fix story. I will again go thru the above links. This is a new project, I went with using interfaces to ensure when you updating a given implementation we will not break clients be it java, cs, py, or js. Also the original library is written in java and I follow their usage of interfaces and classes to minimize maintenance nightmares of the slice ice file down the line. Thanks.

  • Hi xdm:
    Having read again the-slice-language about classes. This is my use case.
    1. I have an sdk library written in java, I want to make such sdk available in cs, python, and js,
    2. an example of the sdk: It has an interface (RangerAccessResource) and the corresponding impl (RangerAccessResourceImpl)

    Then how do I model this interface/class in my slice.ice? I thought to faithfully model it as the initial java, that way if there is a change in java, e.g the implementation changes, if the client is referencing the interface then it will minimize support of the cs, py, and js.

    Thanks for your help

  • xdm
    xdm La Coruña, Spain

    Hi,

    Keep in mind that with your original approach of passing interfaces by value, you have to provide the implementation for these interfaces in all languages.

    If you want that all languages access the Java implementation you should pass interface references and the client can use the proxy to make invocations that are sent to the Java implementation where you will implement the server.

    Finding the correct API for exposing the library will require some trying, I would say that if the API is too fine-grained you end up doing many RPCs keep in mind that an RPC is more expensive than a local method call, this might or might not be an issue depending on the tradeoffs of your application.

  • Hi xdm:
    I agree with. you with respect to send to the client a composite object after all calls are locals. To me client do 1 remote call, the server populate this return object (i.e. RangerAccessResponse), from there all client call on that object are local.
    Providing impl for each language is not a big deal as these are basically Pojo/simple container object no business logic.

    So it looks like my approach is right for my use case. Is there a work around for the javascript issue. I am trying to debug the generated js code and see if, temporary fix it there, until an offical bug fix is released. Do you think this is doable?

  • xdm
    xdm La Coruña, Spain

    You can still do something like that using value factories, see https://doc.zeroc.com/ice/3.7/language-mappings/javascript-mapping/client-side-slice-to-javascript-mapping/javascript-mapping-for-classes#id-.JavaScriptMappingforClassesv3.7-ValueFactoriesinJavaScript

    The idea will be to define RangerAccessResponse as a class and then register a value factory that is responsible to create the instances, in the value factory you can return a class derived from RangerAccessResponse that provides the operations you need.

  • Thank you for the pointer. I will read about it. Do you have any idea about the bug fix timeline?