This tutorial concerns using Google Accounts to maintain the existence of your users in a Google App Engine application.
Google App Engine provides the class UserServiceFactory to facilitate that. UserServiceFactory is then used to generate UserService object, which in turn provides the following features
createLoginURL
createLogoutURL
getCurrentUser
isUserAdmin
isUserLoggedIn
You would use UserService object to generate the login URL for the browser. The browser would be directed/redirected to this URL. On reaching this URL, the Google log-in prompt would be displayed by Google's server.
Once logged in, your application could use the UserService object to inquire about the current user.
However, UserServiceFactory should be used on the server side not the client side. You cannot include it as part of your GWT module because
- GWT compiler would request for the source code of UserServiceFactory and UserService - because GWT compiler needs to be presented all source code that is to be compiled into Javascript.
- You cannot run UserServiceFactory and UserService on GWT client because they need to access Google's internal server-side objects.
If that is the case, how then do you pass UserService information to the GWT client? Simple - use RPC.
Server-side interface
You need to create a server-side GWT RPC interface similar to the following.
public interface UserServiceWrapper
extends RemoteService{
String createLoginURL(String callbackUrl);
String createLoginURL(String callbackUrl, String authDomain);
String createLogoutURL(String callbackUrl);
String createLogoutURL(String destinationURL, String authDomain);
UserInfo getCurrentUser();
boolean isUserAdmin();
boolean isUserLoggedIn();
}
RPC servlet
Then your RPC server-side servlet would implement that interface
public class UserServiceServlet
extends RemoteServiceServlet
implements UserServiceWrapper
{
final static public UserService userService = UserServiceFactory.getUserService();
@Override
public String createLoginURL(String callbackUrl) {
return userService.createLoginURL(callbackUrl);
}
@Override
public String createLoginURL(String callbackUrl, String authDomain) {
return userService.createLoginURL(callbackUrl, authDomain);
}
@Override
public String createLogoutURL(String callbackUrl) {
return userService.createLogoutURL(callbackUrl);
}
@Override
public String createLogoutURL(String destinationURL, String authDomain) {
return userService.createLogoutURL(destinationURL, authDomain);
}
@Override
public UserInfo getCurrentUser() {
return mkUserInfo(userService.getCurrentUser());
}
@Override
public boolean isUserAdmin() {
return userService.isUserAdmin();
}
@Override
public boolean isUserLoggedIn() {
return userService.isUserLoggedIn();
}
static public SeriUser mkSeriUser(User user){
return new SeriUser(
user.getAuthDomain(),
user.getEmail(),
user.getNickname(),
user.getUserId()
);
}
}
You cannot pass Google User object to a GWT client, unless you have the source code or fake the source code for User class. The simple way is to define a serializable SeriUser class and pass an instance of that class to the GWT client.
Client-side interface
Google Plugin for Eclipse would then aid you to create the client-side RPC interface:
public interface UserServiceWrapperAsync{
void createLoginURL(
String callbackUrl,
AsyncCallback<String> callback);
void createLoginURL(
String callbackUrl, String authDomain,
AsyncCallback<String> callback);
void createLogoutURL(
String callbackUrl,
AsyncCallback<String> callback);
void createLogoutURL(
String destinationURL, String authDomain,
AsyncCallback<String> callback);
void getCurrentUser(
AsyncCallback<UserInfo> callback);
void isUserAdmin(
AsyncCallback<Boolean> callback);
void isUserLoggedIn(
AsyncCallback<Boolean> callback);
}
Client-side call
Let us say you have a GWT main client window with a MenuBar.
public class MainMenuBar
extends Composite{
private final UserServiceWrapperAsync userInfo =
GWT.create(UserServiceWrapper.class);
.....
final Command doLogin = new Command(){
@Override public void execute() {
userInfo.createLoginURL(
"googleLoggedin.jsp",
loginCallback
);
}
AsyncCallback<String> loginCallback = new AsyncCallback<String>()
{
@Override
public void onSuccess(String loginUrl) {
popupFrame.showPage(loginUrl, "Google Log-in");
}
@Override
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
};
....
}
On your MenuBar, you would have a MenuItem [Log in to Google].
- On clicking this item, it would execute a Command doLogin to either create a NamedFrame in the main window or show a DialogBox embedded with a NamedFrame.
- Here, popupFrame is the instance of a class extension of DialogBox, which creates a NamedFrame by providing it with the Google login URL.
- The NamedFrame would access that URL where a Google server would display the Google Accounts log-in page.
- When users authenticate their account with Google successfully, Google server would redirect the page to the URL of your page which is stored in the String entryPointURL.
- Hopefully, you have provided a close button on your DialogBox or NamedFrame to either close the frame or the DialogBox.
- On closing the DialogBox or Frame, the onClose listener would trigger the MenuBar to update itself to show the current user.
The MenuBar would fire a RPC call
userInfo.getCurrentUser()to the server in order to list the user.
To logout, a MenuItem [Log out] would similarly fire a RPC call to the server
userInfo.createLogoutURLgo through the whole whatnots similar to logging in.

thank you, article is exactly that i am looking for.
ReplyDeletethank you so much, great article. You just save my life
ReplyDeleteNice article, do you have the code to download and play with? Tks.
ReplyDeletewhat classes are you using for SeriUser and UserInfo
ReplyDeletePlease refer to this similar but complete example here
ReplyDeletehttp://code.google.com/webtoolkit/doc/latest/tutorial/appengine.html