MOBILE

BlackBerry Java Application Development : Networking - calling a web service

6/11/2012 11:37:00 AM
  1. The first step is to get the CopyCat service working. This service is written in .NET and is built with Microsoft Visual Studio 2008. Not everyone will have access to this tool so feel free to create a web service using your favorite tool. The thing we are interested in at this point is a web method named CopyMe that accepts a string parameter named Value and returns a string. In fact, the implementation of CopyMe is exceedingly simple as it just returns the same string that was passed into it.

  2. As you actually need to send data to a server now, you need to start by adding an edit field to the application that prompts for the data to send. Add an EditField as a data member to the application.

    protected EditField _CopyString = new EditField();
    
  3. Next, add the field to the screen by adding this code into the constructor.

    _CopyString.setLabel("Copy Source: ");
    _CopyString.setMaxSize(50);
    _add(CopyString);
    
  4. We'll come back to the Screen class later. At this point, we need to modify the ServiceRequestThread class to add a data member and a method to set it.

    protected URLEncodedPostData _PostData = null;
    public void setPOSTData(URLEncodedPostData data)
    {
    _PostData = data;
    }
    
  5. Once you have the _PostData object, you need to use it. In the run method, replace the setRequestMethod call with this if statement.

    if (_PostData != null)
    {
    conn.setRequestMethod(HttpConnection.POST);
    conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
    conn.setRequestProperty("Content-Length", Integer.toString(_PostData.size()));
    OutputStream strmOut = conn.openOutputStream();
    strmOut.write(_PostData.getBytes());
    strmOut.close();
    }
    else
    {
    conn.setRequestMethod(HttpConnection.GET);
    }
    
    
    					  
  6. Now that the ServiceRequestThread class is changed you can come back to HttpBasicsMainScreen and add a new menu item that you will use to trigger a request. You will likely need to change the address in the connection string or, at the very least, the port number of the service. Make sure that the URL is correct for referencing the web service and that the service is currently running.

    protected MenuItem _PostDataAction = new MenuItem("PostData" , 100000, 10)
    {
    public void run()
    {
    URLEncodedPostData oPostData = new URLEncodedPostData( URLEncodedPostData.DEFAULT_CHARSET, false);
    oPostData.append("Value",_CopyString.getText());
    String URL = "http://localhost:2997/CopycatWebServiceCSharp/ Service.asmx/CopyMe;deviceside=true";
    ServiceRequestThread svc = new ServiceRequestThread(URL, (HTTPBasicsMainScreen)
    UiApplication.getUiApplication().getActiveScreen());
    svc.setPOSTData(oPostData);
    svc.start();
    }
    };
    
    
    					  
  7. Lastly, you need to add the menu into the application by adding the next line to the constructor.

    addMenuItem(_PostDataAction);
    

What just happened?

Step 1 of this section is simply about setting up a web service that you can test with. While I do provide some code, I also know that not everyone will be able to use the tool or be able to set up the service. This is why there are specific directions given in case you need to create your own. We could have tried to rely on one of the public web services such as at www.webservicex.net, but the services can change, break, or be removed all together and the example wouldn't be valid any more. Therefore, it's better to utilize a service that you control. If you choose to use the provided code, great! If you prefer to write your own, that's great too!

The other steps are mostly housekeeping steps until you get to steps 4 and 5, which modify the ServiceRequestThread class. As we pointed out earlier, the URLEncodedPostData class is used to collect the parameters that are passed with the HTTP POST request. This thread is designed to be generic, therefore it can't populate the parameters. Instead, the setPOSTData method is there to allow the class that starts the thread to supply a pre-populated URLEncodedPostData class that will be used later when the request is actually processed.

protected URLEncodedPostData _PostData = null;
public void setPOSTData(URLEncodedPostData data)
{
_PostData = data;
}

The run method is also changed slightly to check and see if there are any POST parameters supplied. If so, then the request type is set to use a POST method and the parameters are added to the output stream. Also, there are a couple of properties that are set to support the additional POST data. The Content-type property is used to let the receiving computer know more about the data that is included within the request. In this case, you are specifying that the data has been URL encoded by using the application/x-www-form-urlencoded value. This value isn't an arbitrary value, but a specific value that the server already knows about. In addition to setting the content type, you also set the size of the data being sent with the request.

Once the supporting attributes are set you get a stream that will be used to add the parameter data in with the request by using the openOutputStream method. The actual data is written by using the stream's write method before being closed.

All of this work is necessary because of the extra data that needs to go with an HTTP POST command. If the _PostData object isn't set, then we skip all of this work and issue an HTTP GET command instead.

if (_PostData != null)
{
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", Integer.toString(_PostData.size()));
OutputStream strmOut = conn.openOutputStream();
strmOut.write(_PostData.getBytes());
strmOut.close();
}
else
{
conn.setRequestMethod(HttpConnection.GET);
}


					  

Once the thread is taken care of, you go back to the screen and add the menu that will be used to issue the request. The request is largely the same as the request that is used fetch a web page, but this adds the step of creating and populating the URLEncodedPostData object. When populating this object keep in mind that the parameters that you add must be named the same as those in the web service definition. In this case, the web service declares the input parameter to be named Value so you must use that same name when adding the parameter to the PostData.

URLEncodedPostData oPostData = new
URLEncodedPostData(URLEncodedPostData.DEFAULT_CHARSET, false);
oPostData.append("Value",_CopyString.getText());

The final step is to give the completed URLEncodedPostData object to the thread that will be handling the request by using the setPostData method that we created earlier.

Once you run the application you can see that the CopyMe service is doing exactly what it is supposed to do, which is to simply return the input parameter as the output of the web service. But, if that's the case, why is there all of this extra stuff around it?

Web services return data wrapped in XML using a protocol called SOAP that can get very large and complicated when dealing with custom structures or complex objects. This is about as simple as we can get. You can see that the real data we are after is buried in the middle of a lot of XML data. Sooner or later, you will need to parse that XML in order to get to the meaningful data that you care about.

Pop quiz

  1. What must be done to any data sent with an HTTP request?

    a. It must be converted into a byte array

    b. It must be a string type

    c. It must be URL encoded

  2. What properties must be set passing additional data with an HTTP request?

    a. The content length property

    b. The content type property

    c. Both content length and content type

  3. When adding parameter data, what name should be used?

    a. The name that is defined in the web service definition

    b. The name is irrelevant; any name will work.

    c. The name should be in the form of param with a sequential number afterward

There are a few different approaches to parsing the data as well. You can try to do the string matching and manipulations yourself. If the data you are working with is both small and static, then this might be the easiest approach. However, if the data is at all complicated, then this approach gets real messy real quick. It's better to rely on a tool that has already been tested.

The BlackBerry SDK provides an implementation of a Simple API for XML (SAX) parser that we will use to retrieve data from the returned pages. As the name implies, this tool is simple to use and simple in capabilities, which can mean that if you want to do something complex, it may no longer be simple! In technical speak, a SAX parser is a non-validating parser that uses a callback mechanism to notify the application each time it encounters a new attribute or element.

When we say it is a non-validating parser it means that the parser does not have any knowledge about how the XML should be formatted and it doesn't try to validate whether the XML is formatted properly or not. As long as the XML structure is technically valid the parser will parse it without issue. If certain nodes are supposed to be nested, if a node is supposed to be of a particular type, or only supposed to occur once the SAX parser will not enforce any of these rules.

Generally, you don't need to worry much about validating the structure of the XML when consuming the string from a service; you can usually trust that the service will provide well structured output. Because of this, a SAX parser usually works out just fine.

In order to utilize the SAX parser you must create a specific Handler class for each kind of XML response that you want to parse. This class is derived from a class called DefaultHandler and is how the parser makes callbacks to notify the application of various events that are encountered when parsing the XML. For example, a method called StartElement is there and can be overridden to do some processing each time a new element tag is encountered.

So with that bit of overview in place, let's expend the HttpBasics class to process the results of the CopyMe web method call.

Other  
  •  Ipad : Presentations with Keynote - Adding Transitions (part 2) - Object Transitions
  •  Ipad : Presentations with Keynote - Adding Transitions (part 1) - Magic Move
  •  What the world is waiting for ?
  •  Galaxy Tab 10.1 - Touchy-feely
  •  Le Pan II - Entry-level Honeycomb tablet
  •  Mobile - The Good, The Budget And The Surprising
  •  The Blackberry OS 2.0 - So, The Playbook Is Whole
  •  Mobile Phone Update Fever (Part 4)
  •  Mobile Phone Update Fever (Part 3)
  •  Mobile Phone Update Fever (Part 2) - Social integration, Multitasking & Tablets
  •  Mobile Phone Update Fever (Part 1) - Apple iOS 5, Google Android 4.0 & Microsoft Windows Phone 7.5
  •  Mobile - Four Cores Good, Two Cores Bad
  •  Mac - That Syncing Feeling
  •  Toshiba Regza Tablet AT200 - The Thinnest
  •  ASUS Transformer Pad - Transforming Value to Quality
  •  Sony Xperia S - A Fresh Xperience
  •  Targus Travel Chill Mat - Chillin' On-The-Go
  •  Kingston Wi-Drive - Rekindling The Wi-Drive
  •  Bootleg Unzipped (Part 2) - An industry of fakes
  •  Bootleg Unzipped (Part 1)
  •  
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Windows Server 2003 : Terminal Services Administration (part 1) - Terminal Services Manager
    Is It Time To Quarantine Infected Pcs?
    MEElectronics Air-Fi AF32
    Getting the Most Out of the Microsoft Outlook Client : Deploying Outlook 2007
    AMD Radeon HD 7870
    Programming .NET Security : Extending the .NET Framework (part 1) - Defining the Key Exchange Formatter
    Display Warriors (part 4) - AOC 2352Phz & Philips 226V3LSB28
    Windows Azure : Using the Blob Storage API
    Primer – Choosing And Using Peripheral Buses (Part 1)
    Programming COM+ Security (part 2) - Creating the Serviced Component, Specifying the COM+ Application Type
    iPhone Application Development : Exploring Interface Builder - Connecting to Code
    Intel : We For One Welcome Our Apple Overlords
    Visual Studio Team System 2008 : Creating new report (part 1) - Report server project
    Brother MFC-J4510DW - An Innovative All-In-One A3 Printer
    The State Of Mobile... Creative Media In 2012 (Part 2)
    Microsoft Dynamics AX 2009 : Building Lookups - Picking a color
    Servlet Development and Deployment : Writing our first servlet & Compiling the servlet
    Working with the Windows Phone 7 Application Life Cycle (part 1) - Observing Application Life Cycle Events
    MiniStack MAX - Adds Versatility To External Drive Options
    ASP.NET 4 in VB 2010 : Reading and Writing with Streams (part 2) - Shortcuts for Reading and Writing Files, A Simple Guest Book