Musings on Managing Static Resources in WebObjects Applications
When we refer to “Static Resources” in dynamic web-based applications, we are referring to publicly visible content files that are not dynamically generated or produced by the software. Usually these are image, CSS , or stand-alone HTML files. There are several approaches to handling static resources in WebObjects, each with its own advantages and drawbacks. The three approaches discussed below are probably the most straightforward.
First Approach: Add Resources to your Xcode Project’s Application Server Build Target
This is perhaps the easiest approach. Adding one or more resources is accomplished in Xcode by using the ‘Project’ drop-down menu and clicking on ‘Add To Project’. Select the images or other files you wish to add on the first pop-up sheet. On the second pop-up sheet, under ‘Add To Targets’ check Application Server. Check the ‘Copy items…’ checkbox if the resources do not yet currently reside inside the project folder.
Once the project contains the resources and is aware of them, you can simply refer to them by name when doing bindings in WOBuilder. At the time of deployment the resource files are included inside the application “.woa” bundle which is installed in /Library/WebObjects/Applications. Inside the bundle the resources are in /Contents/Resources. Since the files are not in the webserver documents area, Apache (or another webserver) cannot vend them directly. The URL calls the WO application and the WOResourceManager finds the image (or other resource) and returns it.
Although this approach is easy, the WebObjects application is involved in generating each image URL and is also required to make a response for every image displayed. Also, in certain circumstances, the ability for the webserver to cache images is disabled (since the URL can change each time).
Second Approach: Add Resources to your Xcode Project’s Web Server Build Target
Adding resources is just as easy as the first approach - under ‘Add To Targets’ you just check Web Server.
WOResourceManager is still consulted when doing page generation to create the full path, since the WO template contains only the file name.
This second approach is Apple’s recommended default solution, though there are some issues I will discuss.
Where do the files go when you deploy? You have to do some special tricks when deploying to manage this (Called a “split install”). A special bundle is created, called the same as your application (i.e. “MyApp.woa”), that contains all the webserver resources but none of the executable code, and this goes in the WebServer Documents directory, in a directory called WebObjects. The resource files now have a static location that is publicly visible.
What do URLs look like?
“/WebObjects/MyApp.woa/Contents/Resources/header.jpg”
The main advantage of this approach is that the webserver serves images directly and the images can be locally cached. On the other hand, doing split installs takes some extra work and needs to be done carefully. Moreover, URLs are long (adding size to HTML files). Lastly, images are ‘filed’ in directories that correspond to a particular application and are more difficult to share (yes, you can create a framework to be loaded by multiple applications. But if any of the resources are used by non-WO content this gets unwieldy).
Third Approach: Store Resources Externally to your Project
In this approach, all images and other resources are kept external to the project and are not ‘managed’ by Xcode. They are stored in a subdirectory of the the webserver document root and are always accessed via the webserver.
On the up side, this approach results in the best performance of the three and it scales well. When the number of distinct image files becomes very large, you can further ensure good performance by creating a directory tree and distributing images across the tree. Images (and resources generally) can be shared between applications and with static html pages. Finally, when outside graphic designers are involved in a project they can manipulate image files directly without the need for someone to rebuild application bundles.
On the other hand, this third approach requires a bit more effort from developers. Unlike the other two approaches, the names of the resources do not show up WOBuilder. Potential problems can arise as developers enter image file names in component bindings, sometimes misspelling them. However, if the images are installed locally in the webserver document root, WOBuilder will render them immediately, so you get feedback right away if you make a typo.
The trick I use for this is to create a Static Resources directory adjacent to my project directory and create a symbolic link to it from the webserver document root. This allows me to do an update or commit to my source code control system from the directory containing the project and the resource directories to update or commit them both at the same time. Once the link is in place I can forget (on my development machine anyway) about updating the webserver content.
Summary
My personal favorite is approach number three. CodeFab’s development projects almost always get large and complex enough that there are resources that need to be shared beyond what a WO framework provides. Additionally we often end up with static HTML pages, CSS files, JavaScript files, etc. that do not really belong inside the project. Your personal mileage may vary.
All three of the approaches discussed here are in wide use. Based on the requirements of a particular application, we recommend that you chose one of them and stick with it. Especially on projects with multiple developers it is a good idea to make this system architecture decision early and make sure everyone understands it.
