Low Bandwidth SOAP
Introduction
With the mobile phone industry reporting better than expected sales, and news that, by the end of this year, smart phones are expected to outsell hand-held computers, it should come as no surprise that wireless application development is on the rise. Sun recently announced that by the end of 2004 there may well be more than 200,000,000 Java-enabled mobile handsets. Yet, with all the attention being paid to these microdevices (i.e., low resource mobile devices), it's surprising to learn that a developer wishing to build a wireless application using XML, SOAP, and web services is left behind.
Why is this? First, a microdevice by definition has an extremely limited amount of memory. Second, traditional packages such as Xerces (for XML) and Axis (for SOAP) are far too large and resource-intensive to work on microdevices. A examination of Xerces.jar file should adeptly demonstrate this fact; it's over one megabyte in size. Microdevices are simply too small to be expected to work with packages originally designed for desktop clients and servers.
Fortunately this issue is well recognized by the larger wireless community. Sun, in particular, is currently in the stage of finalizing JSR172, a specification that addresses the use of XML, SOAP, and web services on microdevices. The downside is that, given past experience, it's not unreasonable to expect at least ten to twelve months to pass before finalization and widespread implementation. But that shouldn't deter anyone wishing to create a wireless application today, for doing so is quite possible using a powerful, free, and open source package readily available from Enhydra.org.
This article explains the basics of building web service servers and clients using Enhydra's KSOAP implementation.
Introducing KSOAP
A key ingredient for any web services application is SOAP. The problem with developing a wireless SOAP/XML application -- and the reason for the above-mentioned JSR172 -- revolves around the following issues. First, the common XML and SOAP packages currently available are quite large and contain hundreds of classes. Second, these packages depend on features of the Java runtime that simply don't exist on a microdevice. I'm thinking specifically about the Connected Limited Device Configuration (CLDC) specification which did away with nearly the entire core set of Java classes normally present in the J2EE and J2SE distributions: AWT, Swing, Beans, Reflection, and most java.util and java.io classes have simply disappeared. The purpose of this "bare bones" Java runtime is to accommodate the limited footprint of the KVM -- a low-memory virtual machine running on a microdevice.
This is where Enhydra.org comes to the rescue. KSOAP and KXML are two packages available from the web site designed to enable SOAP and XML applications to run within a KVM. They are thin, easy to use, and well documented. Combined into a single jar file, they take up less than 42K.
KSOAP begins with a class called SoapObject. This is a
highly generic class which allows a wireless application to build SOAP
calls. A quick look at the
documentation reveals that the methods getProperty() and
setProperty() are used to accomplish this functionality.
You might immediately notice the conflict with traditional Java
programming inherent in this design model; it detracts from the use of
static typing. Ideally, application development goes more smoothly
if the data structures are defined statically and are able to be
marshaled/unmarshaled across the network, just as if they were running
within the same runtime environment. In other words, imagine having to
rely solely on the Hashtable for all your data structures,
assigning each property a key for access and retrieval and then having to
remember each property's unique key and given type.
By having your data model defined statically, a developer can forget all that and rely on the compiler, not the runtime, to catch the type-mismatch errors. Further, casting is kept to a minimum, and it is easier to take advantage of tool support that depends on static typing to help the programmer.
Fortunately, the developers behind KSOAP recognized the importance of
statically defined data structures; they've provided the necessary
interface. By implementing KvmSerializable, a developer can
continue to use his or her own data objects. Using this interface becomes
even more important within large-scale enterprise environments where the
data models might be numerous and previously defined.
An Example Application
In an effort to explain how to take advantage of KSOAP, I have put together a sample application. For the purpose of clarity I have made this application simple and straightforward. It is a wireless-app that enables a fictitious manager to receive, by way of a mobile phone, system alerts that are periodically generated by some anonymous back-end system during the normal course of the day. Upon receiving such an alert he or she might decide to call an administrator, or notify their department, or perhaps even dial-in from home and fix the problem.
This sample application involves just four classes.
-
SystemAlert.java
The data model -
AlertService.java
The Service module generating SystemAlerts. -
AlertServlet.java
The HTTP interface that sends and receives SOAP Messages. -
AlertClient.java
The MIDLet application residing on the Mobile Phone
The components work together as illustrated below.
There are three basic tasks involved in working with KSOAP.
- Implement the serialization logic of your data objects via the
KvmSerializableinterface. - Register your data objects with the KSOAP
ClassMap. (This needs to done on both the client and server side.) - Integrate your services with the KSoapServlet. (Optionally, you can create your own servlet to suit your given needs -- all of the KSOAP source code is freely available.)
Let's begin by taking a look at the SystemAlert class
before it has been modified to work with KSOAP.
SystemAlert.java (before adding KSOAP)
As you can see the class is intended to be serialized; however, since
the CLDC specification
has done away with DataObjectStreams and the
Introspection classes, the traditional mechanism for passing
objects over the network can't be utilized, and a new process of
(de)serialization must be used. KvmSerializable provides the
mechanisms to accomplish this task. Examine the same class definition
after the changes have been made.
SystemAlert.java (after adding KSOAP)
As you can see, the methods getProperty() and
setProperty() handle all the logic necessary for
serialization and deserialization. These methods are called
behind-the-scenes by the SOAP engine rather than by the application
itself, and they provide all the logic necessary to map the binary data to
its string representation. The simple types such as String,
long, and int are taken care of for you by the
KSOAP framework. Complex types are handled by implementing the mapping
logic in a similar fashion.
While implementing mapping logic for each and every object can quickly become a tedious exercise, I have created a helpful Ant task to speed the process along. Using this Ant task, a developer need not bother with any of the mapping logic at all; it is created and added automatically. This will save time for the large-scale projects with scores of data objects needing to be serialized.
Servlet
The next piece to examine is the servlet that will function as the
interface between your service and outside world (i.e. the mobile phone or
some other microdevice). This can be best accomplished by extending
KSoapServlet, which is available in the KSOAP package, and
overriding its init() method as shown below.
public void init(ServletConfig cfg) throws ServletException {
super.init(cfg);
ClassMap classMap = getClassMap ();
classMap.addMapping("localNameSpace", "SystemAlert",
new SystemAlert().getClass());
AlertService alertService = new AlertService();
instanceMap = new HashMap();
instanceMap.put("AlertService", alertService);
}
By registering the SystemAlert class with the
ClassMap, the SOAP engine knows to expect a class of that
given type, what it should be named and what namespace to assign it
(though the namespace assignment is curiously non-standard.) Have a quick
look at the associated SOAP message below.
<SOAP-ENV:Envelope
xmlns:n0="examples.soapservice"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<n0:getNextSystemAlertResponse id="o0" SOAP-ENC:root="1">
<return xsi:type="n0:SystemAlert">
<timeStamp xsi:type="xsd:long">1057726422543</timeStamp>
<message xsi:type="xsd:string">Sample Error Message</message>
</return>
</n0:getNextSystemAlertResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Further down the init() method, a HashMap is
created to store the given instance of our AlertService. When
the client makes a request it will send along with it an "AlertService"
parameter so that the servlet executes the desired service. The
getInstance() methods show how this is key is utilized and
how the service object is retrieved. As a conscientious developer you may
wish to enforce stronger security and access control. This is essentially
the location to achieve that; all your database and encryption logic can
branch off from here.
protected Object getInstance (HttpServletRequest req) {
Object result = instanceMap.get(req.getParameter("service"));
return result;
}
Client
This brings us to the final piece, the client. In order to execute on a
mobile phone, a developer might choose to use the MIDlet framework, as I
have. Interacting with the AlertServlet amounts to just a few
lines of code. Below is a snippet of code from AlerterClient.java
(available from the example
code.) For the purposes of this example assume the service resides on
a host running at http://somehost.com:8181/services.
public SystemAlert makeRequestToServer() throws Exception {
ClassMap classMap = new ClassMap();
classMap.addMapping("localNameSpace", "SystemAlert",
new SystemAlert().getClass() );
SoapObject rpc = new SoapObject("urn:xmethods-AlertService",
"getNextSystemAlert");
HttpTransport tx = new
HttpTransport('HTTP:// somehost.com:8181/services' +
"?service=AlertService",
"urn:xmethods-AlertService");
tx.setClassMap( classMap );
SystemAlert alert = (SystemAlert) tx.call( rpc );
return alert;
}
Once again, we register the SystemAlert class with the
ClassMap. Secondly, we create a SoapObject for
the sole purpose of making the request -- your application might wish to
send some custom KvmSerializable object instead. We then
create an HttpTransport object passing it the destination
address for our Service; notice that the "service"
parameter is also appended. Lastly, we initiate the transaction via method
tx.call(). If all is well a SystemAlert object
is returned; and if something should go wrong, the SOAP message will
contain a SOAPFault element instead of its normal payload.
Subsequently, an exception will be thrown from within the
call() method.
As you can see, developing an application like this is not so difficult. By leveraging KSOAP for your wireless application, you can help make it a more powerful and reliable one. Since much of the infrastructure is provided, you as the developer can spend more time focusing on the important aspects of development such as the business logic.
- plz help me to how to solve this bug
2007-01-07 07:38:12 KumarDomain - plz help me to how to solve this bug
2007-01-07 10:15:03 jeffmc - plz help me to how to solve this bug
2007-01-07 10:14:55 jeffmc - plz solve this problem
2007-01-04 08:09:01 KumarDomain - Runable with PersonalJava?
2005-04-26 04:29:11 DarkGuardian - ksoap
2004-02-01 10:10:06 rika f