Saturday, December 31, 2011

XQuery vs XSLT comparison: which to use?


The advantages of XSLT:
* XSLT is in xml format, thus XSLT files can be parsed, validated, dynamically created (e.g. using templates) using xml / soa tools.
* Pull/program-driven approach: XSLT works well to query high structured / predictable documents (e.g. a WSDL-defined SOAP message)
* The template is the strong point of XSLT, although it's possible to simulate this with a user-defined xquery function using tree transversal.
* With xsl:import you can override templates, thus improving reusability (analogous to inheritance & polymorphism in OO languages.)

The advantages of Xquery:
* Push/content-driven approach: Xquery is easier than XSLT to deal with loose structure / less predictable documents (e.g. html) where the stylesheets have to react dynamically to the content of the child elements.
* Xquery is less verbose and less cumbersome compared with XSLT, thus it's easier to learn.
* Xquery applies type strictness using the datatype definitions in the schemas.

Other factors to decide is the supports in the tools you used, e.g. Oracle Soa suite has better xslt editor, no xquery editor. On the other hand, the Oracle OSB has better xquery support than xslt. In general XSLT is better adopted in the SOA tools than Xquery, especially the old tools.

My experience: in my job I need to learn them both, when I started to use xml transformation in my job (about 2006) xquery was not exist, so xslt was the only option. Nowadays people in my office use xquery instead of xslt since they use oracle osb more, which has better xquery support, so I need to learn to adopt xquery more.

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




References:

XSLT: Axis and Predicate power!

This blog shows you about how to take advantage of axis and predicate in xpath expression: axis::test[predicate].
For example you have this XML:

<Projects>
<Project>
<ProjectName> Teach my toddler computer </ProjectName>

<ProjectActivities>
<ProjectActivity>
<ActivityName> Install Qimo Linux </ActivityName>
</ProjectActivity>
<ProjectActivity>
<ActivityName> Teach mouse game for mouse training </ActivityName >
</ProjectActivity>
</ProjectActivities>

<Elements>
<ProjectElement>
<ElementName>mouse skills</ElementName>
</ProjectElement>
<ProjectElement>
<ElementName>menu navigation</ElementName>
</ProjectElement>
</Elements>
</Project>

<Project>

<ProjectName> Make my wife happy</ProjectName>

<ProjectActivities>
<ProjectActivity>
<ActivityName> Buying flowers </ActivityName>
</ProjectActivity>
<ProjectActivity>
<ActivityName> Morning kiss </ActivityName >
</ProjectActivity>
</ProjectActivities>

<Elements>
<ProjectElement>
<ElementName>love</ElementName>
</ProjectElement>
</Elements>
</Project>

<Projects>

you want to transform this XML to this text:

Project: Teach my toddler computer
*Activities: Install Qimo Linux
**Elements: mouse skills, menu navigation
*Activities: Teach mouse game for mouse
**Elements: mouse skills, menu navigation
Project: Make my wife happy
*Activities: Buying flowers
**Elements: love
*Activities: Morning kiss
**Elements: love

using this xslt:


<xsl:for-each select="//Projects/Project">
<xsl:variable name="nuproj" select="ProjectName"/>
Project:<xsl:value-of select="ActivityName"/>,
<xsl:for-each select="ProjectActivities/ProjectActivity">
*Activities:<xsl:value-of select="ActivityName"/>,
<xsl:text></xsl:text>
<xsl:for-each select="following::Elements[parent::Project/ProjectName=$nuproj]/ProjectElement">
**Elements:<xsl:value-of select="ElementName"/> ,
</xsl:for-each>
<xsl:text></xsl:text>
</xsl:for-each>
<xsl:text></xsl:text>
</xsl:for-each>



In this xsl we iterate over ProjectActivity within each Project. So during this iteration the current context is in a ProjectActivity, while you want also to iterate over each Elements/ProjectElement. We solve this using xpath expression in the form of axis::test[predicate] :

following::Elements[parent::Project/ProjectName=$nuproj]/ProjectElement

so the "following" is the axis which tells that we select the Elements/ProjectElement located following the current context ProjectActivity. There many as other axis expression such as preceding, parents, descendants, etc which specifies the location relative to the current context.

[parent::Project/ProjectName=$nuproj] is the predicate, which specifies the condition of which Elements node to be selected (since there are more than one Elements nodes located following the current context ProjectActivity. In this case we specify that the Elements node to be selected should have a parent Project which has Project/ProjectName node with value equal to the variable $nuproj, i.e. the Elements node that belongs to the same Project with the current context ProjectActivity.

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




References:


Jesper Tverskov's axis tutorial
XSLT 2.0 and XPath 2.0 Programmer's Reference

Testing for Empty Elements in XSLT & Xquery


While processing an XML with XSLT sometimes you need to access a node but you want to make sure that that node exists otherwise the XSLT processor will complain (analogous to the infamous null point exception in Java).

For example using this XML:

<Projects>
<Project>
<ProjectName> Teach my toddler computer </ProjectName>
<ProjectActivities>
<ProjectActivity>
<ActivityName> Install Qimo Linux </ActivityName>
</ProjectActivity>
<ProjectActivity>
<ActivityName> Teach mouse game for mouse training </ActivityName >
</ProjectActivity>
</ProjectActivities>
</Project>

<Project>
<ProjectName> Teach my kids piano </ProjectName>
<ProjectActivities/>
</Project>

<Projects>

Suppose you want to iterate over ProjectActivity within project, but some project has no ProjectActivity (such as the "Teach my kids piano" project above).

XSLT solution
* To test if the element exists in XSLT you can use: xsl:if test="ProjectActivities/ProjectActivity".
*
To test if the element exists and non-empty: xsl:if test="string(ProjectActivities/ProjectActivity)".
*To test that the element exists and has text or any element content (e.g. subnodes or attributes): xsl:if test=" ProjectActivities/ProjectActivity/text() or ProjectActivities/ProjectActivity/*"

So for example using this test in this XSL:

<xsl:for-each select="//Projects/Project">
<xsl:variable name="nuproj" select="ProjectName"/>
Project:<xsl:value-of select="ActivityName"/>
<xsl:if test="ProjectActivities/ProjectActivity">
<xsl:for-each select="ProjectActivities/ProjectActivity">
To do:<xsl:value-of select="ActivityName"/>
<xsl:text></xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text></xsl:text>
</xsl:for-each>

you will expect this result:

Project: Teach my toddler computer
To do: Install Qimo Linux
Project: Teach my kids piano

Xquery solution:
* To test if the element exists :exists($ProjectVariable/ProjectActivities/ProjectActivity)
or using similar strategy used by xslt above:
if ($ProjectVariable/ProjectActivities/ProjectActivity) then ... else ...

*To test if the string non-empty:string-length($ProjectVariable/ProjectActivities/ProjectActivity) != 0)
or using similar strategy used by xslt above:
if (string($ProjectVariable/ProjectActivities/ProjectActivity)!="") then ... else ...

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




References:
XSLT Empty Element tutorial

Beginning XSLT and XPath: by Ian Williams

Tuesday, December 20, 2011

Maven, Artifactory and Hudson for Oracle OSB Continuous Integration

In the previous blog we discussed about using Ant and Hudson/Jenkins for continuous integration. What hasn't been explicitly discussed is about dependency management, that Maven can handsomely handle.

The benefits of using Maven instead of Ant:
1. standardization following best practices (e.g. directory structure) that leads to shorter/simpler configuration file (pom.xml), less maintenance, and higher reusability
2. transitive dependency management: Maven will find and solve the conflicts of the libraries needed. Perhaps you know this concept already if you've used ivy framework with Ant, but this concept is central in Maven so that lots of innovations has been implemented regarding this feature (e.g. enterprise repositories).
For example I just made adjustment and commited StudentRegistrationService-ver2.0 which depends on LDAPService-ver2.0 and hibernate-ver3.jar. When I deploy the StudentRegistrationService-ver2.0, Maven will include also the LDAPService-ver2.0 and hibernate-ver3.jar from a enterprise repository that stores all the libraries used in your company. If the build & test processes success, the artifact of my new StudentRegistrationService-ver2.0 will be included in the repository, so other services which consume my service will be able to use this version 2.0 of my service. Strong enough, you can specify the version dependencies using ranges (e.g. min version, max version), so I can specify that my service depends on LDAPService max version 2.0 (since I don't support the new interface of the newer LDAPService yet) and also depends on PaymentService min version 3.1.1 since there is a payment bug in the PaymentService version lower than 3.1.1. Here is an example of defining these dependencies in the pom.xml of the StudentRegistrationService:

<dependency>
<groupId>TUD</groupId>
<artifactId>LDAPService</artifactId>
<version>[0,2.0]</version>
</dependency>

<dependency>
<groupId>TUD</groupId>
<artifactId>PaymentService</artifactId>
<version>[3.1.1,)</version>
</dependency>

An illustration about how it works:


1. Using Hudson/Jenkins to let the svn commit trigger the Maven build
Please see the previous blog about how to install and setup Hudson/Jenkins.

For this example, I specify Hudson/Jenkins to pool the svn server every minute (set by the schedule "* * * * *" using cron format). When there is a new commit in the mysvnproject, the Maven "install" goal (along with its previous lifecycles phases i.e. compile, test) will be invoked.


2a. Checkout using mvn-scm plugin

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.1</version>
<configuration>
<username>username</username>
<password>password</password>
</configuration>
<execution>
<id>checkout</id>
<configuration>
<connectionUrl>mysvnserver</connectionUrl>
<checkoutDirectory>mysvndir</checkoutDirectory>
<excludes>folder2exclude/*</excludes>
</configuration>
<phase>compile</phase>
<goals>
<goal>checkout</goal>
</goals>
</execution>
</plugin>

2b. Build the OSB, you can use the same ant task as in my previous blog, wrapped with maven-antrun-plugin.

3a. Obtain the dependencies from the repositories, using dependency:copy-dependencies or dependency:copy.

3b. Deploy the OSB project and its dependencies, you can use the same ant task as in my previous blog, wrapped with maven-antrun-plugin.

4. Run SOAP UI web service test using maven-soapui-plugin (or alternatively you can use testrunner.bat / testrunner.sh similar to my other blog)

<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>3.0</version>
<executions>
<execution>
<phase>test</phase>
<id>soapuitest</id>
<configuration>
<projectFile>${mysoapuitestfile}</projectFile>
<outputFolder>${testreportdir} </outputFolder>
<junitReport>true</junitReport>
<exportwAll>true</exportwAll>
<printReport>true</printReport>
<settingsFile>${soapuisettingfile}</settingsFile>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>

5. Archieving the artifact using an enterprise repository.
The benefit of using enterprise repository:
• your developers don't have to search, download and install the libs manually
• it's faster & more reliable than downloading the libs from internet, the concept is similar to proxy server that cache the internet.
• it will store the artifacts of your company projects from ant/maven builds, so they will be readily available for testing and shipping
• web administration interface, search, backup, import/exports

I chose Artifactory as enterprise repository since it has more features than other products, such as: xpath search inside XML/POM, hudson integration (e.g. for build promotion), conn to ldap, cloud (saas) possibility, easy install (running in an embedded jetty server or as service in Windows/Linux.)
You can use Hudson artifactory plugin to integrate Artifactory to Hudson/Jenkins process.

I use 3 local repositories inside your Artifactory for different library categories:
open source/ibibliolibraries (e.g. apache common jars), the Artifactory can download these automatically
proprietary libraries (e.g. oracle jdbc jar), you need to install these manually (e.g. via Artifactory web interface)
company libraries, you need to install these manually or via Hudson build as done in this example. For the company repository, I define such that the repository cab handle both the release/stable version (e.g. the PaymentService-ver3.1.1 which is already well tested and approved) as well as the snapshot version (e.g. I am not finished with my StudentRegistrationService-2.0 yet but I want to make it available for other projects which depend on it). For example in the artifactory.config.xml:

<localRepository>
<key>tud-repo</key>
<description>mycompany-libs</description>
<handleReleases>true</handleReleases>
<handleSnapshots>true</handleSnapshots>
</localRepository>

<localRepository>
<key>ibiblio-repo</key>
<description>stable-opensource-libs</description>
<handleReleases>true</handleReleases>
<handleSnapshots>false</handleSnapshots>
</localRepository>

You need to declare these repositories in your pom.xml (or with similar approach in settings.xml for all of your projects):

<repositories>
<repository>
<id>ibiblio-repo</id>
<url>http://myreposerver:port/artifactory/repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>tud-repo</id>
<url>http://myreposerver:port/artifactory/repo</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>ibiblio-repo</id>
<url>http://myreposerver:port/artifactory/repo</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>tud-repo</id>
<url>http://myreposerver:port/artifactory/repo</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories&gt

For the sake of clarity there are some details omitted from this blog. The concepts in this blog work also for non OSB projects (e.g. Java/J2EE applications).

Any comments are welcome :)



See also: http://soa-java.blogspot.nl/2011/03/soa-continuous-integration-test.html


References:
Setting Up a Maven Repository
Comparison Maven repository: Archiva, Artifactory, Nexus
Amis blog: Soapui test with maven


Continuous integration for Oracle OSB projects using Ant and Hudson / Jenkins

Continuous integration (CI) is pervasive. This doesn't come from nothing, CI has many benefits, such as to avoid last minute integration hell and to improve software quality


The principles of Continuous integration
1. every commit to the SCM should be build so that you'll have an early feedback if the build breaks
2. automate build for consistency
3. automate deployment for consistency
4. automate test of the build artifact for consistency
5. archive the build artifact so that it'll be readily available (e.g. for further test)
6. keep the reports & metrics from build & test

You can also add additional steps for example when this commit breaks the test you can reject the commit by rolling back the deployment (using undeploy wlst task) & roll back the svn commit using merge backward:
svn merge -r currentver:previousver ; svn commit

This blog will show how to achieve these steps using Ant and Hudson/Jenkins. We use Ant since in many organizations Ant is already well adopted compared with Maven. In another blog we will discuss how to achieve the same goal using Maven and artifact repository (e.g. Artifactory or Nexus) which are handier than Ant particularly with respect to dependency management.

How it works:
1.Using Hudson/Jenkins to let the svn-commit triggers the Ant build
I chose Hudson/Jenkins since it's easy to use, has good features, scalable and recommended by many people (including folks working at Oracle). You can see Jenkins as a new version of Hudson, Jenkins was created to avoid legal problem with Oracle when Kohsuke Kawaguchi, the Hudson's creator, left Sun/Oracle.
Installing Hudson/Jenkins is easy, in Windows it can be run as a Window service. Hudson/Jenkins contains an embedeed Winstone servlet engine, so you can also run it using
java -jar hudson.war --httpPort=aportnumber
To install Hudson/Jenkins in Weblogic you need to add the deployment descriptor weblogic.xml to solve classpath conflicts of certain jars (depend on which version you install), also Hudson/Jenkins will not work in Weblogic servers with SOA/OSB extensions due to some conflicting settings.
You can add some plugins for example locale (to set languages), svn related plugins, trac (to recognize trac tag e.g. fixed#), cvs/svn browser viewer, html report, scp artifact repository, promote builds, among others.

You need to set some configurations such as JDK location, svn connection, Ant location, Maven location, Junit test report location, artifacts location, SMTP/email server for notifications.

For this example, I specify Hudson/Jenkins to pool the svn server every minute (set by the schedule "* * * * *" using cron format). When there is a new commit in the mysvnproject, the Ant ("main" target) will be invoked.

2. Checkout the new commited svn project using svntask:

<target name="checkout">
<delete failonerror="false" includeemptydirs="true" quiet="true"
dir="${servicename}" />
<svn username="${subversion.user}" password="${subversion.password}">
<checkout url="${subversion.path}" destPath="${servicename}" />
</svn>
</target>

Build this code to an OSB project using ConfigExport

<target name="makeosbjar" depends="deletemetadata">

<!-- osb jar compile -->
<java dir="${osb.eclipse.home}"
jar="${osb.eclipse.home}/plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar"
fork="true"
failonerror="true"
maxmemory="768m">
<jvmarg line="-XX:MaxPermSize=256m" />
<arg line="-application com.bea.alsb.core.ConfigExport" />
<arg line="-data ${workdir}" />
<arg line="-configProject ${osb.config.project}" />
<arg line="-configJar ${jardir}/${packagename}" />
<arg line="-configSubProjects ${servicename}" />
<sysproperty key="weblogic.home" value="${osb.weblogic.home}" />
<sysproperty key="osb.home" value="${osb.home}" />
</java>
</target>

3. Deploy the jar to the OSB server using WLST import (a python script)

<target name="deployOSB">
<wlst fileName="${import.script}" debug="true" failOnError="false"
arguments="${wls.username} ${wls.password} ${wls.server} ${servicename} ${jardir}/${packagename} ${import.customFile}">
<script> <!-- run these before import.py -->
adminUser=sys.argv[1]
adminPassword=sys.argv[2]
adminUrl=sys.argv[3]
passphrase = "osb"
project=sys.argv[4]
importJar=sys.argv[5]
customFile=sys.argv[6]
connect(adminUser,adminPassword,adminUrl)
domainRuntime()
</script>
</wlst>
</target>

4. Run the SOAPUI web service test and generate the junit test report:
<target name="soapui-test">
<exec executable="cmd.exe" osfamily="windows" failonerror="false">
<arg line="/c ${testrunner.bat} -j -freports ${soapui.test}"/>
</exec>

<junitreport todir="${testreportdir}">
<fileset dir="reports">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${testreportdir}/html"/>
</junitreport>
</target>


Example of Hudson/Jenkins output:

Hudson also sent email notifications:

For the sake of clarity, there are some details omitted from this blog (e.g. the ant classpath for lib needed: svnant, svnjavahl, svnclientadapter, xmltask), these details will be found in the build.xml. Please download the build.xml, build.properties and the import.py wlst here.

The concepts in this blog work also for non OSB projects (e.g. Java/J2EE applications).

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




The file download is made possible by OpenDrive


References:

Using the Oracle Service Bus Plug-ins for Workshop for WebLogic http://docs.oracle.com/cd/E13159_01/osb/docs10gr3/eclipsehelp/tasks.html
Using WLST http://docs.oracle.com/cd/E15051_01/wls/docs103/config_scripting/using_WLST.html
Biemond's blog http://biemond.blogspot.com/2010/07/osb-11g-ant-deployment-scripts.html
How-to-deploy-Hudson-to-weblogic http://jenkins.361315.n4.nabble.com/How-to-deploy-Hudson-to-weblogic-td3246817.html

VMware virtual network configuration: NAT port forwarding

Playing with virtualization is fun. You can entertain yourself as if you have an army of many computers, connected with one or more (virtual) networks.

There are 3 possible configurations of virtual networking in VMware:

1.Host-only: the virtual computers (VM) are connected each other in the virtual networks inside a host (myPC), which is connected to the internet via IP 123.456.789.012. They can access the internet data but it's impossible for a computer in the internet (e.g. Annie) to send request to these VM since the virtual networks are private (e.g. IP in the 198.168.X.X range).

2.Bridge: you're lucky. The network administrator in your company is your best friend, so he gave you several free slots of IP addresses. Thus the VM has its own IP address (e.g. 123.456.789.013). The VM acts just like a real PC, the computers in the internet can reach this VM.

3. NAT: Well, your organization has a limited IP addresses, but with NAT you can still have possibility to let other computers in the internet to access your VM. For example you have a webserver using port 333 in the VM 198.168.11.12, using Network Address Translation (NAT) you can use the port 444 in the myPC host 123.456.789.012 to expose this webserver to the internet.

The vmware network configuration can be set using vmware-config.pl in Linux or vmnetcfg.exe in Windows. Here is a screenshot example over how to configure the NAT / port forwarding from the host 123.456.789.012:444 to the VM webserver in 198.168.11.12:333.



Notes:
How to get vmnetcfg.exe for VMware Player Windows:
  1. Download the installer
  2. Extract the installer: VMware-player-installer.exe /e tempdir
  3. Extract the network.cab in the tempdir, it contains vmnetcfg.exe
If you update the VMware Player vmnetcfg.exe is not extracted by standard installation so the vmnetcfg.exe in your VMware directory  is still the old version that missmatch with the new VMware version. Thus you need to repeat this procedure to replace the old vmnetcfg.exe in your VMware directory.


Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




Note: you can achieve the same thing with iptables service in linux, but this vmware-config approach is easier.

References:

Monday, December 19, 2011

Android Simulator : simple up and running...


You don't have a smartphone yet but you're curious about how your website looks like in a smartphone?

Cost: free
Time needed: 5 minutes
Steps:
1. download and install the Android development SDK: http://developer.android.com/sdk/index.html
2. create an Android Virtual Device (AVD) profile: startmenu>manage ACD>create an AVD (e.g. Android 2.3.3 HVGA)
3. run the emulator: e.g. emulator -avd name-of-your-avd




Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)

Mobile web development


Why mobile webs are different
You need to adapt your web application since the usability of mobile usage is different compared to the desktop:
• smaller screen size (e.g. 320x480)
• vast variations of browsers & platforms (each with different limitations & compatibilities e.g. some doesn't support javascript yet)
• competing attentions / multitasking users (e.g. the user may use the mobile while waiting for a bus or talking to friends), this leads to more distractability and shorter session (3 min in average instead of 10 min average of desktop users).
• different input devices (e.g. multitouch & virtual keyboard via touch screen instead of desktop keyboard & mouse)

Design strategies
• define user's goals and how they can accomplish their goal in your web with minimum efforts (i.e. minimum clicks/inputs)
• prioritize the features of the desktop version of your web, implement only the top 20% in your mobile version

Usability tips
Simplicity
• implement only 20% of the features of your desktop web application
• minimize user efforts & user inputs, try to infer the context from history/cookies, geolocation, IP address
• no more than 3 clicks (or pages) depth
• limit the main navigation to 4 links, limit the total links in a page to 10
• minimize text, use short/simple words
• to the point, no welcome screen
• limit the bandwidth: simple image, don't use text-image. The bigger the bandwidth, the more users have to pay & the slower your service is.

Layout
• avoid horizontal scrolling
• avoid multi columns
• use all area, 100% width (don't use side menu, side advertisements etc)
• use fluid layout instead of fixed layout

General tips
• always provide a link to the desktop version
• the most used features at the top (e.g. login in a bank service, search in a library service)
• provide enough space (min 20px) for clickable elements and links, since finger touches need more space than using a mouse
• use background colours to separate sections
• use a list instead of a table

Beside these, many of the desktop UI usability rules are still apply in the mobile world, such as visual consistency, legible fonts, clear structure, consistent alignments, etc

Device awareness and content adaptation
A common approach to handle the variations of mobile browsers/platforms is
by grouping according to device/browser capabilities (the groups don't need to be mutually exclusive) for example based on screen resolution, portrait/landscape orientation support, javascript/ajax support, geolocation support, markup languages (old wml,xhtml-mp,html5).

Starting with a basic version of your web (e.g. a plain html without css & javascript), create a different version for each group (e.g. different screen resolution) using different css and technologies (javascript, geolocation, etc).

Your web application needs to aware about the capabilities of the client browser/device and then adapts the content according to which group this device falls to. So first we need to know which browser/device the client uses, using http request header information, for example an (rather old) iphone:

User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2_1 like Mac OS X;
en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1
Mobile/5H11 Safari/525.20
Accept: text/xml,application/xml,application/xhtml+xml,


Then using device libraries (e.g. WURFL) to get the list of device/browser capabilities (screen size, javascript/ajax support, etc).

The weakness of this approach is that you need to maintain several versions of your code (e.g. iphone4.css, iphone3.css, android23.css, vintagemobile.css, ....). The mobile/device list is changing fast, you need to keep up with this (and hopefully also the maintainers of the device library you use). The information in the request header & the device libraries may not be accurate. That why it's recommended to limit the number of groups as minimum as possible.

An example of comparison of a desktop and mobile website
Amazon is one of the most progressive dot.com company, we can learn by observing their design. This is the desktop version:


This is the mobile version (Android simulator, 320x480):

The mobile version has
• much less features than the desktop version
• less text, less images
• list (for links)
• one column
• the most important features in the top of the pages (the shopping cart and the search.)

In the future I will discuss how to implement geolocation mobile web to determine in which building a student is located. Based on this, we provide contextual information to the student for example about the course room/schedule, computer labs availability, the locations of other students from the same course/study-year.

Source: Steve's blogs http://soa-java.blogspot.com/

Any comments are welcome :)




References:
Programming the Mobile Web


Beginning Smartphone Web Development


The UI snapshot examples are the courtesy of www.amazon.com