How to intercept and allow user input from the server

Brief introduction:

I have a simulation [physics] that was a single-user desktop version. The framework serves as a toolkit for incorporating, for example, teachers to create different types of simulation setups without deep knowledge of Java programming and / or specific mathematics. In the end, the idea came up to apply the client-server paradigm to the structure in order to allow several clients to collaborate when working with the same simulator (= to synchronize the simulation for all clients).

Some additional technical facts:

Structure / simulations are based on the MVC pattern.

If the client makes changes to the simulation - for example, through the Swing GUI by moving the slider or drag and drop simulation elements - these changes must be allowed by the server before they are applied to the simulation (+ the server must take care to distribute the changes to all other clients, which should also apply them).

Authorization itself is very simple and basically only decides the timestamps whether to accept the changes (to avoid problems caused by clients with different delays causing changes in the same place for almost the same time).

The task, respectively, is the question:

Now I'm wondering what is the most elegant way to detect (and intercept) user inputs (pass them to the underlying messaging system responsible for client-server interaction)? Is there any model or best practice that is commonly used for the described scenario?

One of my main concerns is to avoid introducing new restrictions that must be taken into account by individuals using the framework to create new content (= simulations). In this sense, I would like the existing simulations to work with the minimum required changes.

One solution that I thought might work:

I was thinking about introducing a new interface, for example:

public interface Synchronizable { public boolean appliesChanges(); } 

The limitation in this case will be that listeners of changes of any type would have to additionally implement this interface if they want the change events that they listen to to be synchronized. Thus, the underlying infrastructure can replace all objects that implement Synchronizable with proxy objects responsible for checking the changes [events] with the server (and if the event is successfully forwarded to the real change listener).

The idea of ​​the applyChanges method is that not all calls to the change listener do lead to a change that requires synchronization. For example, Swing JSlider can generate events whenever the handle moves, but a particular change listener implementation can only apply the actual change after the handle is released (this value is no longer adjusted). Changing events occurring between them will not need to be sent to the server, since they have no effect. This approach would be neither convenient nor particularly beautiful, but I could not think of any other opportunity to solve the problem in a different way ?!

In addition to the problem that end users would have to explicitly think about what events they would like to synchronize (and, therefore, declare and implement the mentioned interface for all specific listeners), one of the remaining problems will be how to automatically find regardless on which specific method is responsible for processing events of an arbitrary type (to avoid the implementation of specific proxies for each possible listener for changes).

An example describing this problem:

 public interface SynchronizedChangeListener extends ChangeListener, Synchronizable {} public interface SynchronizedPropertyChangeListener extends PropertyChangeListener, Synchronizable {} public static void main(String[] args) { SynchronizedChangeListener scl = new SynchronizedChangeListener() { public void stateChanged(ChangeEvent e) { System.out.println("Hello world - SynchronizedChangeListener"); } public boolean appliesChanges() { return true; } }; SynchronizedPropertyChangeListener spcl = new SynchronizedPropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { System.out.println("Hello world - SynchronizedPropertyChangeListener"); } public boolean appliesChanges() { return true; } }; } 

How would a proxy listener know that for PropertyChangeEvents it should call the propertyChange method, whereas for ChangeEvents it should call the stateChanged method? Is reflection able to solve this problem?

We look forward to your contributions - I would be glad of any thought you may have, or any repetition in the literature on this topic.

+7
source share
3 answers

As I can see, you have a user interface in which the user can provide some input. You have another simulation user interface in which physical modeling is performed. Input from the user user interface must be submitted to another only after authorization of the server.

So far so good?

Now your modeling user interface should eventually expect events from your server. I was thinking of something like this:

  • Prepare an XML that contains the changes that the user wants from the user ui.
  • Deploy a simple servlet (or struts) on the tomcat server to parse this XML and respond to the user who requested it with authorization. The answer may also be in XML.
  • Send this authorization back to the simulation user interface through the queue. The simulation user interface should listen to this queue for any events superimposed on it.
  • This applies to one user scenario. For multiple users receiving events from the server, the easiest way to do this is to poll. Deploy a level timer in front of the simulation user interface that the server will poll. The server can respond with the latest changes. Now submit this to the simulation user interface queue.
0
source

I'm not quite sure that I understand your question, but based on it seems to be a concurrency problem that allows multiple clients to change the state of a service at the same time.

As I understand it, you have a client that allows the user to view the state of the system (your simulation) and change it. On the client side, you have an event-based MVC where the listener expects changes from the user interface and then passes the changes along with the client, which notifies the server. In a very rudimentary sense, for example:

 Today: -------- ------------------ ---------- | UI | - change event -> | Event Listener | - set value -> | Server | -------- ------------------ ---------- 

If I understand your proposed solution correctly, you want to intercept these events and first ask the server if someone has recently changed state before trying to make changes.

 Proposed: -------- ------------------ ------------------ ---------- | UI | - change event -> | Proxy Listener | - event -> | Event Listener | - set value -> | Server | -------- ------------------ ------------------ ---------- | timestamp | v ---------- | Server | ---------- 

In my opinion, this is not an ideal solution for various reasons. First, you talk to the server twice. Secondly, you will need to figure out how to create proxies for the various types of event handlers that exist, which you mentioned in the section “How to find out which method to call”. This will require either a lot of different proxy listeners, or some very dirty reflective logic. (Perhaps you could do this with dynamic proxies.) Finally, you need to rely on the proxy listener added every time, so concurrent security is not the default.

I think a more general solution that can be applied to your current use cases and any future extensions will look at making the setpoint call a secure server. This means that the server must detect when the Event Listener is trying to make changes to the current value (aka: the value is "out of date") and in this case, discard this change. In this case, there are two smaller problems: how to detect the change in an outdated state, and secondly, how to inform the client that the change has not been made.

For the first problem, you can implement some form of optimistic blocking. Like the proposed solution, you can use timestamps for this. For example, when the user interface displays, it will receive a value from the server. The server can pass the value as well as the timestamp when this value was last changed. When a user makes a change, the client passes the new value to the server and the initial last modified timestamp. (ie, “Server, set foo to 10 and the last time someone changed foo yesterday.”) Then the server knows if your change has the last value, and if not, it can refuse the change.

If you don’t have the ability to save the last modified timestamp with each value that can be changed, you can do the same with the hash. When the server returns the value to the client, calculate and return the hash with the value. When the server receives an update request, the client will send the hash, and the server can recalculate the hash from the value that it has. If they match, then the customer change is at the most recent value.

(Terminology warning: whether you use a timestamp or a hash, this value serves as a mutex.)

You do not provide much details about the interaction between the client and server, so I can only guess about the interface, but if the server has the ability to track clients in sessions on the server side, you can do the storage work and provide the corresponding mutex value completely on the server side. In this case, the server keeps track of what values ​​it provided to a particular client for a given session and what were the mutex values. When a client returns with an update request in the same session, the server can find the mutexes for this value and take the appropriate action, even if the client does not even know that the server is doing this. In this case, you can provide compatible code without changing your client from what it looks like today.

Regarding the second issue, how to notify the client that the change was rejected because it was deprecated, this should be relatively easy depending on the interaction of your client and server. If you are using some kind of SOAP or RPC that allows remote exceptions, I would recommend that you throw something similar to the Java ConcurrentModificationException. In this case, all you have to do is review, review the exception, and handle it accordingly. This probably means that the server should again get the latest value and probably notify the user that their requested update was not accepted, because the simulation state has changed from it.

0
source

Synchronization requires consensus. If you can tolerate some deviations (read gaps) in your simulations, you can allow clients to force the values ​​set at another station when distributing updates. If there is a local simulation clock, then updates can be sent with this value to prevent a potential change leading to different results.

Other answers address multiple communication issues and the possibility of synchronization using mutexes.

One approach is to block resources when they relate (perhaps with some kind of preference or redefinition of the instructor). Publish a lock to prevent local modifications, and then distribute updates until the lock is released.

You can avoid blocking if you have asymmetric clients where only designated users can control variables that make blocking implicit.

If you use multicast (for both real and pub-sub) of all client variables, then this can become part of a planned state update that does not require specific support (except your value is not adjusted ').

The real solution is whether you intend to allow updates with multiple wizards or restrict changes from a single source. This will fundamentally determine the algorithm, protocol, and implementation.

0
source

All Articles