Reputation: 1624
What is the best way to perform an initial RPC call at startup with GWT?
I would like to retrieve configuration data that are dynamically generated on the server side, when a user loads a page. but If I do an asynchronous RPC call from the browser to retrieve the data, I sometimes don't get a response before the page is fully loaded, resulting in the page not having access to that configuration data. (no Thread.sleep() function for example)
thanks
thanks to @Steve-J's response, I found a solution...
Basically the idea is the following:
et voila...
The initial RPC call is completed before doing anything else...
Is there anything wrong with that approach?
Note that as suggested by @Tom-Miette it is nice have a simple "loading..." message until the StartupCompleted event is received.
Upvotes: 2
Views: 2254
Reputation: 3361
FWIW I had a solution that involves suspending EntryPoint.onModuleLoad() until the RPC returns.
I was using dependency injection and GWTP Dispatch which kind of complicated the bootstrap process. I also wanted the result to be a singleton instance in my system (client side).
The result was a GWT native (no command pattern) RPC call that launched dependency injection upon success.
EntryPoint class snippet:
@Override
public void onModuleLoad() {
SessionInfoProvider.init(new Runnable() {
@Override
public void run() {
// can now complete setup
AppInjector injector = GWT.create(AppInjector.class);
injector.bootstrap();
}
});
}
SessionInfoProvider snippet:
public class SessionInfoProvider implements Provider<SessionInfo> {
private static SessionInfo.Bean sessionInfo;
/**
* Needs to be called before the module is used.
*/
public static void init(final Runnable onCompletion) {
GreetingServiceAsync s = GWT.create(GreetingService.class);
s.loadSessionInfo(new AsyncCallback<SessionInfo.Bean>() {
@Override
public void onFailure(Throwable caught) {
GWT.log("Failed to retrieve Session Info");
}
@Override
public void onSuccess(SessionInfo.Bean result) {
GWT.log("Successfully retrieved session info bean. Username:" + result.getUserName());
sessionInfo = result;
onCompletion.run();
}
});
}
@Override
public SessionInfo get() {
if (sessionInfo == null) throw illegalState("Session Info not ready.");
return sessionInfo;
}
}
Upvotes: 0
Reputation: 2674
Are you using messaging for control flow? I do the RPC call, and on success, I send the message that triggers the first active popup for the user to interact with. On failure, a different message is fired that triggers a popup to tell the user that he can't proceed.
Don't forget to enable the glass panel on your popups so that the user can't mess with anything in the background while he is waiting.
Update: From the comments: "But my problem is that the user can bookmark a page, and go directly to it without any interaction. I may end up in a case where I have not received the result of the RPC call, but where I am generating the page he has requested. Even if in that generation I try to check if I've received the result, I can't pause until that's the case before completing the generation of the page."
Ah, I see. OK, GWT has a solution for this. You should look at Activities and Places. When the user bookmarks a "page", he is really bookmarking the state of the GWT application. When he returns to that "page", the Activity is fired and automatically calls the start() method. This is your opportunity to retrieve data from a server and do any other setup that is required. Once you have your data, your start() method proceeds to set up what is called the "view". From the user's perspective, the "page" has "loaded".
Upvotes: 3
Reputation: 129
Cover your html page with a kind of "loading screen":
<div
id="loading"
style="
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: black;
color: white;"
>
Loading...
</div>
and just remove it when the RPC has succeeded/failed:
RootPanel.get("loading").getElement().removeFromParent();
Upvotes: 0
Reputation: 3238
Not sure if its the best way but a good way is to avoid the initial call altogether and use a jsp page instead of a html page as your entry point into the application. You can then set variables for your initial state in javascript in the page server side e.g.
<script type="text/javascript">
var InitialState = {
"userName" : "<%= userName %>",
"emailAddress" : "<%= emailAddress %>",
etc...
};
In your GWT app you can read these values using the GWT Dictionary class
Dictionary state = Dictionary.getDictionary("InitialState");
String userName = state.get("userName");
String emailAddress = state.get("emailAddress");
Upvotes: 3