Some of the information here may be outdated, please check the book instead
[edit]

Disclaimer

This is not a comparison of features. I am trying to explain web2py to Java programmers.

Overview

In J2EE and Java based frameworks the separation between the Model (the data representation), the View (the presentation layer) and the Controller (the business logic and workflow) is achieved by the following components:

  • Models are JavaBeans
  • Views are Java Server Pages (JSP)
  • Controllers are Serverlets

(I am quoting this source)

web2py provides equivalent functionalities but uses the Python language instead of Java.

Controllers

This is a typical Java serverlet

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {
   public void doGet(HttpServletRequest request,HttpServletResponse response)
   throws ServletException, IOException {
      PrintWriter out = response.getWriter();
      out.println("Hello World");
   }
}

Here is the equivalent web2py controller function

 def HelloWorld():
       return 'Hello World'

Notice that:

  • Python is more expressive than Java and therefore it tends to be more compact and more readable.
  • In both cases a URL is mapped into a function call HelloWorld(). In web2py one can use regular expression to map any URL path into this function but there is a default URL associated to it.
  • A web2py controller function can return a string (as in the above example). In this case the string is returned to the browser. The most common situation is that the controller function returns a set of variables stored in a Python dictionary. In this case the dictionary is transformed into a web page by the associated view. For example

    def HelloWorld(): return dict(message='Hello World')

This page would ber rendered by a view called HelloWorld.html. If such view does not exist, the built-in generic.html is used instead. This allows to create controllers and fully functional web application without writing any HTML. The view, the presentation layer, is typically added as a last step in development.

In web2py, the controller has access to the following objects (request, response, session, cache) and they can be used, for example, to read request GET/POST variables and environment variables (according to the WSGI specs) as in this example:

 def HelloWorld():
       return dict(message='Hello '+request.env.remote_addr)

As for Java serverlets, every call to a web2py controller action is executed in its own thread. Thus multiple requests can be executed concurrently.

web2py comes with its own SSL enabled web server you also works with Apache, Lightpd and any server that supports WSGI or FastCGI or CGI.

Views

A typical Java Server Page looks like this:

<html>
   <body>
     <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     <c:forEach var="i" begin="1" end="10">
        Hello Number ${i}<br/>
     </c:forEach> 
  </body>
</html>

In web2py the same code reads

<html>
   <body>
       {{for i in range(1,10):}}
          Hello Number {{=i}}<br/>
       {{pass}} 
  </body>
</html>

The code in {{ }} is pure Python code (not a subset). Blocks start with a line ending in colon and stop with the keyword pass.

As in JSP, web2py views can extend and include other views:

 {{extend 'layout.html'}}
 {{for i in range(1,10):}}
    Hello Number {{=i}}<br/>
 {{pass}}

layout.html comes with web2py but it is easy to create other layouts using HTML or using our layout designer.

Notice that:

  • in web2py all the output printed with {{=..}}, by default, is escaped to prevent possible XSS vulnerabilities. In Java it is up to the developer to remember to explicitly escape the output.
  • the use of the {{ }} tags instead of the < > tags has been chosen because it is transparent to WYSIWYG HTML editors and thus they can be used with web2py without special plug-ins.

Data Persistence and Models

Any web application needs persistence. In Java this is achieved by JavaBeans. There are JavaBeans to handle session variables and there are JavaBeans to interact with the database. web2py uses three distinct mechanisms to handle persistence: sessions, ORM, and cache.

session variables

Consider the following web2py controller that implements a counter

def count():
    if not sessin.c: session.c=1
    else: session.c+=1
    return dict(message='Counted up to %i' % session.c)

session is a built-in object used to store session variables. When queried for an attribute that does not exist (if session.c) is False. When an attribute is set (session.c=1) this is stored in the session. By default sessions are stored in files and locked when used. Optionally they can be stored in the database. Almost any Python object can be stored into a session. web2py automatically creates session cookies.

Object Relational Mapper

J2EE, out of the box, does not have something equivalent to an ORM. Perhaps you can get one from a third party vendor but I have never seen one. web2py's ORM provides a API to interact with the database that is completely independent on the database backed. This is not the same as JDBC! JDBC is all about connecting to the database, sending SQL queries and a retrieving response but the developer still has to write SQL and the SQL queries depend on the dialect of the database back-end. If you develop your Java+JDBC app using Oracle and you decide to move to Postgresql (or vice versa), you have to rewrite most of the SQL queries.

The web2py ORM (as any Python ORM) writes the SQL for you, in real time, with no overhead, preventing SQL injections, for any supported database back-end.

The web2py ORM (like many Python ORM) seamlessly work with SQLIte, MySQL, PostgreSQL, Oracle, and (with limitations) on Google Big Tables.

The web2py ORM (unlikely many Python ORM) does migrations. It means after you connect to the database and define a table, if the table does not exist, it will create it; if it exists but is different, it will alter it accordingly. Here is an example or ORM usage:

 db=SQLDB('sqlite://mydb.db')
 db.define_table('user',
       SQLField('name'))
 db.user.insert(name='massimo')
 rows=db().select(db.user.ALL)

The first line connects to the database (here a file-based sqlite database). In the case of sqlite, if the file does not exist it is created.

The second and third lines define a table "user". If the table does not exist, web2py generates the 'CREATE TABLE....' for the specific SQL dialect and sends it to the database server.

The fourth line inserts a record.

The fifth line selects all fields for all users from the database table user.

The first three lines trigger web2py not just to create/alter the table but also to generate a web based administrative interface for this database.

web2py provides API to build complex queries like

 rows=db(db.user.name.like('mas%')&(db.user.name!='massimo'))\
    .select(orderby=db.user.name,groupby=db.user.name,limitby=(0,10))

and more complex like joins, left joins, multiple joins, nested selects.

The ORM access is always transaction safe. The transaction is committed when a web page returns without error else the error is logged and the transaction is rolled back.

In web2py db.define_table(....) statements are stored in model files since they constitute a description of the data representation.

The reader can create web2py models using our model builder

cache

web2py can cache any function in ram (cache.ram), on disk (cache.disk), or using memcache. Any function includes results of select, controller functions, views, etc. Here is how to cache a controller for 60 seconds

 @cache(request.env.path_info,60,cache.ram)
 def HelloWorld():
       return dict(message='Hello World')

and here is how to cache a select for 60 seconds.

 rows=db().select(db.user.ALL,cache=(cache.ram,60))

JavaBeans

web2py does not have JavaBeans because it does not need them.

Web Services

According to [SUN(http://java.sun.com/developer/technicalArticles/J2EE/j2ee_ws/) "Building an XML-RPC style web service using the J2EE 1.4 platform involves five steps:"

  • Design and code the web service endpoint interface.
  • Implement the interface.
  • Write a configuration file.
  • Generate the necessary files.
  • Use the deploytool to package the service in a WAR file and deploy it.

Here we just list the example SUN provides for the second step:

import java.rmi.RemoteException;
public class MathImpl implements MathFace {
   public int add(int a, int b) throws RemoteException {
     return a + b;
   }
}

In web2py there is only this second step (we honestly do not understand why J2EE needs the other four). You just write in a controller:

 def add(a,b): return a+b
 def handler(): return response.xmlrpc(request,(add,))

The second function is the controller (which we choose to call "handler") and it exposes as XML-RPC the function add. One can expose multiple functions via the same "handler" function.

We really do not feel we need to add any comment here.

Internationalization

In web2py:

T('this is a message')

(and as usual no need to import anything since you are supposed to use T) You web2py you can also do

T('this is message %(name)s',dict(name='xxx'))
  • In both cases the expression is evaluated lazily when displayed in views.
  • In web2py, the web based administrative interface provides a translation page interface.
  • To create a language file in web2py just type its name (for example it-it.py ) in the admin interface.

What else?

  • web2py comes in one executable package including an SSL enabled web server, the sqlite database, a web administratve interface that allows you to create/edit/deploy and manage all your applications.

  • Exception are automatically caught by web2py which logs the traceback, the code causing the exception, and issues a ticket to the visitor that triggered the exception. No code is exposed to the visitor, not even by mistake, ever.

  • web2py includes libraries for generating CREATE/UPDATE/DELETE forms from your database tables.

  • web2py incudes libraries for handling AJAX, JSON, REST, RSS, ATOM, RTF, CSV, WIKI (markdown) and some more protocols.

  • web2py has helpers that help you build objects that can be serialized in HTML or XML. Any correct HTML/XML can be generated using exclusively helpers.

  • web2py code runs on the Google App Engine.

  • web2py packages everything you need in one binary file that you don't even need to install. I keep mine on a USB stick. You just click on it and it start web server, the sqlite database, fires the browser for access to the administrative interface.

  • web2py deals with static files for you, streams them when they are large (both in upload and download), and automatically supports IF_MODIFIED_SINCE and PARTIAL CONTENT. You can do streaming audio and video without any extra tools or settings.

  • web2py can map URLs using regular expressions so that you can use it to handle legacy URLs.

  • web2py has no configuration files. You just create an empty app via the shell or the web based admin interface and create/edit your models, controllers and views (using an editor or the web based admin interface).

There is a repository of free web2py apps here and an interactive FAQ there.

© 2008-2010 by Massimo Di Pierro - All rights reserved - Powered by web2py - design derived from a theme by the earlybird
The content of this book is released under the Artistic License 2.0 - Modified content cannot be reproduced.