vADC Blog

Simply WURFL (08/07/2009)

by yvan on ‎12-10-2012 12:00 AM (1,198 Views)

Simply WURFL (08/07/2009)

WURFL?! Yes, another acronym:

<a title="WURFL" href="http://wurfl.sourceforge.net/" target="_blank">*Wireless Universal Resource FiLe*</a>

The WURFL website expands on this:

136_23426.png

"

<a title="What's the WURFL? - Luca Passani" href="http://wurfl.sourceforge.net/backgroundinfo.php" target="_blank">*You can think of the WURFL as a global database of all devices and their capabilities.*</a>

" Such a database is especially useful in the current mobile device landscape where a vast array of HTML/WML/Flash/AJAX features are implemented differently (or not at all.) In essence, WURFL makes it easier for you to improve the web experience you offer people when they are on the move.

WURFL is the product of much diligence and attention to detail by Luca Passani and many contributors of device information. As an added bonus it is open and free for anyone to use. This is in the best interests of mobile device users everywhere of course! Luckily for us the WURFL project goes all the way and provides a Java API. To get started with WURFL you first need to ensure your Stingray Traffic Manager has working Java support and then download the following items.

<a title="Download WURFL" href="http://sourceforge.net/projects/wurfl/files/WURFL/" target="_blank">*wurfl-latest.zip*</a>

- the WURFL itself

<a title="web_browsers_path.xml" href="http://wurfl.sourceforge.net/web_browsers_patch.xml" target="_blank">*web_browsers_patch.xml*</a>

- an optional file that adds data for desktop web browsers

<a title="Download WURFL Java API" href="http://sourceforge.net/projects/wurfl/files/WURFL%20Java%20API/" target="_blank">*wurfl-1.0.jar*</a>

- get the most recent WURFL .jar file, 1.0 at the time of writing

<a title="Collections Downloads" href="http://commons.apache.org/downloads/download_collections.cgi" target="_blank">*commons-collections*</a>

- extract the commons-collections-

<a title="Lang Downloads" href="http://commons.apache.org/downloads/download_lang.cgi" target="_blank">*commons-lang*</a>

- extract the commons-lang-

<a title="Logging Downloads" href="http://commons.apache.org/downloads/download_logging.cgi" target="_blank">*commons-logging*</a>

- extract the commons-logging-

<a title="backport-util-concurrent" href="http://sourceforge.net/projects/backport-jsr166/files/backport-jsr166/" target="_blank">*backport-util-concurrent*</a>

- download most appropriate 3.x release (backport-util-concurrent-Java60-3.1.tar.gz in my case) and extract the backport-util-concurrent.jar file from it

Upload the files specified using the Calalogs > Java UI page on your Stingray Traffic Manager. Note that the wurfl-latest.zipcan be uploaded as-is, but you can choose to unzip it and upload the wurfl.xml file. Now you're all set to experiment with the following examples.

The first sample servlet is a very simple use-case of WURFL, useful as a base for your own servlet or for debugging. The intention is for it to introduce the WURFL API as it fits within the framework of Stingray Java Extensions. WURFL is typically configured using the ConfigListener model, but we're not TomCat and don't go as far as implementing all the nuts and bolts required by full web applications. Our WURFL servlet must perform the required initialisation itself, so I've implemented an init method that sets up a WURFLManager. As much work as possible is done at servlet initialisation time. Then all the doGet method needs to do is check the request against the pre-initialised WURFLManager. You can download

<a href="http://blogs.riverbed.com/files/zeuswurflinfoservlet.java" target="_blank">*the code*</a>

or the

<a href="http://blogs.riverbed.com/files/zeuswurflinfoservlet.class" target="_blank">*compiled class*</a>

for this servlet. To compile the code yourself execute the following javac command. This example is given for compiling on the Stingray host system after all the .jar files mentioned above have been uploaded to your Stingray Traffic Manager, you can also compile the servlet on another machine as outlined in our

<a href="https://support.riverbed.com/docs/stingray/trafficmanager.htm" target="_blank">*Java Devlopment Guide*</a>

.

javac -cp "$ZEUSHOME/zxtm/lib/*:$ZEUSHOME/zxtm/conf/jars/wurfl-1.0.jar" \
StingrayWURFLInfoServlet.java

To get the servlet working follow these steps:

Upload the ZeusWURFLInfoServlet.class file using Stingray Catalogs > Java UI page, leave the "Automatically create TrafficScript rule" checkbox ticked

If you want normal web browsers to be detected properly click on the ZeusWURFLInfoServlet link on the UI page and add the parameter "wurfl_patches" with the value "web_browsers_patch.xml" (which you must also upload to the Catalogs > Javapage as covered above)

    1. Set up a Virtual Server for testing, I set one up listening on port 60000 and tied it to the special "discard" pool

Associate the auto-generated ZeusWURFLInfoServlet rule with the test Virtual Server as a request rule

    1. Visit your virtual server in some different web browsers!


The result should be a page showing some general information about your browser at the top followed by the full table of WURFL capabilities and their values. The following screenshots show the top part of the output using a few browsers available in the Stingray office.

Firefox on Ubuntu Linux

872i7EEE39C2804BDEA6.png

Opera on HTC S710

874i8CD9C2EA37135684.png

IE on HTC S710

876iF73BF8B69BAE97D9.png

Safari on iPhone

878i123767D7EB9648B7.jpg

This is neat and all as a demo, but not particularly useful. What we really want is a module that can export capabilities so that they can be used by TrafficScript and other extensions. We also don't want to specifically be a doGet processor, so we'll modify the servlet along the lines described in the

<a href="/t5/Code-Samples/Writing-TrafficScript-functions-in-Java/td-p/17094" target="_blank">*Writing TrafficScript functions in Java*</a>

article.

There are a lot of capabilities covered by WURFL, the tables in the above screenshots go on for several pages - more than 500 capabilities in all. So we'll make it possible for TrafficScript to specify what capability fields it wants.

This gives us a servlet that could be used from TrafficScript using the following function.

  1. sub checkWURFL() {
  2. $ua = http.getHeader( "User-Agent" );
  3. if (!string.length($ua)) return;
  4. $markup = data.get("WURFL" . $ua . "preferred_markup");
  5. $datarate = data.get("WURFL" . $ua . "max_data_rate");
  6. if (string.length($markup)) {
  7. log.info("Returning cached values for User-Agent: " .
  8. $datarate . ", " . $markup);
  9. $1 = $markup;
  10. $2 = $datarate;
  11. return;
  12. }
  13. # no cached values for the UA, so run it through WURFL
  14. java.run( "ZeusWURFLServlet", "max_data_rate", "preferred_markup" );
  15. $markup = connection.data.get("preferred_markup");
  16. $datarate = connection.data.get("max_data_rate");
  17. data.set("WURFL" . $ua . "preferred_markup", $markup);
  18. data.set("WURFL" . $ua . "max_data_rate", $datarate);
  19. log.info("Returning fresh WURFL values for User-Agent: " .
  20. $datarate . ", " . $markup);
  21. $1 = $markup;
  22. $2 = $datarate;
  23. return;
  24. }
  25. # simple case to test the checkWURFL function
  26. checkWURFL();
  27. http.sendResponse("200", "text/html",
  28. "" .
  29. "h1. Max Data Rate: " . $2 . "kbps
    " .
  30. "h1. Preferred Markup: " . $1 . "
    ", "");

The corresponding Java code and .jar file are available for you to download.

<a href="/t5/Articles/Apache-Commons-Logging-08-07-2009/m-p/23438#M101" target="_blank">*Zeus*</a>

http://blogs.riverbed.com/files/zeuswurflservlet.javaWURFLServlet.java

<a href="http://blogs.riverbed.com/files/zeuswurflservlet.jar" target="_blank">*ZeusWURFLServlet.jar*</a>

Rather than the doGet method implemented in the ZeusWURFLInfoServlet we now have a simpler service method.


  1. public void service(HttpServletRequest request, HttpServletResponse response)
  2. throws ServletException, IOException {
  3. String[] args = (String[])request.getAttribute( "args" );
  4. if (args == null || args.length == 0) {
  5. throw new ServletException("error: no arguments supplied");
  6. }
  7. Device device = manager.getDeviceForRequest(request);
  8. Map capabilities = device.getCapabilities();
  9. for (int i = 0; i < args.length; ++i) {
  10. String cap = (String)capabilities.get(args);
  11. if (cap == null) {
  12. log("no capability found matching: " + args);
  13. } else {
  14. ((ZXTMServletRequest)request).setConnectionData( args, cap );
  15. }
  16. }
  17. }

Note that for this implementation I've included another class that properly directs org.apache.commons.logging messages to the Stingray Event Log properly. The logging code is

<a href="http://blogs.riverbed.com/stingray/2009/08/apache-commons-logging.html" target="_self">*documented here*</a>

, you can also download ZeusServletLogger.class here or from that page. The commands used to build the jar file on my Stingray host machine follow.

javac -cp "$ZEUSHOME/zxtm/lib/*:$ZEUSHOME/zxtm/conf/jars/wurfl-1.0.jar" \
ZeusWURFLServlet.java
jar -cvf ZeusWURFLServlet.jar ZeusWURFLServlet.class ZeusServletLogger.class

There is much more you could do with the WURFL Java Extension provided in this article. Think of it as a starting point for developing your own solutions to improve the web browsing experience of your mobile users.

A few examples:

    1. The max_data_rate value retrieved above could be used to reduce image quality or size for people with low bandwidth devices. This would result in a snappier web browsing experience for these people as there would be less data for them to retrieve over their slow links.
    2. The preferred_markup value can be used to direct clients to different backend pools based on whether they can handle XHTML, or should be served WML.
    3. The streaming_flv value can be checked to see if the device has Flash video support and can thus be sent to your full bells-and-whistles website. A scaled down version could be made for those that only have Flash Lite, which is specified by the value of flash_lite_version. Devices that don't support flash at all (such as the iPhone) can be sent to a plain HTML version of the site, or WML as in the previous bullet point.

Speaking of the iPhone, it doesn't have Flash but its browser does have excellent AJAX support. You know your site is being visited by an iPhone user using the normal iPhone web browser when model_name is "iPhone" and mobile_browser is "Safari". If there are important differences between iPhone OS releases you can also check model_extra_info ordevice_os_version for this detail.

    1. For AJAX in general there are a whole set of specific properties:
    1. ajax_manipulate_css
    2. ajax_manipulate_dom
    3. ajax_support_event_listener
    4. ajax_support_events
    5. ...

Up to date documentation on all the WURFL capabilities can be found on the

<a title="WURFL Devices and WURFL Capabilities" href="http://wurfl.sourceforge.net/help_doc.php" target="_blank">*WURFL website*</a>

.

Any of these values can also be passed on to your backend nodes of course. You could add special headers containing the values, a cookie, or a URL argument. You could also cache browser capabilities uniquely to each device with cookies or another method of session tracking, rather than cache the capabilities based solely on the user agent. Then you could offer users the ability to override special mobile device modes.

We would love to hear your ideas and learn how we can help you in this exciting area - the opportunities are practically limitless.