Archived

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

Can ObjectPrx.toString() more clever

public class Server {
    public static void
    main(String[] args)
    {
	int status = 0;
	Ice.Communicator ic = null;
        try {
	    ic = Ice.Util.initialize(args);
	    Ice.ObjectAdapter adapter
		= ic.createObjectAdapterWithEndpoints(
		    "SimplePrinterAdapter", "udp -p 10000");
	    Ice.Object object = new PrinterI();
	    ObjectPrx objPrx = adapter.add(
		    object,
		    ic.stringToIdentity("SimplePrinter"));
	    System.out.println([B][COLOR="Blue"]objPrx.toString()[/COLOR][/B]);
	    System.out.println([COLOR="blue"][B]objPrx.ice_datagram().toString()[/B][/COLOR]);
	    adapter.activate();
	    ic.waitForShutdown();
        } catch (Exception e) {
	    e.printStackTrace();
	    status = 1;
	}
        //...
    }
}

This is the above code's output:
SimplePrinter -t:udp -h 192.168.1.3 -p 10000
SimplePrinter -d:udp -h 192.168.1.3 -p 10000

It seems that the initial ObjectPrx has the default "-t" parameter instead of "-d". Can it be more clever that it could get the "-d" by "udp -h 192.168.1.3 -p 10000" ?

This could lead to many problems if we get a proxy from an Ice call.

BTW, I think it would be wrong if I config IceGrid as follows:
1.IceGrid registry
IceGrid.Registry.Client.Endpoints=[COLOR="blue"][B]tcp[/B][/COLOR] -h 192.168.1.3 -p 10000
IceGrid.Registry.Server.Endpoints=[COLOR="Blue"][B]udp[/B][/COLOR] -h 192.168.1.3 -p 10000
...

2.Server
Ice.Default.Locator=IceGrid/Locator:tcp -h 192.168.1.3 -p 10000 
because the serverPrx returned by IceGrid/Locator would be something like this IceGrid/xxx -t:udp -h 192.168.1.3 -p 10000. Tomorrow I will do a test.

Comments

  • Please see the following code:
    [B]//Printer.ice[/B]
    #ifndef SIMPLE_ICE
    #define SIMPLE_ICE
    
    module Demo
    {
        interface Printer
        {
    	void printString(string s);
        };
        interface Agent
        {
            Printer* getPrinter();
        };
    };
    
    #endif
    
    [B]//PrinterI.java[/B]
    public class PrinterI extends Demo._PrinterDisp {
        public void
        printString(String s, Ice.Current current)
        {
            System.out.println(s);
        }
    }
    
    [B]//AgentI.java[/B]
    import Demo.*;
    
    public final class AgentI extends _AgentDisp
    {
        private Demo.PrinterPrx _printerPrx;	
        public
        AgentI(PrinterPrx printerPrx)
        {
        	_printerPrx = printerPrx;
    [COLOR="Blue"]    	System.out.println("This is the printerPrx:"+_printerPrx.toString());[/COLOR]
        }
    
        public PrinterPrx
        getPrinter(Ice.Current __current)
        {
    	return _printerPrx;
        }
    }
    
    [B]//Client.java[/B]
    public class Client {
        public static void main(String[] args)
        {
            int status = 0;
            Ice.Communicator ic = null;
            try {
    	    ic = Ice.Util.initialize(args);
    	    Ice.ObjectPrx base = ic.stringToProxy(
    		    "SimpleAgent:tcp -p 10000");
    	    Demo.AgentPrx agent = Demo.AgentPrxHelper.checkedCast(base);
    	    if (agent == null)
    	        throw new Error("Invalid proxy");
    	    	    
    	    Demo.PrinterPrx printer = agent.getPrinter();
    	    printer.printString("Hello World!");
            } catch (Ice.LocalException e) {
                e.printStackTrace();
    	    status = 1;
            } catch (Exception e) {
    	    System.err.println(e.getMessage());
    	    status = 1;
    	}
    	//...
        }
    }
    
    [B]//Server.java[/B]
    import Ice.ObjectPrx;
    public class Server {
        public static void
        main(String[] args)
        {
    	int status = 0;
    	Ice.Communicator ic = null;
            try {
    	    ic = Ice.Util.initialize(args);
    
    	    //1.    
    	    Ice.ObjectAdapter printerAdapter
    		= ic.createObjectAdapterWithEndpoints(
    		    "SimplePrinterAdapter", [B][COLOR="Red"]"udp -p 9999"[/COLOR][/B]);
    	    Demo.PrinterPrx printerPrx = Demo.PrinterPrxHelper.uncheckedCast(
    	    	  printerAdapter.add(new PrinterI(),ic.stringToIdentity("SimplePrinter"))
    	    	);
    	    System.out.println(printerPrx.toString());
    	    
    	    //2.    
    	    Ice.ObjectAdapter agentAdapter
    		= ic.createObjectAdapterWithEndpoints(
    		    "SimpleAgentAdapter", "tcp -p 10000");
    	    agentAdapter.add(new AgentI(printerPrx),ic.stringToIdentity("SimpleAgent"));	    
    	    
    	    //3.
    	    printerAdapter.activate();
    	    agentAdapter.activate();
    	    
    	    ic.waitForShutdown();
            } catch (Exception e) {
    	    e.printStackTrace();
    	    status = 1;
    	}
            //...
        }
    }
    

    The above client will get an exception as follows:
    Ice.NoEndpointException
        proxy = "SimplePrinter [COLOR="Red"][B]-t[/B][/COLOR]:udp -h 192.168.1.134 -p 9999        
            at IceInternal.RoutableReference.createConnection(RoutableReference.java:364)
            at IceInternal.DirectReference.getConnection(DirectReference.java:192)
            at Ice._ObjectDelM.setup(_ObjectDelM.java:258)
            at Ice.ObjectPrxHelperBase.__getDelegate(ObjectPrxHelperBase.java:905)
            at Demo.PrinterPrxHelper.printString(PrinterPrxHelper.java:31)
            at Demo.PrinterPrxHelper.printString(PrinterPrxHelper.java:20)
            at Client.main(Client.java:25)
    

    However, if I change "udp -p 9999" in Server.java to "tcp -p 9999", the client will work properly.
  • I think this is a question same as Ice's selection of byte order. Ice always use little-endian byte order for numeric types instead of using “receiver makes it right”. This is of course a clever decision. As of proxies, however, I think that "sender makes it right" will be appropriate. That is, when the server generates a proxy, it would output "SimplePrinter -t:tcp -h 192.168.1.134 -p 9999" for a TCP endpoint and otherwise an "SimplePrinter -d:udp -h 192.168.1.134 -p 9999" for an UDP endpoint.
  • bernard
    bernard Jupiter, FL
    Hi Eric,

    You have to remember that a proxy can have several endpoints, for example, both a tcp and an udp endpoint. By default, when you create a proxy and don't specify a mode, it's twoway, so
    "<identity>:endpoint1:endpoint2:endpoint3" is always equivalent to "<identity> -t:endpoint1:endpoint2:endpoint3".

    I think you'd like a variable default, like "if all endpoints are udp, then use -d (datagram) as default". I guess it would be possible, but that's not how we specify proxies today.

    A related issue is that today you can control the endpoint or endpoints "published" by an object adapter, but you can't set other proxy options such as -o (oneway) and -d (datagram) in the proxies created by this adapter. The object adapter always creates twoway proxies and you need to programmatically update these proxies to apply the desired options. I think it would make sense to provide the ability to set the "published" options through config as well.

    Cheers,
    Bernard
  • Yes, this is a dilemma. However, if this can not be improved, it would lead to endless problems for application code. For example, if the server-side's code or config file changs from "tcp -p 9999" to "udp -p 9999", the client will not work properly.

    I think IceGrid also has this problem if I config as follows:
    1.IceGrid registry
    IceGrid.Registry.Client.Endpoints=tcp -h 192.168.1.3 -p 10000
    IceGrid.Registry.Server.Endpoints=udp -h 192.168.1.3 -p 10000
    ...
    
    2.Server
    Ice.Default.Locator=IceGrid/Locator:tcp -h 192.168.1.3 -p 10000
    

    bernard wrote: »
    I think you'd like a variable default, like "if all endpoints are udp, then use -d (datagram) as default". I guess it would be possible, but that's not how we specify proxies today.
    Yes, this is what I want. By this, the object adapter can make the most-possible right decision instead of a default "-t".
  • Maybe another solution is to add a new config item:)
    MyAdapter.Endpoints=udp -h 10.10.122.111 -p 9999
    MyAdapter.PublishedEndpoints=udp -h 211.133.122.111 -p 9999
    [COLOR="red"][B]MyAdapter.Endpoints.ProxyOptions="-d"[/B][/COLOR]
    

    Then the proxy created by the object adapter can be "objId -d:udp -h 211.133.122.111 -p 9999"
  • I am sorry that my guess about IceGrid in previous posts is wrong. IceGrid does not suffer from this question because it will simply throw away datagram endpoints.
  • bernard
    bernard Jupiter, FL
    Yes, all the IceGrid object adapters must use either tcp or ssl endpoints.

    Regarding the title of this thread: the behavior of ObjectPrx.toString() is not in question. Once you have a proxy, it's either twoway, oneway, datagram (...) and toString() must just output the corresponding option as it is.

    I think you're really talking about a new <adapter>.PublishedProxyOptions property, e.g.

    MyAdapter.Endpoints=udp -h 10.10.122.111 -p 9999
    MyAdapter.PublishedEndpoints=udp -h 211.133.122.111 -p 9999
    MyAdapter.PublishedProxyOptions=-d

    Maybe "-d" could be the default for this property when all endpoints are udp.

    And a separate question is for "stringToProxy": when there is no explicit -t/-d/-o, what should be the default? (Today, it's -t = twoway).

    Cheers,
    Bernard
  • bernard wrote: »
    And a separate question is for "stringToProxy": when there is no explicit -t/-d/-o, what should be the default? (Today, it's -t = twoway).
    This is my solution for stringToProxy:
    1.if all endpoints are udp, then use -d (datagram) as default.
    2.if all endpoints are tcp, then use -t (two way) as default.
    3.if the endpoints are mixed with tcp and udp, then check which is the first:
    1)if the first is an udp endpoint, then use -d as default.
    2)if the first is an tcp endpoint, then use -t as default.