problems with auto-complete form login

76 views
Skip to first unread message

Magnus

unread,
Aug 30, 2010, 1:45:20 AM8/30/10
to Google Web Toolkit
Hi,

I implemented a login form suitable for auto-complete by the browser
nearly exactly as described here:

http://borglin.net/gwt-project/?page_id=467

Unfortunately, I have problems with it:

1. The password field is not filled in.

When I login for the first time the browser (FF) asks me to remember
the form fields. I can verify in the browsers settings that the
username and password is stored in the browser.

However, when I login again, only the username field is autofilled.
The password field is empty.

2. I cannot repeat the login.

When I login, logout and then try to login again, the form cannot be
created. The call to Document.get().getElementById(LOGINFORM_ID);
returns null.

I would be glad if someone could help me with this problem!

Below is my code.

Thank you
Magnus

--------------------
index.html:

<!doctype html>
<!-- The DOCTYPE declaration above will set the -->
<!-- browser's rendering engine into -->
<!-- "Standards Mode". Replacing this declaration -->
<!-- with a "Quirks Mode" doctype may lead to some -->
<!-- differences in layout. -->

<html>
<head>
<meta http-equiv="content-type" content="text/html;
charset=UTF-8">

<!--
-->
<!-- Consider inlining CSS to reduce the number of requested files
-->
<!--
-->
<link type="text/css" rel="stylesheet" href="ics.css">

<!-- -->
<!-- Any title is fine -->
<!-- -->
<title>Isar Chess System</title>

<!-- -->
<!-- This script loads your compiled module. -->
<!-- If you add any GWT meta tags, they must -->
<!-- be added before this line. -->
<!-- -->
<script type="text/javascript" language="javascript" src="ics/
ics.nocache.js"></script>
</head>

<!-- -->
<!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. -->
<!-- -->
<body>

<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
style="position:absolute;width:0;height:0;border:0"></iframe>

<!-- RECOMMENDED if your web app will not function without
JavaScript enabled -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-
left: -11em; color: red; background-color: white; border: 1px solid
red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>

  <div class="apl-Indicator" id="apl-Indicator">
    <img src="img/Indicator.gif"  alt="loading">
  </div>

<div id="loginDiv" style="display:none">
<form action="login" id="loginForm">
<table id="loginTable" valign="center">
<tr>
<td id="loginLabel">Username:</td>
</tr>
<tr>
<td><input id="loginUsername" name="u" style="margin-top: 0px"></
td>
</tr>
<tr>
<td id="loginLabel">Password:</td>
</tr>
<tr>
<td><input id="loginPassword" name="pw" type="password"
style="margin: 0px"></td>
</tr>
<tr>
<td id="loginRememberMe"></td>
</tr>
<tr>
<td align='right'>
<button id="loginSubmit" type="submit">Login</button>
</td>
</tr>
</table>
</form>
</div>

</body>
</html>


--------------------
LoginBox.java:

package ics.client.gui.box;

import ics.client.Application;
import ics.client.apl.Command;
import ics.client.gui.cmp.*;

import com.google.gwt.dom.client.*;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import
com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;

public class LoginBox extends Box
{
private static final String LOGINFORM_ID = "loginForm";
private static final String LOGINBUTTON_ID = "loginSubmit";
private static final String REMEMBERME_ID = "loginRememberMe";
private static final String USERNAME_ID = "loginUsername";
private static final String PASSWORD_ID = "loginPassword";

public LoginBox ()
{
build ();
}

public void build ()
{
Element e = Document.get().getElementById(LOGINFORM_ID);
Window.alert ("LoginBox - Element: " + e);

assert (e != null);

FormPanel form = FormPanel.wrap(e, false);

form.setAction("javascript:__gwt_login()");

TableCellElement rememberMeCell = (TableCellElement)
Document.get().getElementById(REMEMBERME_ID);
CheckBox box = new CheckBox("Remember Me");
rememberMeCell.appendChild(box.getElement());

injectLoginFunction(this);

VerticalPanel p = new VerticalPanel ();
p.add(form);
setWidget(p);
}

private native void injectLoginFunction(LoginBox view)
/*-{
$wnd.__gwt_login = function()
{
view.@ics.client.gui.box.LoginBox::doLogin()();
}
}-*/;

private void doLogin()
{
String usr = ((InputElement)
Document.get().getElementById(USERNAME_ID)).getValue();
String pwd = ((InputElement)
Document.get().getElementById(PASSWORD_ID)).getValue();

execute (usr,pwd);
}

private void execute (String usr,String pwd)
{
// process login
}

}

Thomas Broyer

unread,
Aug 30, 2010, 4:48:53 AM8/30/10
to Google Web Toolkit

On 30 août, 07:45, Magnus <alpineblas...@googlemail.com> wrote:
> Hi,
>
> I implemented a login form suitable for auto-complete by the browser
> nearly exactly as described here:
>
> http://borglin.net/gwt-project/?page_id=467

...which violates rule #3: do not move the form around or the browser
will treat it the same as a dynamically generated form and won't auto-
fill it (well, it really depends on which browser, and probably which
browser version).
All you're "allowed" to do with the form is to show and hide it and
change its style.
(but believe me, you'd rather externalize the login process from your
app, just like Google apps –as you're using GMail, you should
understand what I mean–, it makes things so much simpler!)

> Unfortunately, I have problems with it:
>
> 1. The password field is not filled in.
>
> When I login for the first time the browser (FF) asks me to remember
> the form fields. I can verify in the browsers settings that the
> username and password is stored in the browser.
>
> However, when I login again, only the username field is autofilled.
> The password field is empty.

See above, the problem is moving the FormPanel around (adding it to a
VerticalPanel in this case).

> 2. I cannot repeat the login.
>
> When I login, logout and then try to login again, the form cannot be
> created. The call to Document.get().getElementById(LOGINFORM_ID);
> returns null.

First, because the form has already been wrapped, you shouldn't try to
wrap it again; consider your FormPanel as a singleton, and always
reuse it (as a rule of thumb, make all your views singletons if you
can; working with the DOM is probably what degrades your app's
performances the most, so try to not do it more than necessary).
In your case, getElementById probably returns null because you removed
the FormPanel from the document instead of just hiding/showing it.

But let me reiterate: your life will be easier if you externalize the
login process from your app.
When the app loads, it knows if the user is authenticated (in case you
authorize unauthenticated access, otherwise the app wouldn't even be
loaded as the "authentication gatekeeper" wouldn't let the user in
without first authenticating) and who she is; and the user's identity
cannot change through the lifetime of the app (signing out will unload
the app, re-signing in will load it again), which means you can keep
data "cached". Integrating the login process in your app means
dispatching login/logout events and handling them to clear cached
data, which can really become very painful.
Believe me on this, I built two apps this way before I realize the
obvious (well, I already knew it before making the second one, but it
had to work the same as the first :-( )

Magnus

unread,
Aug 31, 2010, 5:38:50 AM8/31/10
to Google Web Toolkit
Hi Thomas,

didn't you propose exactly this method which is referenced in the
document I referred to?

http://groups.google.com/group/google-web-toolkit/browse_frm/thread/2b2ce0b6aaa82461/088048aa1040a5ee?lnk=gst&q=login+form#088048aa1040a5ee

On 30 Aug., 10:48, Thomas Broyer <t.bro...@gmail.com> wrote:
> ...which violates rule #3: do not move the form around

Which rule do you mean?

> See above, the problem is moving the FormPanel around (adding it to a
> VerticalPanel in this case).

I don't understand that, because the VerticalPanel is also used in the
example, and this seems to work:

http://borglin.net/gwt-project/?page_id=467

> (but believe me, you'd rather externalize the login process from your
> app, just like Google apps –as you're using GMail, you should
> understand what I mean–, it makes things so much simpler!)

What exactly would get simpler? If the login/logout mechanism works,
everything is fine, isn't it?

On the other hand, the group application we are posting in looks the
same, if you are logged in or not. It seems nicely integrated in the
whole app.

> But let me reiterate: your life will be easier if you externalize the
> login process from your app.

I believe that you are right and I really would like to adhere your
advice, but I need a small working example that shows how control flow
is passed between login page and app and vice versa. It would be great
if you could give me such an example.

Magnus

Thomas Broyer

unread,
Aug 31, 2010, 12:00:45 PM8/31/10
to Google Web Toolkit


On 31 août, 11:38, Magnus <alpineblas...@googlemail.com> wrote:
> Hi Thomas,
>
> didn't you propose exactly this method which is referenced in the
> document I referred to?

Yes, and I implemented it, and I now regret.

> On 30 Aug., 10:48, Thomas Broyer <t.bro...@gmail.com> wrote:
>
> > ...which violates rule #3: do not move the form around
>
> Which rule do you mean?

Some informal rules. Rule #1 is to have the form in the original
markup of the page, and rule #2 is to let the browser submit the form
using an <input type=submit> or <button type=submit>, rather than
calling form.submit().

> > See above, the problem is moving the FormPanel around (adding it to a
> > VerticalPanel in this case).
>
> I don't understand that, because the VerticalPanel is also used in the
> example, and this seems to work:
>
> http://borglin.net/gwt-project/?page_id=467

I can't tell whether the example work in all browsers, but in my (now
ancient) testings, you had to leave the form where you found it and
only play with its attributes and style (that'd be rule #3).

> > (but believe me, you'd rather externalize the login process from your
> > app, just like Google apps –as you're using GMail, you should
> > understand what I mean–, it makes things so much simpler!)
>
> What exactly would get simpler? If the login/logout mechanism works,
> everything is fine, isn't it?

If you "cache" some data on the client-side (which also includes, for
instance, populating a ListBox only if it's empty, because you know
upfront that the data shouldn't change for the lifetime of the app,
for a given user), then you'd have to dispatch login/logout events to
all your components so they empty their caches. You don't have to
think about this kind of things if data won't change for the lifetime
of the app (because signing out would mean leaving the app).

Magnus

unread,
Aug 31, 2010, 1:34:45 PM8/31/10
to Google Web Toolkit
Hi folks,

is it the common opinion for GWT apps to have a separate login page?
(Thomas, your "cache" example seems a bit artificial to me (although I
believe that you know why you recommend a separate login page).)

Could someone please provide an example for a separate login page? I
wonder if this should be realized as a servlet or a jsp or something
like that, how control is passed to the app and how the app finds out
that the user is logged in...

Thanks
Magnus

Thomas Broyer

unread,
Aug 31, 2010, 6:13:45 PM8/31/10
to Google Web Toolkit


On 31 août, 19:34, Magnus <alpineblas...@googlemail.com> wrote:
> Hi folks,
>
> is it the common opinion for GWT apps to have a separate login page?
> (Thomas, your "cache" example seems a bit artificial to me (although I
> believe that you know why you recommend a separate login page).)

Having built 2 apps that way, and having to remember to handle those
login/logout events to "reset" the views, I can assure you it's not
"artificial", but lot of boilerplate code I could have just avoided
writing. I also spent way too much time (IMO) to get the login process
working (have to use a base AsyncCallback/RequestCallback that handles
authentication errors to show the login screen –RequestFactory will
fortunately makes this waaay easier–; and what to do once you log back
in? replay the request? the reason we went for an "integrated login"
UX was our client asking for sessions to expire, and we didn't want
the user to lose its unsaved work, so the login screen in this case is
showed "above" the screen, with the username field switched to
readonly; if you do not have a need for such a thing, then I you could
probably live with an "externalized login"; I'm now trying to make
clients change their mind about session expiration, and/or adopting a
different approach with auto-saves into server-side "working copies",
or live with their users losing work if they don't hit "save" soon
enough though without automatically redirecting them to the login
screen, similar to how "web 1.0" applications generally work –
directing you to the login screen only when you hit the server, i.e.
only between page loads–)

> Could someone please provide an example for a separate login page? I
> wonder if this should be realized as a servlet or a jsp or something
> like that, how control is passed to the app and how the app finds out
> that the user is logged in...

To force authentication, my approach is to just have the "host html
page" a protected resource (configure security in the web.xml to
require a valid, authenticated user; letting the servlet container
handling authentication, using JASPIC/JSR-196 or the container's own
APIs when you need/want customization).
For the app to know the user's details, the host html page is a JSP,
rendering a <script> block defining a JavaScript variable with the
needed info,and using JSNI or just Dictionnary to getthe info from the
GWT app (do a view-source on GMail or any AJAX Google App, you'll see
that they're doing similar things), but an RPC request at onModuleLoad
could do it too (though a bit less performant).

I can't give you code/config sample offhand, but there's nothing
really special about it. The only missing thing is to detect session
expirations from your RPC calls but you already were doing this,
right?
(as I said, RequestFactory makes this easier –dispatching an event on
the eventbus– so if you can wait GWT 2.1, use RequestFactory!)

Magnus

unread,
Sep 1, 2010, 9:42:17 AM9/1/10
to Google Web Toolkit
Hi Thomas,

I have thought about this the whole day now and it really sounds
interesting to me to give it a try with external login, but - if I
understood you right - I see a big disatvantage:

Many applications are not or should not be usable at all when the user
is not logged in. But there are also applications that should be
usable (in a limited way) without login.

Consider eBay: You can search and browse as nobody, but if you want to
sell, you have to sign in. Or consider a chess application: You can
watch everything, but if you want to create a new game, you have to
sign in first. Consider a forum: You can read a lot, but not
everything, but after you login, you can read everything and also
write.

So my problem is that with your method I had to lock out all guest
users that just want to come and see what is going on there!

For now, I am not sure if I understood you right. In addition I am
thinking about a "dummy user" to let guests come into my application,
but I am not sure if this is a solution.

What do you think about this?

Magnus
Message has been deleted

Jeff Chimene

unread,
Sep 1, 2010, 10:38:13 AM9/1/10
to google-we...@googlegroups.com
On Wed, Sep 1, 2010 at 6:42 AM, Magnus <alpine...@googlemail.com> wrote:
Hi Thomas,

I have thought about this the whole day now and it really sounds
interesting to me to give it a try with external login, but - if I
understood you right - I see a big disatvantage:

Many applications are not or should not be usable at all when the user
is not logged in. But there are also applications that should be
usable (in a limited way) without login.

Consider eBay: You can search and browse as nobody, but if you want to
sell, you have to sign in. Or consider a chess application: You can
watch everything, but if you want to create a new game, you have to
sign in first. Consider a forum: You can read a lot, but not
everything, but after you login, you can read everything and also
write.

So my problem is that with your method I had to lock out all guest
users that just want to come and see what is going on there!

For now, I am not sure if I understood you right. In addition I am
thinking about a "dummy user" to let guests come into my application,
but I am not sure if this is a solution.

What do you think about this?

You're on the right track. Consider separating authentication (who are you) from authorization (what can you do). You have a /guest/ role along side a /user/ role.

Thomas Broyer

unread,
Sep 1, 2010, 9:47:15 PM9/1/10
to Google Web Toolkit


On Sep 1, 3:42 pm, Magnus <alpineblas...@googlemail.com> wrote:
> Hi Thomas,
>
> I have thought about this the whole day now and it really sounds
> interesting to me to give it a try with external login, but - if I
> understood you right - I see a big disatvantage:
>
> Many applications are not or should not be usable at all when the user
> is not logged in. But there are also applications that should be
> usable (in a limited way) without login.
>
> Consider eBay: You can search and browse as nobody, but if you want to
> sell, you have to sign in. Or consider a chess application: You can
> watch everything, but if you want to create a new game, you have to
> sign in first. Consider a forum: You can read a lot, but not
> everything, but after you login, you can read everything and also
> write.
>
> So my problem is that with your method I had to lock out all guest
> users that just want to come and see what is going on there!

Not necessarily.
The setup I described about web.xml, etc. would make it behave as you
describe, but that's just one way to do "externalized login", and a
way that doesn't make "guest access" possible (to make things simpler
and keeping the advantages of container-managed login using servlet
FORM or JASPIC, you could just use 2 "host pages": a world-accessible
one and a restricted one, possible using redirections and so on to
make it "work as intended" in every corner case, I haven't tested; I
bet you'll find plenty of examples on the Web about doing guest and
authenticated access on the same resource in Java servlet/JSP)

In every of the 3 cases you cite, I don't see a problem in reloading
the app when switching from unauthenticated to authenticated access
(if you want to keep some information around –such as your shopping
cart–, send it as part of the login process –or store it on the server
and pass some ID around–). YMMV of course (and I didn't say
"externalize login" is a silver bullet, you might really want/need
some UX that would make it impossible to use).

One possibility too is to only allow a guest-to-authenticated-user
workflow without reloading the app ("integrated login"). As soon as
the user wants to sign out, then reload the app and start back in
"guest mode". That way, you don't have to fear about restricted data
"leaking" between user sessions, but you'd still have to make sure to
clear some client-side caches (depending on your use case; for the
forum case you gave, for instance, clear the list of posts so you'll
reload them from the server and see the "restricted posts").

Magnus

unread,
Sep 3, 2010, 1:00:49 PM9/3/10
to Google Web Toolkit
Hmmm...I would like to get my peace with this, but...

I now created an invisible iframe in my host html.
On login I just show it, so it's a native html form.
It's not so nice as a DialogBox, but it works.

I cannot see why this is bad.

Why is it bad?

You see, I cannot let it go... :-)

Magnus

Magnus

unread,
Sep 6, 2010, 9:00:56 AM9/6/10
to Google Web Toolkit
Thomas,

I was too quick when saying that it works with iframes: The login page
was shown correctly and the browser offered autofill, but
FormPanel.wrap caused an exception which I could not get away (i think
a JS exception).

Then I tried a combination of both - external login and visual GWT
integration:

I made an external JSP page for the log, totally outside of GWT, but I
loaded this JSP page into an iframe so that it showed up within my GWT
app.

The only problem is, when I submit the login form inside the iframe,
the login page redirects to my app inside the iframe. So the app
appears inside the iframe.

Isn't there a way to do the following:
If the login form within the iframe is submitted, reload the app
outside the iframe.

Magnus

George Georgovassilis

unread,
Sep 6, 2010, 1:22:20 PM9/6/10
to Google Web Toolkit
Hello Magnus,

That's called "Breaking out of frames" [1]. If you need your app to be
able to detect a valid login, then you'll need to communicate from
within the iframe to the hosting app that the login was ok (have a
look at window.name transport in this case [2])

[1] http://www.blooberry.com/indexdot/html/topics/breakframe.htm
[2] http://development.lombardi.com/?p=611

Thomas Broyer

unread,
Sep 6, 2010, 1:59:05 PM9/6/10
to Google Web Toolkit


On 6 sep, 19:22, George Georgovassilis <g.georgovassi...@gmail.com>
wrote:
> Hello Magnus,
>
> That's called "Breaking out of frames" [1]. If you need your app to be
> able to detect a valid login, then you'll need to communicate from
> within the iframe to the hosting app that the login was ok (have a
> look at window.name transport in this case [2])
>
> [1]http://www.blooberry.com/indexdot/html/topics/breakframe.htm
> [2]http://development.lombardi.com/?p=611

In this case, a target=_top on the <form> would be enough.

But honestly, I don't understand how this design is any different from
redirecting to the login page (unless maybe you have a "cancel" button
that leaves you in the app, i.e. without reload)

Magnus

unread,
Sep 7, 2010, 5:44:53 AM9/7/10
to Google Web Toolkit
On 6 Sep., 19:59, Thomas Broyer <t.bro...@gmail.com> wrote:
> But honestly, I don't understand how this design is any different from
> redirecting to the login page (unless maybe you have a "cancel" button
> that leaves you in the app, i.e. without reload)

Well, from my point of view it would be nice if the login form is
visually integrated into my app. I managed to size and center the
iframe so that it just opens as a popup.

However, I now have an external login page, totally outside of GWT,
but I am not happy with all that. First, my app loads. Then, when I
request the login, it unloads and loads the external login page, and
then, after login, my app loads again. This is a very time consuming
process. And the login page itself does not fit into the visual design
of the app at all...

I wonder why we have to research on this topic. It must be a problem
that almost all GWT developers must also have. Why isn't there a
generic recommendation, or even a solution within GWT? I have the
feeling that we are inventing some wheels here.

As I already said, I am totally unhappy with this solution, and I hope
some GWT developers point me/us into a better direction someday...

Magnus

Magnus

unread,
Sep 7, 2010, 8:10:38 AM9/7/10
to Google Web Toolkit
Just for the completeness: I recall what was the problem with the GWT
integration:

As I said I had an iframe with the src attribute pointing to a
separate html file with the login form. Then, to inject the JS code
for form submission I needed to wrap the form. But I did not get
access to the iframe's DOM...

Just for the completeness... I am still unhappy... :-/

Magnus
Reply all
Reply to author
Forward
0 new messages