WebObjects

Eurovision Song Contest: 150 Million Viewers Cannot Be Wrong!

Tuesday, May 30th, 2006

Our friends at Phonofile have done it again. The software we developed with them (see European Digital Music Downloads - Wholesale!) was used for the on-line store and music download site for the Eurovision Song Contest. The WebObjects and WireHose based store application can be found here: http://www.eurovisiondownloadshop.tv.

Eurovision is big. Really big. This year was it’s 50th anniversary contest (can you see “American Idol” lasting 50 years? I can’t.) And the rivalry between countries can be fierce. (See the enormous Wikipedia entry to see who won, who lost and who hates who.)

What does this mean for our WebObjects application? A peak load of between 2,500 and 3,000 concurrent sessions (with 20 minute timeout) and a sustained download rate during the finals of 6MB/second. Yowza! And this is just one of Phonofile’s dozens of custom portals all running against a common backend infrastructure. Sweet.

WebObjects/EOF Patch: Better Way to Limit Fetches with OpenBase

Saturday, February 11th, 2006

Some background first. When writing a WebObjects / EOF application there are many, many situations where you want to run a query against the database, but you really don’t need all the matching rows. Most typical is when your end user does a query against a huge pile of data and you want to limit what is displayed to a single page of results (trust me - they always find a way to run a fetch that returns the whole database). EOFetchSpecification allows you to add a fetch limit to queries and this does what you want - only returns (at most) that many matching objects.

So we are good, right?

Well, there is a little problem hiding in the magic of automatic generation of SQL by EOF. EOF generally does a great job when the SQL being generated is “standard” - i.e. part of the SQL 92 standard implemented by most database vendors and well handled by JDBC. Unfortunately the concept of fetch limits was, umm, overlooked by the standards folks. This meant that the database vendors all chose their own syntax and now the commands for limiting results are quite different from vendor to vendor. In Sybase you send a separate command first: SET ROWCOUNT XXX. In Oracle there are several approaches, all with some tradeoffs. OpenBase SQL uses RETURN RESULTS XXX at the end of the SQL statement. In Postgres it is LIMIT XXX.

To work around this, EOF takes an approach that is simple and effective, but less than optimal. EOF fetches all the results from the data server and then just turns the requested subset into actual EO objects and discards the rest of the data. This works, and uses less memory than turning all the rows of data into objects, but thats all the good things you can really say. And on the bad side, the database server may need to marshal all the results that match and may end up shipping all the data across the network to your application.

I recently was working on a project that allowed end users to search through a very large amount of data. Not only was this allowed, it was the primary form of user interaction with our application. Most of the users would be searching, most of the time. In all cases we needed to limit their results to a single page of potential matches. As the number of users in our application scaled up, the server ended up spending most of its time handling these searches and the memory footprint of the dataserver grew unacceptably large as it tried to process all these fetches at once. Compounding this was the fact that often seemingly innocuous queries from the users actually matched tens of thousands of records, from which we needed at most 100.

The database server we were using was OpenBase. In order to increase our capacity we needed to lower the load on the dataserver. Working with the excellent team at OpenBase we figured out that we could get a big boost if we could shift from the default EOF client-side fetch limit approach to a server side solution by using the RETURN RESULTS XXX syntax and having the dataserver limit the results before data was sent back to the client.

This was a large application with a complex data model and many places where queries were done. We immediately rejected the approach of switching from dynamically generated SQL to hand coded SQL just to be able to add the fetch limit clause to the end of the command. Additionally, we had a large code-base already in production and we wanted a solution that involved changing as little of the existing code as possible. The solution was to modify the JDBC plugin that actually generated the database vendor-specific SQL commands from the generic activities of the EOF layer.

I obtained the latest version of the OpenBase plugin from the downloads area of the OpenBase site. This is kindly distributed in source form. This plugin does a lot more than just support fetching - it handles inserts, updates, primary key generation and table creation. (NOTE: You should also be linking to the OpenBasePKPlugin framework for optimal primary key generation with OpenBase.) At first blush this looked to be an easy upgrade - there is an obvious method called assembleSelectStatementWithAttributes that creates the select string from various attributes passed in. Unfortunately, the attributes do not include the fetch limit number or the FetchSpecification. After much more digging into this area of EOF that I had never really investigated before, I discovered there was another method that gets called on the plugin’s JDBCExpression subclass that was defined but not overridden by OpenBase’s existing implementation called prepareSelectExpressionWithAttributes that does get called with the original EOFetchSpecification. Problem solved! I grab the fetch limit number there (if there is one) and hold on to it until assembleSelectStatementWithAttributes gets called a few steps later in the SQL generation.

The modified plugin code has been returned to OpenBase and will be available for download from them soon. It will also eventually replace the version currently included with WebObjects. For now, you have permission from OpenBase to download it from here as well.

NOTE from the README: “This plugin code replaces the OpenBasePlugin inside WebObjects. Since it is a replacement and not a subclass, it needs to be included inside your application jar. The only problem with this approach is that it will not work as part of a framework.”

Download the plugin: OpenBasePlugin.java

Download the README: OpenBasePlugIn_README.rtf

European Digital Music Downloads - Wholesale!

Sunday, January 29th, 2006

CodeFab and WireHose were selected to help architect and implement a huge digital media project for Phonofile DK. The Phonofile music download platform, based on WebObjects and the WireHose frameworks, and offers a tailored digital music and e-commerce solution allowing any website, retailer, consumer brand company, or service provider to offer digital music products. The shop is an ala Carte based standard download shop system or a SOAP based API enabling customers to build their own shops.

CodeFab and Gary Teter from WireHose were primarily responsible for the core data modeling and the architecture of the core business logic and display frameworks. We built the rules based product pricing engine, the e-commerce infrastructure, the interface to the Digital Rights Managements system and the SOAP web services api. We were assisted for a time by Chuck Hill and Sacha Mailais from Global Villiage. The deal was closed by Lori Cone of Bulldog Beach who also helped manage the project. The project was started in May 2005 from scratch and opened the first portals in September 2005.

Here are some of the sites implemented with the platform we developed. These sites all use a common backend / database / repository and are only a sampling of the dozen+ custom portals currently in production using this infrastructure:

(Lycos of Sweden)

(a site built using the SOAP interface)


(a site built using Flash. Uziing is the Scandinavian Toys-R-Us and they wanted a “toy like” user interface.)

sorry the sites are all in Danish and Swedish…