I am currently working on a project planning software that “tries” to utilize Java Webstart as its deployment method. Nowadays it is common practice that login dialogs also allow new users to register with the application and existing users to retrieve their password if they forgot it. When I was trying to implement these features I ran into all kinds of issues and finally gave up.
The problem is that login dialogs for webstart applications are stupid. They are not aware of the context in which they are running. All they “know” is that they were shown to the user as a result of a callback from the server. The callback is asking for a user name and a password. This is fine for a simple standard login, but not for an advanced one. How can a new user be created on the server without some kind of connection to the server? Especially if the server is not even known, which is the case when running the webstart client inside an application client container (ACC). The whole idea behind the ACC is to provide injection capabilities, hence freeing the application developer from configuring the initial context.
The following screenshot shows the standard login screen. When the user clicks on the “Login” button the callback object will be populated with the user name and password. The application then simply continues if the login was successful. Another issue I had here was that I could not find out wether the login failed or not. On failure the dialog would simply disappear.
The next screen shows the controls used for registering a new user. I was unable to find a way to actually call something on the server so that the new user would be added. Please let me know if anyone knows a solution for this.
The last screen is used for retrieving a lost password. Once again I ran into problems. The server will not do anything without an authorized user. A solution would be to create a technical user, e.g. “sys” with password “sys”. These values could be put into the callback object and sent back to the server. But how do I let the application know that a password retrieval is in progress? Where do I trigger the code needed to send a mail that contains the user’s password?
Once again, any help would be much appreciated. I still have a couple of months of coding ahead of me before the first release. I would hate to give up on using Webstart as a deployment vehicle.
I can not give you any orher advice that: If you think is JWS fault not letting you do this, implement it as a standalone application and then rethink is is jws fault, I can tell you that we have implemented much more complicated stuff and yor problem has nothing to be with the fact that is a jws application.
I completely agree with you that a login dialog like this one should be an easy thing to do. I also agree that it is possible to write complex apps using JWS (e.g. see my latest post regarding Collapp). But unfortunately it isn’t easy, because at the time of authentication my client (the login dialog) does not have any references to the server, hence can not invoke any logic on the it, not even unprotected EJB methods (e.g. adminBean.createUser()). I should mention that the login dialog runs inside an application client container (ACC), so I use injection for inserting the beans. This should make the whole app easier to deploy, because you don’t have to insert the server address anywhere.
Oh, and one more thing. My client also runs standalone. In this mode I do have everything I need to create the necessary connections to the server and to make the appropriate calls. But in order for this to work I have to pass a couple of arguments to the main() method. The information contained in these arguments is exactly what is missing when run via JWS.
If all your really interested in is sending String arguments to the application you can use properties in the JNLP file.
….
You retrieve them in your code by calling
String arg1 = System.getProperty(“arg1”);
String arg2 = System.getProperty(“arg2”);
But this would defeat the whole purpose of using an application client container ACC with injection. With your approach I would have to manually insert the properties in the JNLP file for each installation.
I think what is missing at the time of authentication is the concept of context, just like servlets have them. A web application is allowed to call unprotected servlets, which then have context to perform the necessary work (insert user in DB).
Looks like the comment system swallowed the jnlp snippet I included.
So in text in the resource section of the JNLP add
property name=”arg1″ value=”xxxx”
property name=”arg2″ value=”yyyy”
Looks like the JNLP defines all the system properties I need (host and port). The only problem I have now is that the bean class is not available in my client. I must setup something differently so that the callback handler that shows the lowing dialog also has access to the remote bean interface.
We use a home grown servlet which fills in a template jnlp with values from the database. This keeps customers from having to crack the WAR to update the JNLP.
The Sun provided JnlpDownloadServlet does much the same thing and would provide good examples.
So essentially you can call a servlet URL instead of hitting a static jnlp file. Your servlet can have access to any context that any other unprotected servlet would have access to.
jdavids: now I am getting pointed into the right direction I think 🙂 Right now I am simply using the JNLP file that gets generated for me by Eclipse when I deploy my app to Glassfish. I will have to follow this lead and see where it takes me.
Further to what jdavids says, the source code for the JnlpDownloadServlet is available. Nevertheless it is better not to modify that but instead delegate to it the regular stuff and just do the JNLP template processing yourself.
I can confirm that this approach works well.
Use java keyring implementation to security store credentials for used. Java has a keystore implementation for it. We use it, however be aware there is an annoying bug in MACOS at present, so we had to implement a workaround. {Problem is MACOS will only return first Java created key, which is unfortunate if more that one Java app using this on the desktop.
UPDATE: I wrote The problem is that login dialogs for webstart applications are stupid. They are not aware of the context in which they are running.. Turns out 2 1/2 years ago I was stupid. The dialog of course knows the context. I simply had to create an instance of InitialContext(). After that I could invoke whatever server-side action I like. I only had to make sure that those actions do not require an authenticated user.