For those who don’t know, Wt is an amazing C++ web development framework. There are thousands of frameworks out there but this is one of the very few that does actually take a different approach and makes web development really easy for those with no HTML or JavaScript knowledge while allowing them deliver buzz compatible applications. In fact, one can use Ajax, HTML5 canvas, HTML5 History API, Comet or embedded Google Maps without worrying about Cross-Site Scripting (XSS) or Cross-Site Request Forgery (CSRF) with zero knowledge of the technologies or their security risks because all of them are wrapped around an intuitive API. The API is specially intuitive for those with Qt knowledge because the API is deliverately similar to Qt’s.
It also sports a large number of widgets including tree views with load on demand using WAbstractItemModel, charts, video and audio playback, as well as support for a good number of browser events including those available in multi-touch devices. The framework is compatible with most browsers (Firefox, IE, Safari, Chrome, Konqueror and Opera) but also with plain HTML browsers (Links and Lynx).
Wt also has its JVM version which is called JWt and some days ago I realized that the J did not only stand for Java but Jython too. So I decided to do several tests on how hard it would be to port a PyQt application to JWt and here is my experience so far with porting a really small part of Koo which has 33.000 lines of code. (Yes, I admit I named the project Woo. Can’t seem to improve my naming skills.)
Setting up tomcat 6 (debian)
You will need one of the packages that provide a tomcat environment. I recommend using tomcat6-user, which allows easily setting up a tomcat server without the need for root privileges. Once installed, execute:
$ tomcat6-instance-create woo
This will create a new directory called ‘woo’ which will have the full tomcat envionment:
$ ls woo bin config lib logs webapps work
No you can start (and stop) the tomcat server:
$ woo/bin/startup.sh $ woo/bin/shutdown.sh
Once started, tomcat server will be available at http://localhost:8080 by default.
For running Jython I tried the existing debian package at first but had some problems make it run in tomcat and decided to download it from jython.org. That worked correctly and just had to update woo/bin/startup.sh with the appropriate JYTHONPATH. So this is how my startup.sh looks like:
#!/bin/sh export JYTHONPATH=/home/albert/jython2.5.2/Lib export CATALINA_BASE=/home/albert/d/jwt/woo /usr/share/tomcat6/bin/startup.sh echo "Tomcat started"
This step is not required in many cases, so you may just jump to next section if you just intend to give Jython + JWt a try.
If you intend to use JWt’s server push features (that is Comet) you will need a Servlet 3.0 API and that’s only available since tomcat 7. Although debian does not yet provide that package you can easily make it work if you already have the environement running with tomcat 6. As root:
# mkdir /usr/local/tomcat # cd /usr/local/tomcat # wget http://apache.prosite.de/tomcat/tomcat-7/v7.0.12/bin/apache-tomcat-7.0.12.tar.gz --2011-04-24 12:07:01-- http://apache.prosite.de/tomcat/tomcat-7/v7.0.12/bin/apache-tomcat-7.0.12.tar.gz S'està resolent apache.prosite.de... 217.13.201.10 S'està connectant a apache.prosite.de|217.13.201.10|:80...connectat. HTTP: s'ha enviat la petició, s'està esperant una resposta...200 OK Mida: 7205567 (6,9M) [application/x-gzip] Saving to: `apache-tomcat-7.0.12.tar.gz' 100%[===================================================================================>] 7.205.567 213K/s en 19s 2011-04-24 12:07:21 (372 KB/s) - `apache-tomcat-7.0.12.tar.gz' saved [7205567/7205567] # tar xvf apache-tomcat-7.0.12.tar.gz
And then, change your tomcat environment:
$ cd woo $ rm lib $ ln -s /usr/local/tomcat/apache-tomcat-7.0.12/lib $ cd bin $ cp /usr/local/tomcat/apache-tomcat-7.0.12/bin/bootstrap.jar .
Finally, change startup.sh to point to tomcat’s 7 startup.sh:
#!/bin/sh
export JYTHONPATH=/home/albert/jython2.5.2/Lib
export CATALINA_BASE=/home/albert/d/jwt/woo
/usr/local/tomcat/apache-tomcat-7.0.12/bin/startup.sh
echo "Tomcat started"
Now that you have the environment running with tomcat 7, you will need to change the class that is used to attend HTTP requests because the default one does not support Comet. So replace the following entry in woo/conf/serverl.xml:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="UTF-8" redirectPort="8443" />
with:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" URIEncoding="UTF-8" redirectPort="8443" />
Deploying a Jython application
In order to be able to use Jython in your tomcat instance you’ll need to create the usual structure in webapps:
$ find woo/webapps/hello
woo/webapps/hello
woo/webapps/hello/WEB-INF
woo/webapps/hello/WEB-INF/jetty-web.xml
woo/webapps/hello/WEB-INF/lib
woo/webapps/hello/WEB-INF/lib/jython.jar
woo/webapps/hello/WEB-INF/lib/jwt-3.1.9.jar
woo/webapps/hello/WEB-INF/lib/antlr.jar
woo/webapps/hello/WEB-INF/lib/commons-io-1.4.jar
woo/webapps/hello/WEB-INF/lib/commons-fileupload-1.2.1.jar
woo/webapps/hello/WEB-INF/lib/ant-antlr.jar
woo/webapps/hello/WEB-INF/context.xml
woo/webapps/hello/WEB-INF/web.xml
woo/webapps/hello/Hello.py
woo/webapps/hello/WHello.py
woo/webapps/hello/WHelloWithWrapper.py
woo/webapps/hello/META-INF
woo/webapps/hello/META-INF/MANIFEST.MF
woo/webapps/hello/META-INF/context.xml
In order to be able to use Jython your woo/webapps/hello/WEB-INF/web.xml should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>PyServlet</servlet-name>
<servlet-class>org.python.util.PyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- If you use tomcat 7 you can enable async support -->
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>*.py</url-pattern>
</servlet-mapping>
</web-app>
Hello, WHello and WHelloWithWrapper
Here you can download the hello.war file. Copy it to woo/webapps, start tomcat and go to http://localhost:8080/hello/Hello.py. This will show you a simple Jython hello world application. If you want to see JWt + Jython in action you can go to http://localhost:8080/hello/WHello.py which is a Jython port of JWt Hello World application (http://www.webtoolkit.eu/jwt/examples/):
The problem you will realize with WHello.py is that JWt requires a class inheriting Signal.Listener in order to handle each signal you want your application to listen to:
class WHelloApplication(WApplication): def __init__(self, env): ... self.listener = ButtonClickedListener(self) self.button.clicked().addListener(self, self.listener) class ButtonClickedListener(Signal.Listener): def __init__(self, app): self.app = app def trigger(self): self.app.greeting.setText("Hello there, " + self.app.nameEdit.getText())
class SignalWrapper(Signal.Listener):
def __init__(self, function):
self.function = function
def trigger(self, *args):
self.function(*args)
class WHelloApplication(WApplication):
def __init__(self, env):
...
self.button.clicked().addListener(self, SignalWrapper(self.greet))
def greet(self):
self.greeting.setText("Hello there, " + self.nameEdit.getText())

Would it be okay with you if I linked to this page from my website? Just asking since some people don’t allow linking to their sites if you don’t take their permission.