XForms Everywhere

12/27/2006

Configuring an Apache Front-End for Orbeon Forms

Filed under: General — Erik Bruchez @ 11:08 am

Apache Logo

Orbeon Forms runs within a container such as Tomcat, which is able to serve HTTP requests directly to a web browser. Usually, serving content this way will be reasonably fast, and you benefit from having just one piece of software to install and configure.

But Tomcat was not primarily designed as a general-purpose HTTP server. In comparison with the Apache HTTP server (simply “Apache” below), it lacks many features: Apache allows you to serve anything from static content to Subversion repositories to PHP to Ruby. And it comes with mod_rewrite, a real workhorse for any server-side web server configuration.

So naturally you would like to use Apache together with Tomcat. The most common way of doing this is to use Apache as a front-end, meaning that Apache handles all incoming HTTP requests and then dispatches some of them to Tomcat. You have two main ways to do this:

  • Configure a reverse proxy that communicates with Tomcat through HTTP. This approach is simple but it has drawbacks, such as the fact that virtual host information is difficult to propagate, and that the target application may have to rewrite URLs.

  • Use AJP, the protocol designed specifically to integrate Apache with servlet containers like Tomcat.

How do you use AJP then? I had a less than satisfying experience in the past with mod_jk, the Apache module typically used for that purpose. mod_jk comes in two confusing major versions (mod_jk2 now appears deprecated in favor of… version 1! - I told you it was confusing), has bad documentation, bastardized configuration files, and dubious Windows support. I’ll stop here.

But it turns out that there is an easier way: mod_rewrite happens to support AJP, and this support is now built into Apache 2.2. The cool thing is that virtual hosts are supported. So you write:

# Make sure these modules are enabled
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
	
# Configure your virtual host
<VirtualHost *>
    ServerName mysite.example.org
    # Other virtual host configuration
    # ...
    # Now configure mod_rewrite to forward to Tomcat
    RewriteEngine on
    RewriteRule ^(.*) ajp://localhost:8009/$1 [P,L]
</VirtualHost>

This redirects any incoming URL on the virtual host to a Tomcat AJP connector listening on port 8009.

And then in your Tomcat’s server.xml:

<Connector port="8009" enableLookups="false" redirectPort="8443" protocol="AJP/1.3"/>
...
<Host name="mysite.example.org" appBase="webapps" unpackWARs="true" autoDeploy="false">
   <Context path="" docBase="/my/path/to/ops-war/" reloadable="false" override="true"/>
</Host>

With just this configuration, you have a perfectly working integration of Apache and Tomcat!

Now you can take the Apache + Tomcat combination to the next level. For example here is how to configure Apache to directly serve the Orbeon Forms public resources such as JavaScript and CSS files:

  • Extract the contents of the Orbeon Forms ops-resources-public.jar into a directory of your choice, say /my/path/to/ops-resources.

  • In the Apache httpd.conf, configure rewriting rules for all the file types available in ops-resources-public.jar:

    RewriteEngine on
    RewriteRule ^/(ops/.*\.css)$  /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.js)$   /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.gif)$  /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.png)$  /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.jpg)$  /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.html)$ /my/path/to/ops-resources/$1 [L]
    RewriteRule ^/(ops/.*\.htc)$  /my/path/to/ops-resources/$1 [L]
    RewriteRule ^(.*) ajp://localhost:8009/$1 [P,L]
    

There you go! Happy Holidays!

12/11/2006

xforms:upload on steroids

Filed under: General — Erik Bruchez @ 12:09 pm

Crane

If you have some experience with HTML and Ajax, you probably know that HTML upload is a funny beast. For example, if you submit an HTML form with JavaScript, you don’t have control over the response and the result is an entirely new document. And you can’t just submit an HTML form through Ajax either. So while you can handle all the other HTML form controls in the background and do cool thing such as server-side validation with Ajax, file upload is often just left behaving like the dumb HTML control that it is. Until recently Orbeon Forms was also limited in this respect and xforms:upload only worked when using xforms:submission with replace="all". This meant that you could not upload files in the background.

But some clever guys have figured neat tricks to overcome these limitations and allow you to upload files in the background, as if with Ajax. Applications like Gmail make use of these tricks to make their interfaces more user-friendly. While the idea is fairly simple (usually submitting an HTML form in a hidden HTML iframe), the implementation in JavaScript and DOM a little less so. Luckily, this is now part of frameworks like Dojo and YUI (which Orbeon Forms uses). It was time that we leverage this in Orbeon Forms.

So we have extended support to replace="instance" and replace="none" and you can now simply bind an upload control to an instance, submit that instance as usual, and automatically see the files selected by the user in the upload control sent to the server in the background if necessary. It’s as simple as it gets:

<xforms:instance id="file-instance">
  <file name="" mediatype="" size=""/>
</xforms>
<xforms:submit ref="instance('file-instance')" replace="none" method="post" action="/send/my/file"/>
...
<xforms:upload ref="instance('file-instance')">
  <xforms:label>File to upload</xforms:label>
  <xforms:filename ref="@name"/>
  <xforms:mediatype ref="@mediatype"/>
  <xxforms:size ref="@size"/>
</xforms>

In the future we would like to support the incremental flag on xforms:upload. This will trigger file upload to the server as soon as a file is selected by the user.

Thanks to Teleflex for supporting this feature!

Powered by WordPress