Archived

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

Manual control of a Glacier2 client

Hi,

I'm quite a beginner in Ice and I'm working on an application where I need a component to use a Glacier2 client as a communication port to some server. All the demos and examples I read have the client program inheret from Glacier2::Application and calling the "main" function which takes care of session creation and the main event loop.

What I want is manual control over the client so that the main event loop will reside in my component and not the Glacier2 client. The component can manual create/destroy sessions, send messages...etc.

Regards,
Michael

Comments

  • xdm
    xdm La Coruña, Spain
    Hi,

    For Java and C# there are also GUI Helper Classes see java/demo/Glacier2/chat or cs/demo/Glacier2/chat for sample usage. The Chat Demo also made use of these classes.
  • Hi,

    I forgot to mention that I'm looking for such functionality in C++. I read the Java example before but I'm having some hard time porting it to C++ so I'm wondering if it's feasible in the first place.

    I apologize for that.

    Regards,
    Michael
  • xdm
    xdm La Coruña, Spain
    A C++ version of this classes is available with IceTouch-1.2.0 C++ SDK, download the source distribution and see files under "IceTouch-1.2.0/cpp/src/Glacier2Lib/" directory, you can compile that files with your C++ application and will probably work, let us know if you found any issue. Next Ice release is likely to also include that GUI C++ helpers.
  • Hi,

    This sounds like a good idea but I'm working on a highly distributed system involving robotic entities. I don't actually need to have a GUI but I'm following a component-based methodology in my design and wanted to separate the communication port (Client) from the rest of the application. I'm pretty sure there is a work-around.

    Thanks for you prompt response.

    Regards,
    Michael
  • xdm
    xdm La Coruña, Spain
    Note that even we have named it "GUI Helper Classes" this classes aren't GUI specific just that the common use cases is GUI applications. Also if you look at the implementation you will see what is required to manually create something similar that is more appropriate to your needs.
  • GUI Helper classes

    Hi,

    I'm studying the Java chat UI demo closely since I'm working on an application where I need to have full control over the client program instead of having the control in the ICE main loop. As far as I understand, this part:
    initData.dispatcher = new Ice.Dispatcher()
                {
                    public void
                    dispatch(Runnable runnable, Ice.Connection connection)
                    {
                        if(_exit)  // The GUI is being destroyed, don't use the GUI thread any more
                        {
                            runnable.run();
                        }
                        else
                        {
                            SwingUtilities.invokeLater(runnable);
                        }
                     
                    }
                };
    

    is for delegating the control to the GUI thread. However, I want to have another thread to delegate the control true. I can't seem to understand how can I accomplish that in the code.

    Another problem is that I get this error whenever I compile and user my own jar:
    Exception in thread "AWT-EventQueue-0" java.lang.NoSuchMethodError: Chat._ChatRoomCallbackDisp.__checkMode(LIce/OperationMode;LIce/OperationMode;)V
    	at Chat._ChatRoomCallbackDisp.___init(_ChatRoomCallbackDisp.java:152)
    	at Chat._ChatRoomCallbackDisp.__dispatch(_ChatRoomCallbackDisp.java:250)
    	at IceInternal.Incoming.invoke(Unknown Source)
    	at Ice.ConnectionI.a(Unknown Source)
    	at Ice.j.run(Unknown Source)
    	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
    	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:647)
    	at java.awt.EventQueue.access$000(EventQueue.java:96)
    	at java.awt.EventQueue$1.run(EventQueue.java:608)
    	at java.awt.EventQueue$1.run(EventQueue.java:606)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:105)
    	at java.awt.EventQueue.dispatchEvent(EventQueue.java:617)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
    	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
    	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
    
    

    I'm kindly asking for an explanation.

    Regards,
    Michael
  • xdm
    xdm La Coruña, Spain
    Hi Michael,

    Not sure if i understand your first question, you want your dispatcher implementation to dispatch requests to a thread of your own, but not to Swing UI thread?

    What you can do is to have your thread acting as a work queue, and the dispatcher will just push requests to the queue, a simple implementation (not tested) could be:
    class DispatchWorkQueue extends Thread
    {
        public void run()
        {
            while(true)
            {
                Runnable r = null;
                synchronized(this)
                {
                    while(_queue.isEmpty())
                    {
                        try
                        {
                            wait();
                        }
                        catch(java.lang.InterruptedException ex)
                        {
                        }
                    }
                    assert !_queue.isEmpty();
                    r = _queue.remove(0);
                }
                r.run();
            }
        }
    
        synchronized public void enqueue(Runnable r)
        {
            if(_queue.isEmpty())
            {
                notify();
            }
            _queue.add(r);
        }
    
        private java.util.List<Runnable> _queue = new java.util.LinkedList<Runnable>();
    }
    
    
    _queue = new DispatchWorkQueue();
    _queue.setDaemon(true);
    _queue.start();
    initData.dispatcher = new Ice.Dispatcher()
        {
            public void
            dispatch(Runnable runnable, Ice.Connection connection)
            {
                _queue.enqueue(runnable);
            }
        };
    

    As for the second problem we will need some more information, specially what OS, Ice, Java versions are you using.

    If you are using proguard , for the stack-trace seems you are , what proguard version, can you reproduce the problem without using proguard?
  • GUI Helper classes

    Hello,

    Thanks for the prompt reply. I apologize for the ambiguities. Specifically, in my application I'm planning to have a Java servlet periodically call (poll) the ICE client for updates and so it's very important that the servlet is not blocked by the event thread. Basically, when the server pushes data to the client, the client will store them and should also provide methods to enable external applications to acquire these data.

    I understand that there is the PHP and SilverLigh ICE web-clients that can do the job but I need to have a Java web-based app (not applets).

    As for the exception, I'm using Java "1.6.0_23" and running on a Linux machine. I'm not using proguard.

    Regards,
    Michael
  • xdm
    xdm La Coruña, Spain
    For your Servlet i don't recommend to use Glacier2.SessionHelper unless you want to have just one session, as you will need a helper per session and this will create a different communicator for each session, if you have just one session is fine to use the Glacier2 helper classes.

    Your Servlet implementation can initialize Ice run-time as part of the Servlet initialization.

    Then you can implement an Chat Callback that just store the messages it receives as a list of objects.

    See the PollCallbackAdapter implementation in PollingChatSessionI.cpp the file is part of C++ ChatDemo server, here you can see how we do that in C++ server.

    In C++ the callback is a local object in the server, in your case it will be a remote Ice object (The callback you pass to Session.setCallback), but is the same idea, the callback convert invocations in event objects and store the objects in a list, when a user poll the Servlet for updates you just need to return the objects in that list.

    If your Servlet must not block during session creation, you must provide some mechanism to know if the session creation has succeed or not, store the results and allow the user to poll for the completion status via HTTP, if you have just one session or a limited set of sessions you can also consider to create the sessions as part of the Servlet initialization.

    As for the InitData.dispatcher, you don't need to use one, when you don't use a dispatcher requests will be dispatched in one of Ice threads, and this will not block your application.

    In your Servlet scenario the use of Ice.Dispatcher doesn't supposes any advantage, the Ice.Dispatcher is mostly useful if you want the invocations to be tied to a specific thread, for example the SWING thread so the application can directly manipulate the UI controls from the callback implementation.

    If your Client Callback use proper synchronization you should not care about what thread call it.

    For your second problem can you post the complete output of your build command, and upload the result JAR file.
  • GUI Helper classes

    Hello,

    Why do you advise against using Glacier2.SessionHelper unless I have one session. In my app multiple clients will communicate with a servlet. Upon request the servlet will create a separate client object for each client, each having its own state and session. What I have in mind (in an abstract way) is that a client object will have these methods:
    createSession ();
    closeSession ();
    getData (); 
    

    The client object will basically be a wrapper for an ICE client, albeit a non-blocking one since it'll be acted upon based on requests coming into the servlet. My app will be a multi-tiered one: each web-client communicates with its own client object through the servlet, and the client object communicates with the backend ICE server.

    I understand there is a substantial overhead but I'm only expecting a handful of clients.

    I'll work on this matter and get back if I have other issues. As for the other problem I'd put it aside for now.

    Regards,
    Michael
  • xdm
    xdm La Coruña, Spain
    If your application has just a few clients Glacier2.SessionHelper is fine, but creating a communicator per client will be an overhead if you have many clients.