HomeDigital EditionSys-Con RadioSearch Web Services Cd
B2B Beginning WS Business Process Management Case Studies Content Management Distributing Computing e-Business Electronic Data Interchange Enterprise Industry Insight Integration Interviews Java & Web Services .NET Portal Product Reviews Scalability & Performance Security SOAP Source Code UDDI Wireless WS Standards WS Tips & Techniques WSDL WS Editorials XML

Source Code for this article

At the end of my last article (WSJ, Vol. 1, issue 4), I promised that in this article I'd show you an even better way to invoke .NET Web services from Pocket PCs. In addition, before this month's article is finished, you'll learn how to invoke .NET Web services from Java-powered devices.

The .NET Compact Framework
In the first half of this article, we'll focus on invoking NET Web services from Windows CE-powered devices (including Pocket PCs) via Microsoft's newest .NET technology: the Compact Framework.

What Is It?
The .NET Compact Framework is the portion of Microsoft's new NET technology initiative specifically targeted for execution on mobile devices. The best way to get a clear picture of this in your head is to contrast it to the rest of .NET. The rest of .NET allows you to create:

  • Windows applications: Full-featured GUI applications intended for use on desktop computers running the Windows OS.
  • Web applications: Apps that serve up various kinds of markup (HTML, etc.)
  • Web services: Apps that, you probably know, substitute XML for the various flavors of presentation markup used by Web applications.
The .NET Compact Framework adds the whole concept of Mobile Device applications to the mix. A Mobile Device application is like a Windows application, in that it is a full-featured GUI application. Unlike Windows applications, however, Mobile Device applications are intended to be used on devices instead of desktop computers. Unlike Web applications and Web services, these applications don't require the presence of an Internet connection in order to be used.

Develop for Devices As You Develop for Windows
The entire goal behind creating a subset of .NET that is intended for execution on devices rather than desktops is to allow the .NET developers to create applications for devices just as they would for desktops. This ability to create device-based applications directly from Visual Studio .NET gives the developer:

  • The eventual ability to use all of the .NET languages (VB, C#, etc.)
  • Access to a large subset of the .NET Framework classes
  • A drag-and-drop approach to creating application GUI's
  • Step-by-step debugging, just like on the desktop!
How Do You Get It?
To create a successful solution using the .NET Compact Framework, you need two things. The first of these is the software needed to turn Visual Studio .NET into a development environment suitable for creating device-based applications. The other is the set of runtime classes for installation onto your device(s) in order to allow them to "speak .NET" (as it were).

At the time of writing, both of these things are available from Microsoft as a product called the Smart Device Extensions for Visual Studio .NET. This product is currently bundled with the Release Candidate version of Visual Studio .NET itself.

There are two ways to get the Release Candidate:

  1. Be a Microsoft Developers Network subscriber
  2. Order it on DVD from http://msdn.microsoft.com/vstudio/nextgen/getrc.asp
Once you get it, simply run the Windows installer. My best experiences with this have been on completely clean machines. So, if you encounter any errors during setup, you might want to consider trying it on a completely "fresh" computer (if you have access to one).

What Do You Do With It?
In this section you'll find sample code for retrieving a stock quote using the .NET Compact Framework. Better yet, of course, you'll see how to use it to create a Visual Studio .NET project that you can compile and deploy to your Pocket PC or emulator.

Coding Your Project
In order to code your project, you must first create the graphical user interface (GUI), then populate it with the appropriate event-handling code.

Drawing the GUI
The Forms Designer portion of Visual Studio .NET isn't yet usable with the Smart Device Extensions, as of the Technology Preview release. In order to create a GUI for your application, then, we're going to have to exercise a bit of a workaround:

  1. Launch Microsoft Visual Studio .NET
  2. Create a new Windows application project named "GUI Builder"
  3. Size Form1 to be 240 x 320 (the size of a Pocket PC screen)
  4. Drag a textbox, label, and button onto Form1
  5. Press F7 to enter Code View
  6. Press Ctrl-A to select all of the code, then Ctrl-C to copy it to the clipboard
  7. Close this project
  8. Create a new Pocket PC Visual Basic Project called "NETcfQuote"
  9. Verify that the project opens in Code View
  10. Press Ctrl-A to select all of the code, then Ctrl-V to paste the code from step #6 above
  11. Comment out the line of code that begins "Me.AutoScaleBaseSize"
At this point, you've transferred the GUI created in the GUI Builder project into your NETcfQuote project. With any luck, this workaround will not be needed in later versions of the Smart Device Extensions.

Walking Through the Code
We're attempting to write a mobile client for a .NET Web service. It makes sense, then, that one of the first things we should do is add a reference to our .NET Web service to our project. One of the most wonderful parts of the Smart Device Extensions for Visual Studio .NET is how easy it makes to reference Web services for device-based code:

  1. Right-click "References" in the Solution Explorer
  2. Enter the address of the .NET Web service we created in last month's article (http:// localhost/Chapter10Server/Service1.asmx)
  3. Once the page has loaded, click "Add Reference"
You're now ready to access the get Quote method on this Web service from a remote device just as easily as you would normally reference methods on a local component! Could it get any easier? Chalk one up to Microsoft's side in the battle for simplicity.

At this point, you're ready to add the code from Listing 1 to your application. Simply copy it, exactly as it appears, immediately below the line that reads:

#End Region
As you might have guessed, this code is intended to run whenever the single button on the application's GUI is clicked. First, it declares a reference to the remote Web service. Then it calls the getQuote method on this reference, passing in the contents of the textbox as its first parameter, and an empty variable - price - as its second. If the method returns successfully, the label is populated with the contents of price, otherwise an error message is placed in it.

Compiling and Deploying
In order to compile and test your application, first select "Pocket PC emulator" from the dropdown that says "<select device>." Then, press F5. If there are errors, Visual Studio .NET will tell you that there were problems with the build and prompt you to continue or abort. If compilation succeeds without a hitch, the new Pocket PC emulator will launch and your application will appear.

At this point, you should enter the symbol of a NASDAQ stock in which you are interested into the textbox on the application's GUI. Then, click the button. Shortly, the most recent price of that stock should appear in the label on the display.

In order to try your application on a real Pocket PC, you need only:

  • Place your Pocket PC in its cradle (attached to your computer via a cable)
  • Choose "Pocket PC Device" from the drop-down instead of "Pocket PC Emulator"
Java 2, Micro Edition (J2ME)
We'll conclude our look at mobile .NET Web services by demonstrating how they may be invoked in a truly cross-platform manner by using the Java platform.

What Is It?
Java is Sun Microsystems' platform for creating software capable of running on a wide variety of hardware and operating system combinations. Software written completely in Java can often run on systems as different as UNIX and Windows without even requiring recompilation.

With the release of Java 2, Sun divided their platform into three distinct flavors:

  • Enterprise Edition (J2EE)
  • Standard Edition (J2SE)
  • Micro Edition (J2ME)
J2SE might be referred to as "regular Java" - it's intended for use with standard, desktop computer applications. J2EE, on the other hand, is intended for the creation of server-based software, such as Web applications and distributed, component-based applications.

J2ME differs from both of the above by focusing on Java code intended for execution directly on mobile devices. In this sense, it's Java's direct analog for Microsoft's .NET Compact Frameworks.

How Do You Get It?
The great thing about J2ME is that almost all of the software needed to create applications for it is freely available for download off the Internet. On the other hand, the software needed in order to run these applications on the devices must typically be hard-wired into devices by the manufacturer (as opposed to being installed after-the-fact by end-users).

Acquiring the Bits
The first thing that you must download is the Java 2 Software Development Kit (SDK). This is the bit that takes standard text files full of Java sourcecode and converts them into binary files full of Java bytecode. You can get it from http://java.sun.com/j2se/1.3/Text.

The second thing that you should try to lay your hands on is the J2ME Wireless Toolkit. Although not absolutely essential for creating J2ME applications, it contains all of the extra libraries that you would need, plus a great assortment of emulators and development tools. Since it's also free, why not download it? Go to http://java.sun.com/products/j2mewtoolkit/Text.

Installation
Both of the above products use standard Windows setup engines to install and configure themselves on your machine. Just make sure that you install the JDK first, and then the Wireless Toolkit. (This is so that the Wireless Toolkit can configure itself to know exactly where your JDK is - thus making automated compilation and testing that much easier!)

What Do You Do With It?
Well, this is the point that we've been building to ever since the start of last month's article: actually invoking a .NET Web service from a mobile device that has nothing whatsoever to do with Microsoft.

The key to our approach, as you'll see, is a little bit of open-source code known as kSOAP. In this section, you'll see how to use kSOAP to build and deploy a J2ME application that can invoke .NET Web services from virtually any J2ME-powered device.

Discussing the Code
Let's begin by looking at Listing 2. It begins, like most Java code, with a series of import statements. The first statement imports the standard Java IO implementation for MIDP. The next few lines import various packages specific to MIDP Java. The final four import statements include support for kSOAP into our MIDlet.

kSOAP can be downloaded free from http://ksoap.enhydra.org. Also included in the package is some basic Javadoc documentation and sample code. In my book, Mobile .NET, I go into greater detail than present space allows about the workings of this fine technology. However, when you've finished entering and running this code listing, you should have a fairly strong basic grasp of how the technology is used.

Inside the FergieStock class, we first find several member variable declarations. The first of these sets the namespace, which must match the namespace we chose for our .NET Web service. After this, a number of GUI elements are declared, and added to the screen by the default constructor, as you can see.

The pauseApp() and destroyApp() methods are present only because the MIDlet specification requires them. The startApp() method is also required and, in this case, serves the purpose of displaying our initial form on the screen.

All of the real magic in our MIDlet happens when users press the single command button on the GUI to transmit their stock symbol up to our Web service. kSOAP's SoapObject component is used to serve as a proxy for the remote .NET Web service. Its ClassMap object is used to encapsulate the parameter that will be passed across the wire to the remote service. Both of these objects are passed into kSOAP's SoapEnv elope component, which will take care of serializing all of the kSOAP objects into appropriate SOAP XML for transmission to our NET Web service.

MIDP's built-in HTTP connectivity is used to facilitate communications with the remote server. First, the XML for our SOAP request is transmitted, then the response is received back via the same HttpConnection method.

kSOAP's SoapEnvelope object provides the technologies needed in order to interpret the XML that's been returned to our client by the server. Once the price of the stock has been parsed out, it's placed into the label on our display. On the other hand, if an error has been raised, the word "Error" is placed inside the label.

Compiling and Testing
In order to try out the code shown above, follow these steps:

  1. Save the code from Listing 2 as Fergie Stock.java
  2. Save the code from Listing 3 as Fergie Stock.jad
  3. Start the kToolBar application from the Windows Start menu (in the J2ME Wireless Toolkit program group)
  4. Select "Open Project," then navigate to "FergieStock.jad" and choose "Open Project" again
  5. Click Build and verify that there are no errors
  6. Click Run
At this point, one of the J2ME Wireless Toolkit's emulators should open, allowing you to test your new J2ME stock quote client. Once you've entered a symbol and gotten back its price, congratulate your-self: you've just talked successfully to Microsoft .NET from Java!

Final Words
There you have it - how to invoke .NET Web services from virtually any kind of mobile device. If you're still hungry for more information about .NET technologies targeted at mobile computing, be sure to check out my MSN community at www.MobileDotNet.com.

Author Bio
Derek Ferguson is chief technology evangelist for Expand Beyond Corp. He is a world-renowned author, speaker, and developer who has been recognized throughout the IT industry for his work. derek@XB.com

Mobile .Net Web Services Part II, by Derek Ferguson
WSJ Vol 02 Issue 02 - pg.27

	


Listing 1
Public Class Form1 Inherits System.Windows.Forms.Form Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles Button1.Click Dim price As String Dim ws As localhost.Service1 = New localhost.Service1() Label1.Text = "" If ws.getQuote(TextBox1.Text, price) Then Label1.Text = price Else Label1.Text = "No such stock!" End If End Sub End Class

Listing 2

import java.io.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.io.*; import org.ksoap.*; import org.kxml.*; import org.kxml.io.*; import org.kxml.parser.*; public class FergieStock extends MIDlet implements CommandListener { static final String serviceNamespace = "http://pocketdba.com/webservices/"; Form mainForm = new Form ("Fergie Stock"); TextField fromField = new TextField ("Symbol :", "ALGX", 4, TextField.ANY); StringItem resultItem = new StringItem ("", ""); Command getCommand = new Command ("Get", Command.SCREEN, 1); public FergieStock () { mainForm.append (fromField); mainForm.append (resultItem); mainForm.addCommand (getCommand); mainForm.setCommandListener (this); } public void startApp () { Display.getDisplay (this).setCurrent (mainForm); } public void pauseApp () { } public void destroyApp (boolean unconditional) { } public void commandAction (Command c, Displayable d) { try { String from = fromField.getString (); ByteArrayOutputStream bos = new ByteArrayOutputStream (); SoapObject request = new SoapObject (serviceNamespace, "getQuote"); request.addProperty ("symbol", fromField.getString ()); ClassMap classMap = new ClassMap(); classMap.prefixMap = new PrefixMap (classMap.prefixMap, "tns", "http://pocketdba.com/webservices/"); SoapEnvelope envelope = new SoapEnvelope (classMap); envelope.setBody (request); XmlWriter xw = new XmlWriter (new OutputStreamWriter (bos)); envelope.write (xw); xw.flush (); byte [] data = bos.toByteArray(); System.out.println (new String (data)); HttpConnection connection = (HttpConnection) Connector.open ("http://localhost/Chapter10Server/Service1.asmx",Connector.READ_WRITE); connection.setRequestMethod (HttpConnection.POST); connection.setRequestProperty ("Content-Type", "text/xml"); connection.setRequestProperty ("Connection", "close"); connection.setRequestProperty ("Content-Length", ""+data.length); connection.setRequestProperty("SOAPAction", "\"http://pocketdba.com/webservices/getQuote\""); OutputStream os = connection.openOutputStream (); os.write (data); os.flush (); InputStream is=((StreamConnection) connection).openInputStream (); int buffSize=200; byte[] buff = new byte[buffSize]; ByteArrayOutputStream bytebuff=new ByteArrayOutputStream(buffSize); int eof=0; while(eof!=-1) { eof=is.read(buff); if (eof!=-1) { bytebuff.write(buff,0,eof); } } is.close(); String response = new String(bytebuff.toByteArray()); System.out.println (response); Reader reader = new InputStreamReader(new ByteArrayInputStream(bytebuff.toByteArray())); XmlParser parser = new XmlParser (reader); SoapEnvelope resultEnvelope = new SoapEnvelope (); resultEnvelope.parse (parser); resultItem.setLabel ("amount :"); String result = (String)resultEnvelope.getResult(); result = result.substring(0,result.indexOf(".")+3); resultItem.setText (" "+result); os.close (); reader.close (); connection.close (); } catch (Exception e) { resultItem.setLabel ("Error:"); resultItem.setText (e.toString ()); } } private static byte[] extractXml(byte[] extractFrom){ byte[] result; int off=0; boolean nonStop=true; for(int i=0;nonStop;i++){ if (extra ctFrom[i]==60) { off=i; nonStop=false; } } result=new byte[extractFrom.length -off]; for(int i=off;i<:extractFrom.length;i++){ result[i-off]=extractFrom[i]; } return result; } }

Listing 3

MIDlet-1: FergieStock, , FergieStock MIDlet-Jar-Size: 40598 MIDlet-Jar-URL: FergieStock.jar MIDlet-Name: FergieStock MIDlet-Vendor: Sun Microsystems MIDlet-Version: 1.0

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.

  E-mail: info@sys-con.com

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.