Skip to main content

Building an eBay Rich Client using the XUI Framework

January 12, 2006

{cs.r.title}









Contents
The eBay SDK
XUI in a Nutshell
Integrating the Data Model
Wrapping the SDK
Coordinating the Interaction
Building a Store
Does this Constitute Rich-Client?
Downsides
Why not Ajax?
Conclusion
Resources

Today eBay is a juggernaut of
e-commerce, with millions of users and companies worldwide using the
service on a daily basis. One of the attractions is the ease of use
of the service: it's very easy to get started with eBay, whether
you are buying or selling. However, while the eBay browser-based
interface is perfectly adequate for many, power users may find it a
bit frustrating to use on a day-to-day basis. Network latency and
other delays mean that interaction with eBay, like any other web
service, is not as responsive as the most demanding of users would
like.

Repetitive processes can prove frustrating, particularly when it
seems that some of the information and state could be reused or
handled in a smarter way, but that is the way of most browser-based
applications. Rich-client applications fit nicely in this sort of
niche, making use of client-side computing power and storage for
more efficient use of data and fewer roundtrips to the server.

Many users also seek additional functionality to extend and
automate common tasks. Auction sniping (automated bidding), for
example, is a much-used but frowned-upon add-on for many eBay power
users. However, much of the potential for using eBay is not just in
speeding things up, but in creating new ways of interacting with the
service. In response to the demand for extensions, alternative
interfaces, and integration capabilities, eBay has released a Java
SDK for their service.

Taking the eBay
SDK
and XUI, an open source
Java and XML framework for building rich-client applications, is a
good way to create an alternative to the browser based interfaces
to eBay. XUI harnesses desktop computing power to improve the
overall end-user experience. Building a XUI rich client for eBay
makes it possible to use this latent power, add features, and
improve upon a service that is already phenomenally popular.

The eBay SDK

The eBay SDK is delivered in several forms, including a Java SDK
that wraps a set of "http://en.wikipedia.org/wiki/SOAP">SOAP interfaces. The Java
SDK provides an easy way to interact with a large part of the eBay
service, allowing you to query user and account information, add
items, and create auctions.

The SDK is a relatively thin wrapper around the SOAP services,
and so the interfaces offered may not be the most natural or
convenient for the desktop Java developer. For instance, the SDK is
structured around the individual SOAP services and exposes some low-level details of those services. The SDK also does little to tie
the various API calls together, so some work needs to be done to
coordinate calls to the SDK. While a lot easier to use than a raw
SOAP API, a further layer of software like "https://xui-ebay-richclient.codebase.ebay.com/">XUI's eBay
library
can help simplify programming a little more.

Quite apart from merely being a wrapper for the eBay SDK, the
XUI framework provides a layer of caching, whereby long-lived data
can be maintained within the client application. The locality of
data that this provides means that many roundtrips to the server
can be avoided and that network latency should be less apparent to the
end user. Throw in some data binding features, and XUI ends up
taking care of much of the data handling involved in a data-rich
client application, leaving the developer free to concentrate on
innovative ways of using the eBay service.

XUI in a Nutshell

As a rich-client framework, XUI takes care of some of the common
tasks involved in constructing applications, and aims to promote
accepted design practices like the MVC architecture and a clean
separation of concerns. XUI applications run on a wide variety of
platforms, from handheld computers to high-end desktops running
Windows, Linux, and the Mac OS.

XUI makes use of XML for many aspects of the framework. But once
processed, the objects declared in XML are first-class Java objects
and at almost any stage these objects can be customized by normal
Java code. Consider the following page declaration in XUI:

[prettify]
<XPage layout="Border">
   <Components>
      <Label content="Hello world" constraint="center" align="center"/>
      <Button name="exitBtn" content="Goodbye" constraint="south"/>
   </Components>
   <Events>
      <Event target="exitBtn" type="ActionHandler" 
         method="${mypackage.MyHelper[test].doExit()}"/>
   </Events>
</XPage>
[/prettify]

This creates a simple page with the familiar "Hello world"
message and a button to close the application. The sample
application is shown in Figure 1:

Screenshot of the Hello World application
Figure 1. A simple Hello World application

The button is declared with the Button element and
an ActionHandler is then added to the button. The
method declaration is an expression that refers to a method named
doExit() in the test instance of the
mypackage.MyHelper class, the code for which is just
some plain Java:

[prettify]
package mypackage;

public class MyHelper
{
    public void doExit()
    {
        System.exit( 0 );
    }
}
[/prettify]

While this in itself is not tremendously interesting, the
separation of UI and application logic is the important concept
here. Unlike some XML-based formats, XUI can do a lot more than
create single-page applications. In large applications, this
separation of concerns can be very important. But why bother with
XML at all? Well, XML, in some cases, is more suited to declaration
of content: take, for example, the creation of coherent styling
within an application where a XUI stylesheet can be replaced so as
to rebrand an application without modifications to the application
code. In fact, given the loose coupling involved, it is possible to
completely modify the user interface and presentation of an
application independently of the data model and the business logic,
something that can be difficult to achieve without such a
framework.

In certain respects, XML can add flexibility to an application;
in other respects, the mix of XML and Java adds complexity and
therefore tool support is vital. XUI ships with a "http://www.netbeans.org/">NetBeans plugin that manages all
of the vital relationships between the various files and allows easy
visual editing of the applications. Therefore, using NetBeans means
that for the most part, the user is programming just another Java
framework.

The trivial example above shows the separation of the UI and the
business logic, but a more realistic separation of concerns also
involves separating the data management from business logic and
from the presentation issues associated with that user interface.
Data binding provides the key abstraction here, allowing data to be
referenced and manipulated independently of the UI. Not only does
this make the UI somewhat easier to manage, but it also means that
your business logic is less encumbered by data management
issues.

Building an eBay application is a different proposition than a
Hello World application, yet many of the same basic concepts come
to play. After all, in an ideal world, we just assemble a few
components and add our application-specific business logic to
create such an application. Two key components in XUI come into play
when considering an interface to eBay: managing all of the data and
wrapping the eBay API. After that is achieved, XUI can be used like
any other Swing framework, while hiding the low-level details of
the eBay services.

Integrating the Data Model

XUI includes a managed data model that can hold a hierarchy of
Java objects. The objects in the model can be from various sources,
such as static property files, databases, or even data retrieved by
remote calls. Nodes within the model's hierarchy can be addressed
with path expressions, and for convenience, the model will also
instantiate storage if you try to write to nodes that did not
previously exist. In the context of user interface development,
this approach is tremendously powerful, allowing you to bind UI
components to an abstract model with a minimum of configuration,
while also being able to reference that model from other pages or
contexts without introducing dependencies between components. The
data model is an essential part of an MVC architecture, and being
able to bind to the model so easily can help remove a lot of glue
logic from an application.

Let's see the model in action with a modified Hello World, this
time taking two pages. The first of them, shown in Figure 2, now
has an edit field where some user value can be entered:

[prettify]
<XPage layout="Border">
<Components>
  <Panel constraint="center" layout="Grid">
    <Label content="Enter your name:" align="right"/>
    <Edit name="userName" />
  </Panel>
  <Button name="nextBtn" content="Next" constraint="south"/>
</Components>
<Events>
  <Event target="nextBtn" type="ActionHandler"
     method="${mypackage.MyHelper[test].showPage()}"/>
</Events>
<Data>
  <Bind target="userName" source="myData/userName"
     output="myData/userName"/>
</Data>
</XPage>
[/prettify]

Screenshot of a simple form
Figure 2. Capture some input

The second page, shown in Figure 3, redisplays the
entered text.

[prettify]
<XPage layout="Border">
<Components>
  <Label content="Goodbye from" constraint="north" align="center"/>
  <Label name="userName" constraint="center" align="center"/>
  <Button name="nextBtn" content="Exit" constraint="south"/>
</Components>
<Events>
  <Event target="nextBtn" type="ActionHandler" 
      method="${mypackage.MyHelper[test].doExit()}"/>
</Events>
<Data>
  <Bind target="userName" source="myData/userName"/>
</Data>
</XPage>
[/prettify]

Redisplay of the input form's data
Figure 3. Redisplay of the input

The data binding will automatically update the label on the
second page with the data from the edit field on the first page
once the second page is displayed, with no extra coding required.
The myData/userName node is automatically created by
the data binding. The first page also references a new Java method,
but it too is very simple:

[prettify]
public void showPage()
{
   XProjectManager.getPageManager().showPage( "goodbye" );
}
[/prettify]

With this brief introduction to how XUI works, we can look at
integrating the eBay SDK.

Wrapping the SDK

The eBay Java SDK relies on SOAP, and each API defines many
constants; for example, the payment method for a transaction can be
set as follows:

[prettify]
ReviseItemRequestType request = 
    new ReviseItemRequestType(); ...
BuyerPaymentMethodCodeType[] methods = 
    new BuyerPaymentMethodCodeType[1];
methods[0] = 
    BuyerPaymentMethodCodeType.CCAccepted;
item.setPaymentMethods(methods); ...
[/prettify]

where the CCAccepted field is defined within the
eBay SDK as:

[prettify]
package com.ebay.soap.eBLBaseComponents;

public class BuyerPaymentMethodCodeType 
    implements java.io.Serializable {
...
public static final org.apache.axis.types.Token 
   _CCAccepted = 
   new org.apache.axis.types.Token("CCAccepted");
...
public static final BuyerPaymentMethodCodeType 
  CCAccepted = new BuyerPaymentMethodCodeType( 
      _CCAccepted);
...
}
[/prettify]

Unfortunately, the BuyerPaymentMethodCodeType class
does not provide any support for enumeration or listing of the
allowed types. To overcome the tedium of using such a limited
API, we have applied a little reflection to inspect the internals of
such classes and provide a more useful way of working with these
constants.

[prettify]
/**
  * Find all the instances of a class referenced 
  * within the class
  * @param clazz the class of interest
  * @param outputModel the model where value are 
  * stored
  */
public void getClassInstances( Class clazz, 
                             XModel outputModel ) 
{
   ArrayList listFields = new ArrayList();
   Field[] fields = clazz.getFields();
   for ( int i = 0 ; i < fields.length ; i++)
   {
      // Only choose the field instances we 
      // requested
      if (
fields[ i ].getType().getClass().equals( clazz ))
         listFields.add( fields[ i ].getName() );            
   }

   // Add the fields to the data model 
   int numFields = listFields.size();        
   for ( int i = 0; i < list.length ; i++ ) {
      XBaseModel listModel = new XBaseModel( 
         outputModel, 
         "row" + i , listFields.get( i ).toString());    
   } 
}
[/prettify]

The above method iterates a list of members from the specified
class and adds the member instances to an output data model, the
XModel parameter being the basic abstract node type
used in XUI's data model. Once the data has been added to the model,
it can be bound to user interface elements, as we have seen above in
the Hello World example.

Applying the same technique to other APIs goes some way towards
a better integration, but we still need some work to wrap the many
APIs in a suitable form.

Coordinating the Interaction

The parameter handling itself is a worthwhile improvement over
the raw API, but it gains added importance when multiple APIs are
required for a complete process, such as adding new items to an eBay
store. Of course, there is nothing to stop you from doing all of the
setup directly, but why bother doing the same stuff over and again
when you can let a data binding do the work? Instead, you can
concentrate on what is unique to the particular process or context.
Data binding alleviates some of the headaches of handling and
coordinating data for the APIs.

Data binding has the added advantage of implicitly caching data,
so the data needed to populate the user interface components is
available locally, thereby improving performance both of the UI and
of the network. In fact, rather than having to make a roundtrip to
the eBay server to get configuration information, you can usually
get it locally. If you don't think this is an issue, then consider
that eBay has gone as far as to add a flag to many APIs indicating
the amount of data to return. Something as simple as requesting the
available delivery methods may return large numbers of shipping
methods and all of the associated data.

Even the process of setting a connection can be a cumbersome
task, so the connection setup code is wrapped in a class to make
programming of other APIs easier.

[prettify]import com.ebay.sdk.*;
import com.ebay.soap.eBLBaseComponents.*;
import java.util.Calendar;
import net.xoetrope.xui.data.XModel;

public class EbayConnection 
{
    protected ApiContext apiContext;
   
    public EbayConnection( XModel connectionModel) 
    {        
        apiContext = new ApiContext();

        ApiCredential cred = 
             apiContext.getApiCredential();
        ac.setDeveloper( 
   connectionModel.getValueAsString( "devID" ) );
        ac.setApplication( 
   connectionModel.getValueAsString( "appID" ) );
        ac.setCertificate( 
  connectionModel.getValueAsString( "certID" ) );

        ApiAccount ac = cred.getApiAccount() ;      
        apiContext.setApiServerUrl( 
   connectionModel.getValueAsString( "url" ) );
      apiContext.getApiCredential().seteBayToken( 
  connectionModel.getValueAsString( "token" ) );

        eBayAccount ec = cred.geteBayAccount(); 
        ec.setUsername( 
  connectionModel.getValueAsString( "userID" ));

        ApiLogging apiLogging = new ApiLogging();
        apiContext.setApiLogging( apiLogging );    
        apiContext.setSite( 
  SiteCodeType.fromString( 
  connectionModel.getValueAsString( "site" ) ) );
        apiContext.setWSDLVersion( 
  connectionModel.getValueAsString( "wsdl" ) );

        //Set the EPS Server URL this server is 
        //used for uploading pictures to ebay
       apiContext.setEpsServerUrl( 
"http://msa-e1.sandbox.ebay.com/ws/eBayISAPI.dll?
EpsBasicApp&com.ebay.presentation.
ForceXmlDownload=true" );

        //For production use this EPS Server URL
        //context.EPSServerUrl = 
//"http://msa-e1.ebay.com/ws/eBayISAPI.dll?
//EpsBasicApp&com.ebay.presentation.
//ForceXmlDownload=true";
    }   
    
    public ApiContext getTheApiContext()
    {
        return apiContext;
    }
}
[/prettify]

The above wrapper does all of the normal stuff needed to set up the
connection, but instead of passing the connection attributes into
the wrapper as method parameters, the attributes are retrieved from
XUI's data model. Now, given that these parameters can be obtained
from the UI without writing any code, you should begin to get an
idea of how XUI's data binding can save some work. The XUI-eBay
library, an open source project on the eBay developer website, goes
on to wrap far more APIs in this manner. As a result, building an
application becomes more a question of hooking up the appropriate
data and services than one of how to use the SDK.

Building a Store

Now that some of the basic ingredients provided by XUI have been
introduced, what can be done to put some richness into the user
experience? To demonstrate such use of the XUI-eBay library, a
sample StoreManager application (shown in Figure 4) aimed at
someone who wants to set up and manage a store on eBay has been
built and released by "http://www.xoetrope.com">Xoetrope, as open source via the eBay
Community
Codebase
.

Screenshot of the my ebay page
Figure 4. The eBay StoreManager application

Using the browser interface, one needs multiple pages and many
mouse clicks to add an individual item. Using the StoreManager
application, the same task can be accomplished more quickly and
easily. Even within a single session, an improvement over what is
possible within the browser can be seen. However, as a XUI data
model can be saved to local storage, it is possible to save an
entire session and all of the associated configuration data. Saving
the data in this way means that a session can be restored and the
user can continue working where they left off, with no need to
configure the setup again. Of course, time-sensitive information
cannot be saved and reused in this way, but even so, enough
information can be saved and reused so that the end user will be
largely oblivious to the fact that a new session has been
started.

Perhaps more importantly, the use of Java affords many
integration possibilities. The StoreManager application can store
transaction histories, details of items for sale, and other
information in a local database. It would not take a huge leap of
imagination to then integrate with some other systems either
through Java or via the local database.

Does this Constitute Rich-Client?

Well, like beauty, it's really in the eye of the beholder. One of
the biggest drawbacks of desktop software is the perceived
installation issue. In most cases, "http://java.sun.com/products/javawebstart/">Java Web Start can
neatly address that issue, but in the case of the eBay SDK, this
assumption might need some qualification. While the XUI library can
be as little as 194KB, the eBay library relies upon the Axis
framework, which alone weighs in at a little over 9MB.
Optimization might help shrink this, but there is a significant
download involved. Therefore, the benefits need to outweigh the
inconvenience of the download, and that largely depends on the use
the application receives.

However, once over the hump of this download, the performance
improvement of a rich-client application should pay dividends for a
regular user. For businesses using eBay, the added incentive of
simplified integration may be reason in itself to use a Java
rich client.

Downsides

One downside to the story is that the eBay API is also
incomplete, lacking any bid functionality. EBay has created a
PlaceOffer API, but unfortunately they will not license it for use
in open source software. Therefore, we have been forced to use
screen-scraping technology from the "http://sourceforge.net/projects/jbidwatcher"">JBidWatcher
project. While perfectly functional, it will not stand up,
without programmer intervention, to major changes made by eBay.

Why not Ajax?

Since Ajax is
the framework du jour, it is worth making a brief
comparison. Ajax is certainly an improvement on vanilla HTML, but
it's still tied to the browser, and for the most part relies upon
JavaScript for its logic. While this is perfectly adequate in many
situations, it lacks the power, integration, and structural
capabilities of a Java-based approach. Nor is Ajax brilliant at
data management in the context of something like a data-intensive
eBay application. At the same time, being browser-based largely
ties an Ajax application to the browsers' concept of page
lifecycle. Finally, it is doubtful if Ajax would help much with the
SOAP integration.

Conclusion

This is a glimpse of what can be achieved with the XUI framework. The
XUI-eBay library, while workable, continues to grow and it is
planned to leverage the techniques described here to make the use
of eBay services even easier. Creation of the eBay StoreManager has
resulted in:

  • An application that is far quicker to use than the browser-based application.
  • Extended integration capabilities.
  • A reduced learning curve for extension.
  • Technology that can just as well be applied to other eBay
    applications and scenarios.

In conclusion, the techniques described here are not unique to
XUI and can be applied to a wide variety of applications and APIs.
By facilitating the integration of a web service API, you can tap into
the power of the desktop and give your end users a far more
satisfying software experience. Integrating with the desktop also
gives further possibilities for working offline, in an
occasionally connected way, or in concert with other systems.
Working within the confines of a web browser is not for everyone, or
for every situation, and this is often the case for the target
audience of the StoreManager: power users. It is right here that
rich-client applications can help.

Resources

width="1" height="1" border="0" alt=" " />
Luan O'Carroll is a software developer and lead developer on the Aria project.
Related Topics >> GUI   |