In most applications we usually have a login page. That’s fairly simple to implement in GWT. Maintaining state after the login is not straightforward. Here’s how we achieve that in a typical GWT application.
Firstly, declare the Service methods that are available to Client.
@RemoteServiceRelativePath("LoginService") public interface LoginService extends RemoteService { /** * Utility class for simplifying access to the instance of async service. */ public static class Util { private static LoginServiceAsync instance; public static LoginServiceAsync getInstance() { if (instance == null) { instance = GWT.create(LoginService.class); } return instance; } } UserDTO loginServer(String name, String password); UserDTO loginFromSessionServer(); boolean changePassword(String name, String newPassword); void logout(); }
Implementation of the server side support for supporting this behaviour is as follows:
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService { private static final long serialVersionUID = 4456105400553118785L; @Override public UserDTO loginServer(String name, String password) { //validate username and password //store the user/session id storeUserInSession(user); return user; } @Override public UserDTO loginFromSessionServer() { return getUserAlreadyFromSession(); } @Override public void logout() { deleteUserFromSession(); } @Override public boolean changePassword(String name, String newPassword) { // change password logic } private UserDTO getUserAlreadyFromSession() { UserDTO user = null; HttpServletRequest httpServletRequest = this.getThreadLocalRequest(); HttpSession session = httpServletRequest.getSession(); Object userObj = session.getAttribute("user"); if (userObj != null && userObj instanceof UserDTO) { user = (UserDTO) userObj; } return user; } private void storeUserInSession(UserDTO user) { HttpServletRequest httpServletRequest = this.getThreadLocalRequest(); HttpSession session = httpServletRequest.getSession(true); session.setAttribute("user", user); } private void deleteUserFromSession() { HttpServletRequest httpServletRequest = this.getThreadLocalRequest(); HttpSession session = httpServletRequest.getSession(); session.removeAttribute("user"); } }
FInally, on the client clicking on the login button. we do the following:
LoginService.Util.getInstance().loginServer(txtfldUserName.getValue(), txtfldPassword.getValue(), new AsyncCallback<UserDTO>() { @Override public void onSuccess(UserDTO result) { if (result.getLoggedIn()) { RootPanel.get().clear(); // load the next app page //set session cookie for 1 day expiry. String sessionID = result.getSessionId(); final long DURATION = 1000 * 60 * 60 * 24 * 1; Date expires = new Date(System.currentTimeMillis() + DURATION); Cookies.setCookie("sid", sessionID, expires, null, "/", false); } else { Window.alert("Access Denied. Check your user-name and password."); } } @Override public void onFailure(Throwable caught) { Window.alert("Access Denied. Check your user-name and password."); } });
Most important validation to determine if session is still valid and appropriately redirect to the app page or directly to the login page back again. So, on the module load do these checks.
public void onModuleLoad() { String sessionID = Cookies.getCookie("sid"); if (sessionID == null) { displayLoginWindow(); } else { checkWithServerIfSessionIdIsStillLegal(); } } private void checkWithServerIfSessionIdIsStillLegal(String sessionID) { LoginService.Util.getInstance().loginFromSessionServer(new AsyncCallback<UserDTO>() { @Override public void onFailure(Throwable caught) { displayLoginWindow(); } @Override public void onSuccess(UserDTO result) { if (result == null) { displayLoginWindow(); } else { if (result.getLoggedIn()) { IndexPage w = new IndexPage(result.getName()); RootPanel.get().add(w); } else { displayLoginWindow(); } } } }); }
Do, drop in your comments. Hope it was useful.
Well halelujah, finaly some simple login tutorial with vanila GWT and with code examples. I was looking for something like this for days. Thank you, it helped a lot. BTW Do you have some project you can put into archive and post it here? It would be even better if yes
You can refer to this project : http://code.google.com/p/yfs-health/. I don’t have a separate project for this example.
Excelente…..
than you very helpful
Bravo! Examples rule! I love when people Show AND Tell!
When i close the browser, the cookies expire, why is this?
Probably, You need to set the expiry date properly(explicitly) in the cookie.
An example please?
Take a look at this : http://www.javacoffeebreak.com/faq/faq0059.html . However, you must be aware that the user can still clean up all cookies on browser exit – by using the “clean up cookies” on exit option.
Varun, I have the same issue as Fabrizio. I can’t see how this would work. As I understand it the session id is cleared when the browser is closed, so it cannot be reused when the browser is opened again, the web server has lost that information and cannot match the session id recovered from teh cookie on the client side. Can you double check please? Thanks.
SessionId is not cleared immediately when the browser is closed, it is subject to idle timeout on the browser and explicit logout issued from the client side.
Great. Fair and square. Simple, effective and complete! Worderful job!
thanks a lot for this tutorial, it was very useful for me however i have one question how generate the sessionid in UserDto?
Session Id is generated by the servlet/http container per “new” request. You dont need to do anything specific for it.
Could you just give an example?
What do you want an example for?
thank you for the reply, So i have to create an attribute “sessionId” in userDto and set the sessionId generated in this attribute?
Yes, if you need to keep track of the user session for some business reasons you could save the sessionid into the object.
ok, thank you 🙂
Thanks for the great example. I have one question.
In checkWithServerIfSessionIdIsStillLegal function, sessionID is passed as an argument. However, this seems not to be used at all. how does this work ?
True, sessionID is not required in the current implementation. I have removed that for now since we are checking with the server for the userdto within the session itself. Thanks for pointing that out.
Great post!! It clarifies the login validation process just fine! I have one question. The UserDTO class is something that you have implemented yourself or is it imported from some package? If it is your implemetation could you post the source code please? Sorry for the newbie question.
Yes its a user-defined class. It looks similar to the code available here: http://code.google.com/p/yfs-health/source/browse/trunk/yfs/src/com/varun/yfs/dto/UserDTO.java . You will need to add/remove the necessary attributes.
Let me know if it helps.
Thanks for the fast response!
Hello, can you tell me where are you setting the sessionId to userDto and how it is generated or where sessionId come from? Thanks
With respect to the example, SessionId is not stored in the userDto and it can be saved if required at the server side – you need not generate the sessionId, typically the generated sessionId is available in the HttpSessionEvent. You need to implement ‘HttpSessionListener’ interface – which has methods for sesssion created, destroyed from where you can get the sessionId or alternatively you can get it from the HttpSession object.
Hope that helps.
Thanks, so i can save the session id in server side, when i call the method storeUserInSession, and it would look like that …
private void storeUserInSession(UserDTO user)
{
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession(true);
user.setSessionId(session.getSessionId);//add this line to save session id into UserDto
session.setAttribute(“user”, user);
}
is it ok?
Yes, It looks ok.
Go ahead.
Thanks
Varun
Hello Varun again, i test it and it run ok. Thank for the fast answer.
looking into the code, i detect and tell if i am ok, that you are not really using the cookie.
you create it on button controller and check in module load
String sessionID = Cookies.getCookie(“sid”);
if (sessionID == null)
{
displayLoginWindow();
} else
{
checkWithServerIfSessionIdIsStillLegal();
}
if it exists you call checkWithServerIfSessionIdIsStillLegal(), but that method goes to server via rpc, and it really checks for the object user in session
UserDTO user = null;
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession();
Object userObj = session.getAttribute(“user”);
if (userObj != null && userObj instanceof UserDTO)
{
user = (UserDTO) userObj;
}
return user;
So If i am not wrong the user doesn’t have to loguin again while session lives and not while the cookie we had created lives.
am i ok?
Again thanks you so much for your help.
Yes, maintaining session information via session cookie is a standard way of implementing session based web applications. I did not use cookies because that is a standard way of doing it, the example shows that you can also maintain session by placing some User configuration – which serves both the purposes , session tracking and retrieving user-info.
I’ve got a problem when I’m doing that, I am getting :
No source code is available for type xxx.xxxx.Xxx..LoginService.Util; did you forget to inherit a required module?
For which code, please be more specific.
It’s on the line where I’m calling “LoginService.Util.getInstance().loginServer”
Implement the method LoginService.Util.getInstance() which will return the instance of Loginservice class by doing GWT.create(…)
How did you solve your problem? I have the same here 😦
It’s exactly what I did … So I don’t really understand why I’m getting this error ! I have, as you explained :
public interface LoginService extends RemoteService
public interface LoginServiceAsync {
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService
And I included :
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
There must be something wrong .. but I don’t know what
If it is eclipse error, try cleaning the project. Sometimes it works. Otherwise I think there is no compilation issue with the code. It is a working project.
I found the main problem, I got an error in my project ! Anyway, I have a new problem : I’m always going in the onFailure function. Do you have an idea why it doesn’t work ?
Thanks !
Simple and clean. Thanks!
Hi, thanks a lot for this tutorial! But can I ask you one thing, how I get the sessionID when user log in? After validate username and password.
You can get the sessionid on the serverside, from the Session/HTTPSession object after user/passwd is validated.
This was so helpful, thank you so much for posting it
Pingback: "Remember Me" login issue with returning the session ID to the client side | Solutions for enthusiast and professional programmers
hi, nice post, but the problem is – it is not working on cookie disable Browser. Can u implement the code by using “RPCManager.setLoginRequiredCallback(new LoginRequiredCallback() {…..}};” ….
i need how to get session id to this method…
I have not used/tried this API. You should be able to use any API if the callback is triggered after the login is successful, Because only after successful login will the session-id be saved -else you will observe that the session-id gets generated on every page refresh.
Hope that helps you.
Thank you bro!!!
That was excellent!!! 🙂 😉
hi …
if (result.getLoggedIn())
{
IndexPage w = new IndexPage(result.getName());
RootPanel.get().add(w);
} else
{
displayLoginWindow();
}
in above code What is IndexPage class? if you have code of IndexPage class …please can you send it me…
resolve? i have the same question to it.
What is in IndexPage class? Please let us know.
Something similar to this: https://code.google.com/p/yfs-health/source/browse/trunk/yfs/src/com/varun/yfs/client/index/IndexPage.java. It is a home-page to where the user gets redirected to after login is successful .
When I’m following your Code and implementing it into GWT sample code I get an error at this point:
greetingService.Util.getInstance().greetServer(textToServer,
new AsyncCallback() { … });
“Util cannot be resolved or is not a field”
What am I doing wrong?
nvm, changed greetingService to GreetingSercice and it works well!
Hi! Amazing tutorial! Thanks!
But I’m getting following error on UserDTO class, although I did import ExtGWT in it:
Line 8: No source code is available for type com.extjs.gxt.ui.client.data.BaseModelData; did you forget to inherit a required module?
What could I do?
Thanks for your feedback.
Please check if the gwt.xml has the import for the gxt module and the jar is in the classpath.
Another question – I downloaded gxt.jar from your source page https://code.google.com/p/yfs-health/source/browse/trunk/yfs/gxt.jar
Now I added inherit in gwt.xml, but now I’m getting another error:
[ERROR] Unable to find ‘com/extjs/gxt/ui/client/data/BaseModelData.gwt.xml’ on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?
I did put it in Build Path -> Libraries.
Sorry for newbie questions…
BaseModelData is from gxt, please read any hello-world tutorial on setting up gxt. That will tell you how to fix the entry in gwt.xml
thanks for all the help! just one more question – in which method I can check the username and password? That is, if they were correctly entered
See LoginServiceImpl.loginServer(UN,PW)
oct. 26, 2015 1:00:01 PM com.google.appengine.tools.development.LocalResourceFileServlet doGet
WARNING: No file found for: /atlas_emergency_status_page/LoginService
Also, getting this error when clicking login button. Although I did everything as written here.
I havent tested this code on the App-engine – I am sure it will not work either. App-engine has a better ways for integration with authentication and authorization – please check with the doc.
that would mean smth like this right?
public UserDTO loginServer(String name, String password) {
UserDTO user = new UserDTO();
if ((name == “atslimos”) && (password == “1234”)) {
storeUserInSession(user);
return user;
}
else return null;
}
this is reply about checking login and password
Yes that should work
Ok, thx, but still getting the previous error, even when typing correct username and password. Webpage gives “Access denied” window and in console no file found error
Please try the example on standalone installation without GAE. I guess it should work.
thanks, that was a good idea, but still getting error:
[WARN] 404 – POST /atlas_emergency_status_page/LoginService (127.0.0.1) 1405 bytes
Request headers
Host: 127.0.0.1:8888
Connection: keep-alive
Content-Length: 200
X-GWT-Module-Base: http://127.0.0.1:8888/atlas_emergency_status_page/
X-GWT-Permutation: 512BC5E71D8D41DD923CAA7193842B68
Origin: http://127.0.0.1:8888
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36
Content-Type: text/x-gwt-rpc; charset=UTF-8
Accept: */*
Referer: http://127.0.0.1:8888/ATLAS_Emergency_Status_Page.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,fr-CH;q=0.6,fr;q=0.4,ka;q=0.2,ru;q=0.2
Response headers
Content-Type: text/html;charset=ISO-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 1405
Now getting this, it still cannot find LoginService… It’s as though I didn;t add/declare it somewhere
Sad, Maybe you should deploy a hello-world app first and then put your changes one at a time.
I tried creating the simple project using all your code, but still getting the same error. As I understand, the server cannot find the file on client side LoginService
It seems that I need to put dependency somewhere, though I don’t quite understand where…
Thank you again for all your help.
Please ensure the LoginService etc. also appears in the web.xml. Maybe that is missing.
Dear Varun Tayur, thank you too much for article!!! It is a pitty that you do not have this project in archive (or on github). It will be usefull for new reader.
But in any case YOU have made really great work for all of us.
Goodluck!
Pingback: Gwt | melihtt