First of all, I know that doing a synchronous call is "wrong", and know that "is not possible".
But, in a situation a lot complex (i dont know how to explain), i need to wait the response from server, I'am using the GWT-Platform command implementation for the GWT RPC calls.
I was looking for some kind of "hack" for doing this.
Thanks in advance.
Usually, by handling stuff in the onSuccess() function of your RPC request, you'll automatically "wait the response from server". So I assume you want to block all the code currently running? Since JavaScript is single-threaded that won't be easy, there is no sleep function that just halts the program.
But it might be that a hack using a timer does what you want:
Timer checkRPCResponse = new Timer() {
#Override
public void run() {
if (!serverResponseReceived) {
this.schedule(100);
} else {
proceedWithProgram();
}
}
};
checkRPCResponse.schedule(100);
I haven't tried out if the this.schedule(100) works in the above example, but you get the idea, which is a check if the server has responded every 100 ms. Of course you have to set serverResponseReceived = true yourself in the onSuccess() function. Call the timer right after the RPC.
There is a solution but it is not easy (e.g. you cannot flip a single parameter to make it work). GWT is using normal JS XMLHttpRequest under the hood. In GWT there is an overlay type for it called com.google.gwt.xhr.client.XMLHttpRequest. This class is used to send requests to the server over HTTP. Each JS XMLHttpRequest is first initialized by calling method open. This method has few parameters, but the third parameter specifies if the request should be asynchronous. If you change it to false, request will be synchronous.
But GWT-RPC doesn't use this class directly, it using it via RpcRequestBuilder, and this class is not using XMLHttpRequest directly as well, it is using RequestBuilder.
So what you'll need to do is to create customized version of RpcRequestBuilder and RequestBuilder (which will use XMLHttpRequest initialized to be synchronous).
The you can set RPCRequest builder to your GWT-RPC service instance, by casting it to the ServiceDefTarget.
Do you still want to have synchronous GWT-RPC requests?
GWT calls XMLHttpRequest.open() whith true as its third parameter which means the call will be asynchronous. I solved a similar need for testing purposes just forcing this third parameter to be always false:
private static native void fakeXMLHttpRequestOpen() /*-{
var proxied = $wnd.XMLHttpRequest.prototype.open;
(function() {
$wnd.XMLHttpRequest.prototype.open =
function() {
arguments[2] = false;
return proxied.apply(this, [].slice.call(arguments));
};
})();
}-*/;
After invoking fakeXMLHttpRequestOpen(), any further use of XMLHttpRequest will act synchronously. For instance:
remoteSvc.getResult(new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
GWT.log("Service called!");
}
#Override
public void onFailure(Throwable caught) {
GWT.log("Service failed...");
}
}
GWT.log("Last message");
will allways render:
Service called!
Last message
See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open for XMLHttpRequest.open() specification.
Related
I'm working on integrating an akka actors based backend within a vaadin application.
the problem i'm facing is i dare say simple (bear with me i'm a vaadin first timer :P).
Project structure (simplified)
2 modules front and backend.
my backEnd has an actor system that manages all the backend actors.
-> and a service class that has all relevant methods for necessary computations.
my frontEnd contains a single UI with a bunch of views.
-> and a second actor system that manages one UIActor (since backend actors can't access the UI)
needless to say the back-end is part of the front-end's dependencies.
The problem
In one of my views i have a click event handler that sends a message through the UIActor to one of the backEnd actors which in turn answers back once computations are done.
this is the "onReceive" method in the UIActor
public void onReceive(Object message) throws Exception {
if (message == "test") {
System.out.println("showing notification by "+currentUI);
currentUI.testMethod();
} else if (message instanceof MyUI) {
System.out.println("this is the ui actor test request forwarded");
currentUI = (MyUI) message;
backEndAgent.tell("check",getSelf());
} else {
unhandled(message);
}
}
the currentUI contains the return value of (MyUI) getCurrent(), sent as an message by the handler, in case you're wondering.
as for the testMethod it's pretty basic.
public void testMethod() {
Notification.show("Success", Notification.Type.HUMANIZED_MESSAGE);
}
unfortunately this call generates a null pointer in the Show method resulting from the Page.getCurrent() returning null.
So my question is why do i get a null pointer here?
also in my actor i send the currentUI reference as message because otherwise calling the getCurrent inside the UIActor returns null. any idea why?
EDIT
This is the new test method the page parameter is currentUI.getPage()
public void testMethod(final Page page) {
this.access(new Runnable() {
#Override
public void run() {
new Notification("Success",Notification.Type.HUMANIZED_MESSAGE).show(page);
}
});
}
this solves the problem somehow but only shows the notification after i click the button a second time but not the first time.
This is driving me crazy.
Notification.show() uses Page.getCurrent() to fetch the current page. Page.getCurrent() is a ThreadLocal which is set during a traditional HTTP request-response cycle meaning that Notification.show() works (doesn't return null) during the HTTP request-response thread.
In you case Notification.show() is called outside the HTTP request-response thread and that's why it returns null. If I understand correctly from your code, currentUI is reference to your current UI and it's not null. In that case you could change your code from
public void testMethod() {
Notification.show("Success", Notification.Type.HUMANIZED_MESSAGE);
}
to
public void testMethod() {
new Notification("Success", Notification.Type.HUMANIZED_MESSAGE).show(getPage());
}
The modified version doesn't use Page.getCurrent() anymore but gets the current page from the getPage() method of your UI instance.
EDIT. Forgot to add important information related to actors / external threads accessing Vaadin code:
The actor calling the method to show a notification is an external thread from the Vaadin point of view. Vaadin assumes that access to Vaadin components and Vaadin related other objects is locked/syncronized properly. A proper locking/syncronization is in place when the traditional HTTP request-response thread is used but when an external thread (e.g. actor) is accessing those, the developer must ensure locking. One way to ensure locking is to use UI.access:
getUI().access(new Runnable() {
#Override
public void run() {
// insert your code accessing Vaadin related objects here
}
});
The reason why you see the notification after clicking a button is that browser doesn't know that there is something to show when an actor calls Notification.show. The request caused by a button click pulls changes from the server to the browser and then the notification is show. To see changes from actors / external threads without user interaction (e.g. a button click) the application must use polling or push. To enable polling, setPollInterval for your ui.
I am using GWT for my web application. I have three RPC requests to server methods. I am calling these functions one after the other in Client side. I am not able to get results for all three functions. I know that asynchronous requests are made to server methods and order of execution may not be same as the order in which methods are called. But I am not able to get result for one of the methods. Will queueing RPC requests solve the problem ?
First of all the question is not at all clear,GWT-RPC is one of the approach to communicate Client to Server,Client is never blocked during communication.
Yes you need maintain a queue like let say you have two request LoginInfo Request and LoginAuth Request then first call LoginInfo Request then onSuccess of LoginInfo call LoginAuth Request,
service.LoginInfo(new AsyncCallback() {
public void onSuccess(Void result) {
// services.LoginAuth(new AsyncCallback(){.....
}
public void onFailure(Throwable caught) {
// do some UI stuff to show failure
}
};
The question might seem stupid/trivial and might be, but I simply cannot understand how to achieve my goal. (Sorry if the title is misguiding, couldn't think of a better one)
I have a webpage on a App Engine server which uses GWT. I got client code and server code. The client code can call RPC methods without any problem (my problem has nothing to do with the "gwt-client" at all).
I got the following classes:
//MyClassService.java - client package
#RemoteServiceRelativePath("myService")
public interface MyClassService extends RemoteService{
public doSomething();
}
//MyClassServiceAsync.java - client package
public interface MyClassServiceAsync{
public void doSomething(AsyncCallback<Void> callback);
}
//MyClassServiceImpl.java - server package
public class MyClassServiceImpl extends RemoteServiceServlet implements MyClassService{
#Override
public void doSomething()
{
//does something
}
}
A scenario and what I want to do:
I've got a remote client, in other words, a client who's not connecting through the page via the "GWT-interface", it's a client who's simply making GET, POST requests to a path on the server (from elsewhere). This remote client is not "using" GWT at all. The client is connecting through an HttpServlet, inside this servlet I want to reuse the RPC mechanics so that i don't have to rewrite the interfaces, who are on the client side and using client-dependent code (the implementation is already server-side).
To reuse the existing methods on the server-side I could create an instance of MyClassServiceImpl.java and just use those. BUT as you can see above, they are implemented as synchronous methods, since GWT-RPC automatically makes the calls asyncronous when using the GWT-RPC.
How would i go about to reuse the MyClassServiceImpl on the server-side and also get them as asynchronous?
Also if I'm wrong with the approach I'm taking, please suggest some other solution. For example, one solution might be for the remote client to directly communicate with the RemoteServiceServlet instead of creating a HttpServlet which the client connects through, but I don't know if that's possible (and if it is, please tell me how)!
Thank you!
EDIT (thanks to some answers below I got some insight and will try to improve my question):
The server-side implementation of the methods is SYNCHRONOUS. Meaning they will block until results a returned. When invoking these method from the gwt-client code, they are 'automatically' made ASYNCHRONOUS one can call them by doing the following:
MyClassServiceAsync = (MyClassServiceAsync) GWT.create(MyClassService.class);
ServiceDefTarget serviceDef = (ServiceDefTarget) service;
serviceDef.setServiceEntryPoint(GWT.getModuleBaseURL() + "myService");
service.doSomething(new AsyncCallback<Void>() {
#Override
public void onSuccess(Void result) {
//do something when we know server has finished doing stuff
}
#Override
public void onFailure(Throwable caught) {
}
});
As you can see from the above code, there is support for the doSomething method to take an AsyncCallback, without even having the implementation for it. This is what I wanted on the server-side so i didn't have to use threads or create a new implementation for "async-usage". Sorry if I was unclear!
1) Any client can call MyClassServiceImpl.doSomething() with the current configuration. MyClassServiceImpl is a servlet and properly exposed. In order to achieve communication this way, the client must be able to "speak" the GWT dialect for data transportation. Google may provide you with libraries implementing this. I haven't used any, so I cannot make suggestions.
An example, proof-of-concept setup: Check the network communications with Firebug to get an idea of what is going on. Then try calling the service with curl.
2) If you do not want to use the GWT dialect, you can easily expose the same service as REST (JSON) or web services (SOAP). There are plenty of libraries, e.g. for the REST case RestEasy and Jersey. You do not mention any server-side frameworks (Spring? Guice? CDI?), so the example will be simplistic.
I'd suggest implementing your business method in a class independent of transportation method:
public class MyBusinessLogic {
public void doSomething() {
...
}
}
Then, the transport implementations use this business logic class, adding only transport-specific stuff (e.g. annotations):
GWT:
public class MyClassServiceImpl extends RemoteServiceServlet implements MyClassService{
#Override
public void doSomething() {
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}
JAX-RS:
#Path("myService")
public class MyResource {
#GET
public void doSomething() {
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}
So the transport endpoints are just shells for the real functionality, implemented in one place, the class MyBusinessLogic.
Is this a real example? Your method takes no arguments and returns no data.
Anyhow you can create a new servlet and invoke it via normal HTTP request. The servlet then just invokes the target method:
public class MyNewServlet extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response){
MyBusinessLogic bean = ... // get it from IoC, new, whatever
bean.doSomething();
}
}
I'm getting confused a bit when it comes to Synchronous calls, and Asynchronous calls in GWT.
I am sure that GWT is makes Async calls.
It's clear to me that Synchronous is just waiting for the response, and after getting that response, executing the next command.
It is not in the case of Asynchronous, because it never waits for the response. Before getting the response it executes the next command right away.
But I can see in some blogs is says that RPC is Synchronous.....
Whereas GWT which uses RPC is not Synchronous. I understand that whenever I send the request it never waits.
Is RPC really synchronous?
If so how does GWT make Async RPCs?
or did I misunderstand anything?
GWT RPC(Remote Procedure Calls) is Asnyc for sure. Actually, All of implementations which are based on AJAX are all Asnyc.
Let's take a look on the example below:
emailService.emptyMyInbox(fUsername, fPassword, new AsyncCallback() {
public void onSuccess(Void result) {
// do some UI stuff to show success
}
public void onFailure(Throwable caught) {
// do some UI stuff to show failure
}
};
// do something more
We call the service on first line, right after the execution, the browser will execute the line // do something more, regardless of if the result returned or not.
For more information, see Dev Guide Server Communication
If I can do this, how do I call Java code (methods for instance) from within JavaScript code, in Wicket.
erk. The correct answer would be ajax call backs. You can either manually code the js to hook into the wicket js, or you can setup the callbacks from wicket components in java.
For example, from AjaxLazyLoadPanel:
component.add( new AbstractDefaultAjaxBehavior() {
#Override
protected void respond(AjaxRequestTarget target) {
// your code here
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead( response );
response.renderOnDomReadyJavascript( getCallbackScript().toString() );
}
}
This example shows how to add call back code to any Component in Wicket. After the OnDomReady event fires in your browser, when loading a page, Wicket will cause it's js enging, to call back into your code, using Ajax, to the 'respond' method shown above, at which point you can execute Java code on the server, and potentially add components to the ajax target to be re-rendered.
To do it manually, from js, you can hook into wicket's system by printing out getCallbackScript().toString() to a attribute on a wicket component, which you'll then be able to access from js. Calling this url from js manually with wicket's wicketAjaxGet from wicket-ajax.js.
Check out the mailing list for lot's of conversation on this topic:
http://www.nabble.com/Wicket-and-javascript-ts24336438.html#a24336438
Excerpt from https://cwiki.apache.org/WICKET/calling-wicket-from-javascript.html
If you add any class that extends AbstractDefaultAjaxBehavior to your page, wicket-ajax.js will be added to the header ofyour web page. wicket-ajax.js provides you with two basic methods to call your component:
function wicketAjaxGet(url, successHandler, failureHandler, precondition, channel)
and
function wicketAjaxPost(url, body, successHandler, failureHandler, precondition, channel)
Here is an example:
JavaScript
function callWicket() {
var wcall = wicketAjaxGet('$url$' + '$args$', function() { }, function() { });
}
$url$ is obtained from the method abstractDefaultAjaxBehavior.getCallbackUrl(). If you paste the String returned from that method into your browser, you'll invoke the respond method, the same applies for the javascript method.
You can optionally add arguments by appending these to the URL string. They take the form &foo=bar.
you get the optional arguments in the Java response method like this:
Map map = ((WebRequestCycle) RequestCycle.get()).getRequest().getParameterMap();
or this:
String paramFoo = RequestCycle.get().getRequest().getParameter("foo");
http://www.wicket-library.com/wicket-examples-6.0.x/index.html/ has plenty of examples to get you going.
Or have a Have a look at DWR
http://directwebremoting.org/
DWR allows Javascript in a browser to interact with Java on a server and helps you manipulate web pages with the results.
As Dorward mentioned this is done via AJAX
Assuming you mean JavaScript running on the client - you cause an HTTP redirect to be made to the server, and have your servlet react to the request for the given URL.
This is known as Ajax, and there are a number of libraries that help you do it..