We are converting a third-party JavaScript component to be a Vaadin component. Can someone give me an idea of how we could handle the following situation?
The way the JS component is designed, it allows the programmer using the component to define some callback functions in JS. These user-defined callback functions must return a value, which is then used by the component to proceed in its path of execution.
How can I define these synchronous callback functions in the Vaadin world?
After struggling with this for a while, we came to the conclusion that there is ABSOLUTELY NO WAY that the browser can make a synchronous call to the server side Vaadin. I hope our conclusion is wrong. Can someone please prove us wrong?
So we are handling the problem as follows:
The programmer using the Vaadin component has to set a string that defines a JS function. This string is then passed to the Vaadin component, which in turn passes it down to gwt to set it as the callback function for the JS component.
This solution, of course, has two problems:
The programmer using the Vaadin component has to write JS code, rather than Java code, which goes against the primary reason to use Vaadin.
Typical JS issues like cross browser incompatibility, lack of compile time error detection, etc.
Browsers can not make synchronous calls to servers. All they do is ajax (Asynchronous …).
What you need is to cache the info needed by the javascript component in client. When the javascript asks for the info, just return the known state. When you get a new state from the server (maybe with normal Vaadin updateFromUIDL()), ask the javascript component to update itself again.
Thanks. There is a programmer-defined computation that needs to happen in these callbacks. So the caching idea probably may not fit here.
btw, I have a different question, related to this situation.
Can you think of a way we can embed native gwt java code in a vaadin app? In other words, I’m looking for an equivalent to the Vaadin Window method executeJavaScript(…) for gwt java code, where I can say executeGWTJava(…).
Actually, it’s the opposite. Synchronous XHR calls are perfectly doable, and Vaadin even uses thoses for window close events (as far as I remember).
So you can make synchronous AJAX (SJAX?) calls to your server using JavaScript, but do note that this will in effect “hang” the browser while it’s waiting for the response from the server.
Do you want the “GWT Java” to be dynamic at runtime ?
If you want code executed in the browser, it has to be in javascript; if you want to execute “GWT Java” in the browser, it would have to be compiled to javascript - and this would be very slow. I am sure there would be lots of other problems involved too - honestly, I really wouldn’t even start thinking about trying this.
If, however, you are talking about using the GWT RPC Mechanism - i.e. call the server side code from a Widget in the browser, using RPC - that probably is possible; mind you, thanks to Vaadin, I’ve had no need to dabble in GWT for some time.
With regular JavaScript we can definitely make synchronous request. If I want to make synchronous request in Vaadin, what API should be used in Vaadin terminal class?
The ApplicationConnection class contains protected method makeUidlRequest.
makeUidlRequest(final String requestData,
final String extraParams, final boolean forceSync)
Can method ApplicationConnection.sendPendingVariableChangesSync() be used for this purpose?
I used javascript call throw JSNI making a custom gwt component:
/**
* Called whenever an update is received from the server
*/
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
...
...
exportGetMac(this);
}
// Expose the following method into JavaScript.
private void getWifiMac (String mac) {
this.client.updateVariable(paintableId, "mac", mac, true);
}
// It is only used to create a reference in the browser to the final method
private native void exportGetMac(VMQTTClient instance) /*-{
$wnd.getMac = function(mac) {
instance.@com.thingtrack.mqtt.client.gwt.client.VMQTTClient::getWifiMac(Ljava/lang/String;) (mac);
};
}-*/;
Tha you I expose the getWifiMac throw JSNI if you call this js script: getMac(“00-23-25-23-22-20”); the js callback getWifiMac will fire and client side recover the value and send to server side like you see.
I use this tecnique to comunicate android native side with vaadin touchkit web addon