The GWTShell -noserver option has caused some confusion on the
GWT forums. This option is intended to allow you to run an external Java servlet container instance (be it Tomcat or anything else) while doing development and using the GWTShell with "Hosted Mode."
Getting this option to work, despite any initial confusion, can be very helpful. For example, if you are working with an external container, you can setup DataSources, Security Realms, Servlet Filters, and anything else your container provides, such as container managed resources (EJBs, JMS queues) - and have it all there in Hosted Mode.
Before I get to the heart of the matter though, and outline a working -noserver setup, I should first mention that this approach is not the only way to work with server resources in hosted mode. You can also "munge" the provided Tomcat instance, if you need simpler resources such as servlets and filters, and have that work in Hosted Mode too. The easiest way to do that, is to let the
GWT-Maven Maven plugin handle it. (See the docs there, for details on that approach - and note the maven plugin *also* has a google.webtoolkit.noserver property.)
So on to the -noserver information. Let's do this in a step by step fashion, with a simple app that has no RPC code, first. For our example purposes we will call this GWT module "
com.package.Module."
1. Get your app to work in normal hosted mode. Use ApplicationCreator to create the scaffolding for your app, and then launch the shell using the -shell script provided, make sure things work as expected.
$GWT_HOME/applicationCreator com.mypackage.client.Module
Module-shell{.cmd/.sh}
Verify things work, then exit the shell.
2. Setup a container context for use with your app.
This of course is container specific, for example we will use
Tomcat 6.0.x (and assume it is running on localhost:8080).
- Create a "$CATALINA_HOME/webapps/com.mypackage.Module" directory.
- Create a test "index.html" file in that same location (whatever in it, just "Test" is fine, plain HTML).
- Restart Tomcat, browse to localhost:8080/com.package.Module/ and ensure there are no errors (you can load the test plain HTML page).
3. Compile your application with the GWTCompiler.
You can use the provided -compile script (if you used ApplicationCreator) or the "compile/browse" button in the shell to accomplish this. The default output location of your files will be $PROJECT/www.
4. Move a minimum of FOUR files to your container hosted webapp location. Copy the host page, cache.html, hosted.html and gwt.js files into the external container document root for your webapp ($CATALINA_HOME/webapps/com.package.Module). These files are created by the GWTCompiler, as shown in the previous step - the default location to find them will be $PROJECT/www.
- Module.html (host page)
- com.package.Module.nocache.html (application nocache script for bootstrapping)
- hosted.html (core GWT - hosted mode hook)
- gwt.js (core GWT - non app specific - js script)
Any other public path "static" content that you have, should also be placed in the external container location. When using -noserver, the shell is designed to look for static content on the remote server. (Whereas when not using noserver, the shell will look for such content on the classpath.)
5. Edit the script or tool you use to start the shell to include the -noserver option and the port for your external container.
For example you can edit the default ApplicationCreator provided Module-shell script, or you can use something such as GWT-Maven, or the following (which is Mac specific, but easily edited/understood for other platforms):
#!/bin/sh
ENTRY_POINT=com.mypackage.Module
HOST_PAGE=Module.html
APPDIR=`dirname $0`;
CPGWT=$APPDIR/src
CPGWT=$CPGWT:$GWT_HOME/gwt-user.jar
CPGWT=$CPGWT:$GWT_HOME/gwt-dev-mac.jar
java -XstartOnFirstThread -cp $CPGWT com.google.gwt.dev.GWTShell -logLevel
/DEBUG -noserver -port 8080 "$@" $ENTRY_POINT/$HOST_PAGE
6. Launch the shell and you should be running against the external container instance.
With this setup you can edit src CLIENT files, and then refresh and things will be updated, as expected, even though you are running against the external server (the shell uses the container to boot things, and of course for server side resources, but client java code is executed directly - not translated to Javascript - while in the shell).
Try it, edit $PROJECT/src/com/mypackage/client/Module.java, and something simple such as a, Panel, a TextField and a response Label so that when the user enters input and clicks the button that input is echoed back:
package com.mypackage.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
public class Module implements EntryPoint {
public void onModuleLoad() {
final VerticalPanel panel = new VerticalPanel();
final Label inputLabel =
new Label("Enter something clever so GWT can echo it:");
final Label responseLabel = new Label();
final TextBox input = new TextBox();
final Button button = new Button("Submit");
panel.add(inputLabel);
panel.add(input);
panel.add(button);
panel.add(new HTML("<br /><br />"));
panel.add(responseLabel);
button.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
responseLabel.setText(input.getText());
}
});
RootPanel.get().add(panel);
}
}
Then hit "refresh" in the Hosted Mode browser, voila! Without restarting the shell, or doing anything other than editing the source file and refreshing the browser, the code is updated and the external container, because of noserver, is doing the hosting.
Click to enlarge.
DONE!
With an example working, and the minimum required to use -noserver now understood, you can really make this configuration useful by placing server side resources, as you need them, in your external server instance.
This can include GWT RPC RemoteServiceServlets, other servlets, filters, data sources, or anything else you need the container to handle. One thing to note with GWT service servlets is that you will have to create a WEB-INF/web.xml deployment descriptor for your external instance, and populate it as required (with specific servlet entries for each servlet, GWT related or not, as you would with any standard container context), in addition you will need to include any required dependencies in WEB-INF/lib (or on the containers classpath elsewhere, again, standard stuff now that you are dealing with an external container).
There is also some GWT documentation on this in the GWT FAQ: http://code.google.com/support/bin/answer.py?answer=55200&topic=10454.
And - in case it helps - I have compiled some other GWT resources, including tooling parameters JavaDocs, and notable third party projects: http://www.screaming-penguin.com/GWTResources.
Comments
Nice Article for Quick Start on -noserver
Hi,
The article is very nice for niche developer who wants to use GWT -noserver option.
I am working on GWT and I will happy to share my experience if there is any need.
Regards.
Allahbaksh
container location?
In step 4 you say "4. Move a minimum of THREE files to your container location. Do you mean $TOMCAT_HOME/webapps, the module directory created in step 2, or somewhere else?"
Yes, sorry if that is
Yes, sorry if that is unclear. Move these files to the new container location where you plan to host/run the app. $TC/webapps/com.module.app.
*nocache.html file
In step 4, what creates the *nocache.html file and where would I find it?
Step 3 creates that file,
Step 3 creates that file, among others. The GWTCompiler will output a nochache.html file, gwt.js, a bunch of hash-cache.html files (these are browser specific versions of the app), and your "public" resources. What you need to do noserver is the nocache, the gwt.js and the host page (and hosted.html if you are using GWT 1.4 or later).
Notes for GWT 1.4
One of the files you need to host externally changed names with GWT 1.4.
Use these FOUR files with GWT 1.4:
[ModuleName].nocache.js
[ModuleName].html
hosted.html
gwt.js
doesn't work in windows
Thanks for writing this tutorial. I followed the instructions, but I can't get this to
work correctly. I tried the sample application hello world - click me, but
in -noserver mode, the web page text comes up, but there is no button. I
am using Windows Vista and GWT 1.4.60. I traced through the
com.package.Module.nocache.js file (compiled with -style pretty) , and
com_package_Module.onScriptLoad() never gets called, so loadDone
is undefined, so maybeStartModule() falls through. Any idea how to figure
out what is wrong, so I can get this to work?
Thanks,
Lance
Should work, here is another tutorial that might help
http://code.google.com/support/bin/answer.py?answer=55200&topic=10454
That is the official GWT FAQ article, pretty much says the same thing, but has been updated more recently than this article. Try going over that and retracing your steps.
Also, make sure you app works in hosted mode first (if you are using a simple app to get started and learn this approach).
solution: doesn't work in windows
I had the same problem on Vista with GWT 1.4.60,
and solved it by also copying hosted.html to my webapp folder.
Thanks for this excellent blogpost, noserver mode really saves me quite some time on my compile/debug cycle.
Koen
solution: doesn't work in windows
Thanks Koen, that fixed the problem. It would have saved me a few hours if that was mentioned somewhere.
Did you figure that out yourself, or was it written somewhere that I missed?
Thanks,
Lance
noserver article updated
The hosted.html thing is something new with GWT 1.4. I have updated the article here to be all 1.4.x focused now - before 1.4 you did not hosted.html (and this article was originally written a long time ago). Sorry it caused confusion, I should have mentioned the version of GWT this was intended for in the original posting - either way though, it's now updated.
Thanks to you guys who caught it ;).
no server mode for Unit tesing
Hi all, this is really wonderfull article, its working great. Now i have a problem while running my unit testing. I cant run the external server. can u please guide me.
noserver drawbacks
Yeah, one thing I noted in the article is that noserver is not the only way to do it, you can also munge the embedded Tomcat.
Even though noserver can be useful, it has two BIG drawbacks.
1. You aren't really solving the configuration problem, you are just moving it. Rather than having to muck with the embedded Tomcat stuff, you have to muck with an external server. In many cases this isn't a big deal, but if you want to SHARE your project, or you are working on a library module, etc, then you have to pass on the problem - you have to include instructions and dependencies and so on for the external setup.
2. The JUnitShell does not support noserver. This means GWTTestCase based tests don't work with noserver (these GWT tests ARE needed in many cases, as they are the only real way to unit test translatable objects and both ends of GWT RPC - another discussion but suffice to say just abandoning GWTTestCase is usually not appropriate either - except in rare circumstances where you don't use RPC, and you don't have any client side other than UI [meaning no model or controller on the client]).
When using -noserver with gwtext (or another library like it)
I've been trying to figure out why I keep getting JavaScript TypeError when I try -noserver for the past hour or so. It turns out that you have to copy the files as mentioned above for similar files from gwtext.jar
(specifically com/gwtext/public/** from gwtext.jar). Hope that helps for other people trying to figure this out...
GWT -noserver
I believe the main use for the hosted mode browser is to enable one to run and debug the GWT UI code without having to compile it to javascript. This is what i would want to do with an external server. According to your explanation above, i have to do a compile and then deploy this to tomcat. I do this all the time using ANT scripts. But this doesnt help me debug the Java UI code. Compiling takes time. I should be able to edit the java code and do a refresh on the hosted mode browser to see the changes. This works well if i havent made any changes to the web.xml file. Or am i missing something?
"I believe the main use for
"I believe the main use for the hosted mode browser is to enable one to run and debug the GWT UI code without having to compile it to javascript."
Yes, that's one of the main points of the GWTShell, but you can still run your client side code in the shell with noserver (-noserver is a shell option) - the point of noserver is to handle your server side stuff while still using the shell (still using Java, debugging, etc).
In the article above I noted that the CLIENT side code can still refresh and such, via the shell, when using noserver. The server side code, however, doesn't. When you copy the four files (minimum) to the server it's only putting the module definition there for the endpoints and such, still running stuff via the shell.
I don't typically use noserver. Rather I use GWT-Maven when configures the embedded server for me, and I connect an external debugger to the process running the shell (when I want to debug). Noserver is more valuable for complicated server side setups.