1

I understand how RAP creates scopes have a specific thread for each client and so on. I also understand how the application scope is unique among several clients, however I don't know how to access that specific scope in a single thread manner.

I would like to have a server side (with access to databases and stuff) that is a single execution to ensure it has a global knowledge of all transaction and that requests from clients are executed in sequence instead of parallel.

Currently I am accessing the application context as follows from the UI:

synchronized( MyServer.class ) {
    ApplicationContext appContext = RWT.getApplicationContext();

    MyServer myServer = (MyServer) appContext.getAttribute("myServer");
        if (myServer == null){
          myServer = new MyServer();
          appContext.setAttribute("myServer", myServer);
        }
    myServer.doSomething(RWTUtils.getSessionID());
}

Even if I access myServer object there and trigger requests, the execution will still be running in the UI thread.

For now the only way to ensure the sequence is to use synchronized as follows on my server

public class MyServer {
    String text = "";

    public void doSomething(String string) {
        try {
            synchronized (this) {
                System.out.println("doSomething - start :" + string);
                text += "[" + string + "]";
                System.out.println("text: " + (text));
                Thread.sleep(10000);
                System.out.println("text: " + (text));
                System.out.println("doSomething - stop :" + string);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Is there a better way to not have to manage the thread synchronization myself?

Any help is welcome

EDIT: To better explain myself, here is what I mean. Either I trust the database to handle multiple request properly and I have to handle also some other knowledge in a synchronized manner to share information between clients (example A) or I find a solution where another thread handles both (example B), the knowledge and the database. Of course, the problem here is that one client may block the others, but this is can be managed with background threads for long actions, most of them will be no problem. My initial question was, is there maybe already some specific thread of the application scope that does Example B or is Example A actually the way to go?

Eclipse RAP threads: how to handle shared knowledge and database access?

Conclusion (so far)

Basically, option A) is the way to go. For database access it will require connection pooling and for shared information it will require thoughtful synchronization of key objects. Main attention has to be done in the database design and the synchronization of objects to ensure that two clients cannot write incompatible data at the same time (e.g. write contradicting entries that make the result dependent of the write order).

Jarod
  • 35
  • 4

1 Answers1

1

First of all, the way that you create MyServer in the first snippet is not thread safe. You are likely to create more than one instance of MyServer.

You need to synchronize the creation of MyServer, like this for example:

synchronized( MyServer.class ) {
  MyServer myServer = (MyServer) appContext.getAttribute("myServer");
  if (myServer == null){
    myServer = new MyServer();
    appContext.setAttribute("myServer", myServer);
  }
}

See also this post How to implement thread-safe lazy initialization? for other possible solutions.

Furthermore, your code is calling doSomething() on the client thread (i.e. the UI thread) which will cause each client to wait until pending requests of other clients are processed. The client UI will become unresponsive.

To solve this problem your code should call doSomething() (or any other long-running operation for that matter) from a background thread (see also Threads in RAP)

When the background thread has finished, you should use Server Push to update the UI.

Community
  • 1
  • 1
Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79
  • Thanks for the reply. Yes, you are right my call to myserver is not safe, I just wrote this to test a concept, this is not a normal way to do it :) Anyway, I see a lot of examples on how to call a UI thread from the background but I don't know how to perform a background action from the UI. – Jarod Feb 18 '16 at 12:39
  • See the example code in the Server Push chapter, it is all there – Rüdiger Herrmann Feb 18 '16 at 12:46
  • Ah yes, okay I oversaw the "Thread bgThread = new Thread( bgRunnable );" lines. So, basically to obtain my single thread server I would only need to share this particular thread among clients, is that correct in your opinion? Thanks for the help! – Jarod Feb 18 '16 at 12:55
  • PS: or even easier make the MyServer Runnable and I start the bgThread at the launch of the server. – Jarod Feb 18 '16 at 12:58
  • The server does not need a thread. Each client that calls the server should to so in an extra thread to keep the UI responsive. You example will even work without threads. It will however block the UI of each client until the call to `server.doSomething()` returns. – Rüdiger Herrmann Feb 18 '16 at 13:06
  • Hmm okay, but if I have a database access, isn't it a problem if several clients perform request on the same connection in paralell? – Jarod Feb 18 '16 at 13:10
  • Usually yes. If so you need to use separate/pooled connections. – Rüdiger Herrmann Feb 18 '16 at 13:30
  • Even though it's is not quite the solution I was expecting/hoping for :) (lazy option B) in my image), I'll still validate the relevant inputs and comments. I added a conclusion to my post to sum up my thoughts based on your inputs. Thanks! – Jarod Feb 19 '16 at 10:20