Sei sulla pagina 1di 24

RESTful Web Services: A Quick-Start How-to Guide - Part

1
Among PowerBuilder 12.5 .NET's new features comes the ability to use WCF to call
RESTful web services. This article, the first in a two-part series, provides a
PowerBuilder 12.5 .NET developer with the foundational knowledge and skills to
rapidly get up and running building PowerBuilder RESTful Web Service clients. Along
the way I'll share with you a few tips and workarounds.
Introduction
PowerBuilder 12.0 .NET provided the ability to call SOAP-based web services using
Microsoft's .NET 3.5 WCF API. I encourage those of you not familiar with WCF and
SOAP to view my PowerBuilder WCF primer and StockTrader reference application
overview hosted on Sybase.com. You can get to all my free tutorials from
http://yakovwerde.ulitzer.com/node/1551687. New with version 12.5, along with an
upgrade to WCF 4.0, is the ability to call RESTful web services, an increasingly popular
mechanism for accessing remote resources in SOA applications. In this article I'll help
you gain some foundational understanding and definitions, then familiarize you with
the mechanics of coding a client to retrieve data from a response-oriented RESTful
service. In Part 2, I'll explore the three types of request-oriented operations.
What Are RESTful Web Services?
In a nutshell, RESTful services are "web natural" and lightweight. They leverage HTPP's
native GET, PUT, POST & DELETE methods to invoke service methods at well-known
URIs. Much has already been written and is freely available on the Internet about the
nature and implementation of RESTful web services and how they compare to
SOAP/WSDL services. Instead of rehashing what has already been thoroughly
described, Listing 1 provides a couple of web references from which you can glean an
understanding of the technology. If you need more information, a quick search on your
favorite search engine will turn up more references. If you're really serious and would
like a full-sized book, you can purchase Jon Flanders' RESTful .NET published by
O'Reilly.
1. A Guide to Designing and Building RESTful Web Services with WCF 3.5
2. Learn REST: A Tutorial
Listing 1: Useful Web References
One pragmatic difference between WSDL / SOAP services and RESTful services from
the client viewpoint is the amount of onus placed on the client developer. SOAP
services are fully described in a WSDL document, including their service methods,
input parameters and return types. A PowerBuilder developer has no responsibility
other than to input the WSDL location into the wizard or project painter and click the
generate proxy button. The project painter does the rest. SOAP calls are also method
based. At runtime the developer instantiates a single proxy and invokes specific
methods as necessary. With RESTful services, however, the developer has more
responsibility in defining the interface. He has to get hold of either a schema (XSD)

document or .NET assembly that fully describes the types in the returned XML or JSON,
OR a sample result set with sufficiently varied data to help the proxy generator
decipher the return structure. He also has to know enough about the structure of the
return type so as to be able to review the wizard's work and make corrections as
necessary (more about this later). Calls to a RESTful service are not method based simply navigating to the service URI with correct parameters appended gets you a
response. This means there is one proxy per service (method), hence more code
objects to maintain.
What Is JSON?
Depending on how they are implemented, RESTful web services can return data in one
of several standard formats. Among the possible formats are XML, CSV, RSS, ATOM
and JSON. PowerBuilder 12.5 allows you to choose either XML or JSON for your
transfer format. What is JSON? The upshot is that JSON is a JavaScript / AJAX browser
friendly data transfer format. Because AJAX is a pervasive web technology, many
services are only available in JSON flavor. Listing 2 provides some useful references
from which you can get more background on JSON.
JSON presents no problem for PowerBuilder! At design time you can provide a sample
data set in JSON or XML format to the project painter. The project painter will parse
the sample data, JSON data and generate the .NET reference objects you'll need to
work with your data. At runtime JSON-based data transfer is parsed and converted to
.NET value objects. The good news is that as a PB programmer you will not have to
write JSON; however, you will have to read it to understand how a result set is
constructed.
1. Quick overview of this JSON
2. JSON, a formal definition
Listing 2: Useful JSON References
Viewing JSON
IE 9 does not have a native facility for viewing JSON data. You'll need to use a tool to
view the output data. One such tool is http://www.jsonviewer.com/. Once on the
page, input the full invocation URL and click the Get JSON and Parse' button. Figure 1
shows what you might see.

Figure 1: JSON Viewer


If you are using Fiddler to monitor HTTP traffic (http://www.fiddler2.com/fiddler2),
install the JSON viewer.Figure 2 shows how you can view returned JSON objects in
Fiddler.

Figure 2: Fiddler with JSON Viewer


Getting Started with PowerBuilder RESTful clients
Sidebar Tip: PowerBuilder relies on tools from the .NET 4.0 SDK to generate many of
the code artifacts your client application will need. At the time of this writing 12.5 is in
beta release version. The installer does not install the .NET 4.0 SDK. You will need to
download and install the .NET 4.0 SDK from Microsoft. If the SDK is not installed on
your system, you will get an error message when you attempt to generate a proxy.
For this tutorial I'm going to the use the free GeoNames service located at
www.GeoNames.org. The GeoNames geographical database covers many countries
and contains over eight million place names that are available for download free of
charge. GeoNames provides a robust set of RESTful services via which you can access

their database. Figure 3 shows a partial listing of available services. You can find the
full list of available services at http://www.geonames.org/export/ws-overview.html.
To explore GeoNames on your own, you'll want to create a free user account using the
Login link on the upper right side of their home page. Having an account is important
since you'll need to provide your username as a parameter to your service calls and
access using the "demo" user name is extremely limited.

Figure 3: Some GeoName Services


Getting Started
Here's a list of the information you'll need to have handy before entering inputs in the
RESTful service project wizard:
1. The name of PBL into which you want to save your project object (usually the
same pbl containing the project object you use to generate you EXE).
2. The name of PBL into which the project painter will generate the code for your
proxy class (you may want a separate pbl just for proxies that you can batch
refresh if need be).
3. The web method type GET, POST, PUT or DELETE.

4. A name for your proxy class. You will interact with this class in your code. I'd
suggest using the P_ prefix as part of your name.
5. A name for the NameSpace you want to put your proxy class in - you can leave
it blank to use the default namespace.
6. The URI for the service including any parameters needed for the call.
7. The service's return data format: XML or JSON.
8. A name for a generated assembly. This assembly will contain value objects used
as parameters and/or return types. It will be added by the wizard to your target
as a reference. This name will also become the namespace for the assembly.
9. A source to help the painter determine the return data type. There are three
options, choose one:
- A schema document (XSD) that defines the structure of the returned dataset.
- A preexisting assembly that formally defines the return type structure
- A sample XML snippet or JSON object whose data is rich and robust enough
that the tool can figure out the data types from its contents.
Sidebar Tip: As shown in Figure 4 you can cause the generator to include input
parameters on the GetMessage( ) method by changing Service URL literal values to
tokens. Identifiers inside { } will become parameter names. If you leave the literal
values in, the generator will emit a parameter-less method call.

Figure 4: Parameterizing the URL


CIO, CTO & Developer Resources
Stepping though the Wizard
Creating a new proxy class is a two-step process. First, you run the wizard in order to
generate the development time project object and reference assembly. Then you
verify your inputs in the project painter and deploy the project object to generate your
runtime code artifacts. Let me visually guide you through the process. For this example
I'm going to do a GET on the GeoName findNearbyWikipedia service. Follow Figures 5
through 12 in sequence to overview the complete process.

Figure 5: Wizard - Step 1

Figure 6: Wizard - Step 2

Figure 7: Wizard - Step 3

Figure 8: Wizard - Step 4

Figure 9: Wizard - Step 5

Figure 10: Project Painter with generated project object

Figure 11: Click the Generate Button on the Painter Toolbar

Figure 12: Generated Code objects


Sidebar Tip: The invocation method for a GET will always be named GetMessage( ). It is
a good practice to include the service name as part of its corresponding proxy class
name. This will make its intent clear.
Sidebar Tip: If you use a sample dataset (XML or JSON) to generate your reference
assembly, it's important that you examine the emitted assembly to verify the data type
of each property. Occasionally the Microsoft parser will misinterpret a property's type.
You'll want to correct that before moving on. There is no intermediate source code for
the reference assembly, so your only recourse is to supply values to the project object
that will cause it to render the property correctly. For example, a supplied postalCode
element with the value 07960' was generated as a UInt16 instead of the expected
String type. Supplying the value x7960' forced the type to be rendered as a String.
Generated Artifacts
Let's take a more in-depth look at the generated code artifacts. Figure 13 shows the
three kinds of objects generated from a project object.

Figure 13: Generated code artifacts


Project Object is a place to input your choices and a front end onto Microsoft and
PowerBuilder code generation tools. You click the Generate Proxy button on the
Project Object's PainterBar to kick off the code generation process
Proxy Class is the class you instantiate in your code and use to call the service. Don't
modify the generated code. Any changes you make to this code object will be lost
when you regenerate your proxy. To extend or modify this code, inherit from this class
and write your changes in the descendant. You instantiate a proxy type object and call
GetMessage( ) passing appropriate parameters to invoke the service. Figure 14, shows
the contents of a typical Proxy class fronting a call to a GET method.

Figure 14: Contents of a GET proxy object


Request and Response Assemblies contain value objects returned by a GET call or
passed as parameters to DELETE, POST and PUT calls. The WCF infrastructure handles
converting JSON & XML into value objects and vice versa. You are spared from dealing
with low-level conversion issues. Usually there will be a wrapper object that may or
may not have data properties. It's the equivalent of the root element in an XML
document. The wrapper object will have an array of value objects. These are the
repeating row-oriented XML structures. The value object will have some set of return
specific data values. Figure 15 shows the contents of a typical Response Assembly.

Figure 15: Contents of a typical Response Assembly


Scripting the Call
The runtime code algorithm follows these steps:
1. Instantiate the proxy in the appropriate scope.
2. Declare return value reference variables.
3. Call the GetMessage( ) method passing applicable parameters and capture the
return.
4. Destroy the proxy or let it go out of scope.
Figure 16 shows the complete code for a GET service invocation. Of course in a "realworld" application you will do something more significant with the return values than
display them in a messagebox.

Figure 16: Complete code for a GET service invocation


Note that even in well-designed applications, things can go wrong that are outside the
client developer's control. For example, at runtime a service can be down or totally
unavailable at the known URI. Therefor even though exception handling is optional, it's
a best practice to avoid runtime system errors by scripting service calls inside TRY
CATCH blocks that include a robust handler for problematic conditions.
Sidebar Tip: Using a single line DataWindow expression to directly load a data buffer
from a PowerScipt NVO array works great. However, directly assigning a .NET value
object array to a DataWindow buffer using an expression throws a runtime error. As a
result you have to take a more time and labor code intensive approach. You must
either (a) iterate the .NET object array and call SetItem( ) for each value OR (b) assign
the .NET value array to an equivalent intermediate PowerScript NVO type array and
then assign it to a DataWindow.
Sidebar Tip: Unfortunately, Web Service DataWindow Objects are only SOAP
compatible. They have not yet become RESTful aware. To use a DataWindow for data
display, you'll need to declare an external data source DataWindow and manually
populate its buffer from the RESTful WS call return.
Conclusion
RESTful services are becoming pervasive on the Web. The APIs of many popular
services, such as Google are Yahoo, are available as RESTful services. PowerBuilder
12.5 .NET programmers now have the ability to integrate calls to RESTful services in
their applications using standard tools and technologies.
Long Live PowerBuilder!

RESTful Web Services: A Quick-Start How-to Guide - Part


2
Part 2 of "RESTful Web Services: A Quick-Start How-To Guide" explores foundational
issues in coding RESTful operations, including Basic Authentication and Exception
handling. Along the way I'll share with you multiple real-world coding tips and
workarounds.
Introduction
As a teenager, one of my favorite TV shows was "The Wild Wild West." The show's
description goes like this, "... a 60 minute western action series on CBS that was like no
other. Special Agents James West and Artemus Gordon were spies for President
Ulysses S. Grant shortly after the civil war. In every other way, they could be easily
confused with James Bond of the 20th century. They had a "high-tech" (for its day)
railroad car stocked with a compliment of advanced weapons. James West especially
seemed to woo every beautiful woman he encountered. The agents' typical mission
involved saving the United States from some disaster or from being taken over by
some evil genius." Just in case you're curious or are a fan like me, here's a link to the
first part of a full episode on YouTube.
What do RESTful services have to do with the Wild Wild West? In my mind, lots. First,
there's the "wildness" part. As even a brief comparison between service provider APIs
will show you, all RESTful services are not created equal. Each service provider, while
loosely conforming to the state representation paradigm, creates requests and
responses in formats that suit their individual styles and predilections. The onus for
implementing the client side of the service falls on the developer. Then there's the
inventive side of things. Just like special agent Artemus Gordon, a RESTful client
developer needs gadgets, inventiveness, and a continual awareness that she's dealing
with an informal (enemy) specification. Plus, on the PowerBuilder side, there's no
direct support for integrating with DataWindow technology (yet), so you'll have to
invent ways to get data into and out of a display. There's also a need to protect your
app against outside issues by wrapping calls in appropriate try catch blocks to handle
possible HTTP exceptions in order to keep your app responsive and stable.
In my opinion, without a formal schema and metadata description support, configuring
RESTful state service clients will remain an art. I have to admit that I stumbled many
times during experiments while writing this article. I tried calling services whose
communication format didn't quite match the generally expected format. One service
provider expected parameters to be passed and results returned in line-separated text
values in the message body instead of formatting data as XML or JSON. After quite a
bit of poking and debugging it became apparent PowerBuilder will only generate and
interpret message body content formatted as JSON and XML. There is no way to
translate from any other format. All the low-level details are handled internally and
there is no way to get inside the message to change the format. Another service
provider showed their API in terms of JSON data sets, but after hours of
experimentation and a little help from engineering, we discovered that the service

needed multipart/form-data with the JSON sent as a form parameter. This is not a
supported format. So e caveat emptor, make sure the service provider has a
traditional' form of RESTful API. Luckily, I believe most of the big boys' with widely
used APIs do.
Oh, Those Project Objects!
Before getting into details, a few words about RESTful project objects and generated
code. RESTful project objects are designed to be like single shot Derringer pistols; fire
one shot, then you have to reload. Each project object is capable of generating one
proxy object for one method, period. That means if you are interacting with multiple
web methods (GET, POST, PUT and DELETE) you're going to have multiple proxy
objects. In addition, each operation, depending on its type, can have up to two
referenced .NET value objects, one for the request and one for the response. One nice
thing I noticed is that if multiple services rely on the same parameter sets, you can
reuse referenced value objects instead of generating superfluous carbon copies. Figure
1 shows how you'd configure the project painter to reference an already-generated
assembly. Each reference object is placed in its own assembly inside an identically
named namespace. Unfortunately it seems like you can't have multiple value objects in
a single assembly or namespace. Figure 2 shows how reference object assemblies
appear in the Solution Explorer. Figure 3 shows you the wizard view when choosing an
existing value object assembly.

Figure 1: Reusing an already referenced assembly

Figure 2: Referenced object in Solution Explorer

Figure 3: Wizard View: Choosing and existing assembly


Here are a series of tips that I discovered while building my application:
Tip 1: The project object owns its generated proxy object. That means that any
modifications you make to it will be lost if you regenerate the proxy. Because I needed
to make modifications to the generated code, I adapted the strategy of using project
object generation as a starting point only. Once the proxy objects were generated to
my liking, I deleted the project object to avoid accidentally nuking my code.
Tip 2: If you have several services that use an identical request object or return the
same result structure, you can reuse your value object definitions. Generate once, use
many. Just pick them on the wizard or in the project object.
Tip 3: The only door into a new project object is in via the Wizard. This is unlike Classic
where there were two doorways into a new project (Wizard or empty project painter
page).
Tip 4: Here are a couple of neat XML sample data parsing features: First, if an XML
element in the sample dataset has attributes, the attribute values are returned as part
of the generated value object. Figure 4 shows a sample response dataset containing
attributes; Figure 5 show the corresponding generated value object. Second, as you
can see from Figure 6 that nested XML structures becomes separate objects within the
generated assembly.

Figure 4: Sample DataSet with Atributes

Figure 5: Value object generated from sample dataset

Figure 6: Nested XML object


With these project object details behind us we can now move on to two important
runtime housekeeping needs: return status checking and exception handling.
Checking Return Status
Some services indicate their outcome by returning data in a specific and constant
format. Other services indicate their outcome by returning an HTTP status code
instead of an XML or JSON embedded status message. Still other services return status
conditions wrapped in specially formatted XML or JSON structures. If you need to
check a HTTP return status code outcome you'll need to get the status code from the
Response object. Here's how: The response object is returned to the proxy in the form
of a PBWebHttp.WebMessage object. This object has a StatusCode property of type
MessageStatus that holds the response outcome. You can test StatusCode against
enumerated values of the WebResponseStatusCode class and branch accordingly.
Figure 7 shows a partial list of MessageStatus codes and their corresponding meaning.
For a complete listing of HTTP 1.1 code see
http://www.w3.org/Protocols/HTTP/HTRESP.html. Listing 1 shows an example of
testing a proxy method call status code.
PBWebHttp.WebMessage msg //generated code
PBWebHttp.MessageStatus l_msg_status //my custom addition
Try
msg = m_service.GetMessage()
//an exception was not thrown - check the status of the outcome
l_msg_status= msg.Status

if l_msg_status.StatusCode = PBWebHttp.WebResponseStatusCode.OK! then


MessageBox('Success! ','call returned OK')
end if
.....
Listing 1: Testing Result Staus Code

Figure 7: MessageStatus codes


Exception Handling
Wizard-generated proxy code does not contain any exception handling logic. Any
exceptions that occur are thrown up to the caller for processing. Unhandled, these
exceptions become system errors. In the web world, Response status codes in the 400
range indicate client errors; those in the 500 range signal server errors. In WCF 400
and 500 codes raise exceptions.
Best coding practices mandate robust exception handling. Depending on the level of
detail you need to report on, you can handle exceptions either at the proxy method
caller level or within the proxy method call itself.
CIO, CTO & Developer Resources

RESTful service methods, predicated on HTTP, usually throw a


System.Net.WebException. Although the common System.Exception ancestor
property Message contains a description of what went wrong, it's more useful to
directly test the value of the returned status code. Luckily the WebException contains
a reference to the returned Response object which holds the status code. Listing 2
shows an example of testing the status code when a call fails.

catch (System.Net.WebException webex)


System.Net.HttpWebResponse l_resp
l_resp = webex.Response
//Get the response object
if l_resp.StatusCode = System.Net.HttpStatusCode.Unauthorized! then
//check its
status code
MessageBox('Your Credentials Are Invalid', 'Uid=' + uid + '~r~nPwd=' + pwd )
return Result
end if
Listing 2: Testing the status code
Now that you are aware of housekeeping issues, let's take a look at security concerns.
Basic Authentication
WCF supports various forms of authentication ranging from None up to Digital
Certificates. When using Basic Authentication you place your credentials in the user ID
and password in request header fields. If HTTP is used, the credentials are encrypted
within in a plain text header (however, freely available programs such as Fidder can
decrypt SSL). If HTTPS is used, then SSL encryption is applied to all transferred packets.
The client/server negotiation algorithm is: (1) Client makes a request; (2) Server
responds with a 401 unauthorized response; (3) Client responds with a request
including a login header containing a user id and password; (4) The client automatically
includes the header in all requests for the duration of the exchange. Figure 8 show the
conversation as revealed by Fiddler. For a more detailed discussion see
http://www.4guysfromrolla.com/articles/031204-1.aspx

Figure 8: HTTP Authorization Conversation


From the PB WCF perspective, your programming job is to set up the credentials for
the exchange. The low-level runtime exchange process is handled internally by the
infrastructure. A minor challenge is that from the PowerBuilder coding perspective
you're navigating into partially uncharted waters. There is no PowerBuilder
documentation on the members of the Sybase.PowerBuilder.WCF.Runtime assembly.
However, armed with a basic understanding of WCF and a few minutes to examine the
members of the referenced assembly I imagine that you will be able to figure out what
to do. Here's the basic algorithm:
1. In the constructor of your proxy class, instantiate a WebClientCredential object and set
your credentials and authentication type into it. Figure 9 shows the
WebClientCredential class and its members (it's just a value object).
a. Set a value for the AuthenticationMode using a value from the AuthenticationMode
enumeration. In our case we set the value to Basic!
b. Provide your user ID and password.

2. Assign your WebClientCredential object to your WebConnection object. The


WebConnection is already instantiated and has the identifier name
restConnectionObject. Figure 9 shows this object with the important property.
3. Call your service as usual. Be sure to include exception handling code that tests for the
401 HTTP error.

Figure 9: WebClientCredential class


Listing 3 shows a sample RESTful service configured to use Basic authentication.
// vvvvv----Project Generated Code----vvvv
m_service = create
PBWebHttp.RestService("http://phprestsql.sourceforge.net/tutorial/user?firstname={
p_first}&surname={p_last}&email={p_email}&company_uid={p_id}",
PBWebHttp.WebMessageFormat.Xml!, PBWebHttp.WebMessageFormat.Xml!)
restConnectionObject = create PBWebHttp.WebConnection
restConnectionObject.Endpoint =
http://phprestsql.sourceforge.net/tutorial/user?firstname={p_first}&surname={p_last}
&email={p_email}&company_uid={p_id}
restConnectionObject.RequestMessageFormat =
PBWebHttp.WebMessageFormat.Xml!
restConnectionObject.ResponseMessageFormat =
PBWebHttp.WebMessageFormat.Xml!
// vvvvv----Custom Authentication Code----vvvv
PBWebHttp.WebClientCredential lsCredential
//configure credentials
lsCredential = create PBWebHttp.WebClientCredential
lsCredential.AccessAuthentication = PBWebHttp.AuthenticationMode.Basic!
lsCredential.Password='demo'
lsCredential.Username='p126371rw'
restConnectionObject.ClientCredential = lsCredential //add credentials to connection

Listing 3
Secure Socket Layer Communication
Specifying and handling encrypted communication over a SSL transport is pretty
transparent to the application developer. As you can see in Figure 10, all you need to
do is specify the HTTPS protocol in the Project Painter Service URL. The handshake and
encryption are handled by the underlying infrastructure as shown in Figure 11.

Figure 10: Setting up SSL communication

Figure 11: SSL Handshake


Conclusion
In addition to calling service methods, the PowerBuilder client-side developer is
responsible for configuring authentication and authorization properties prior to
making service calls as well writing code to handle server-side errors responses. With a
bit of forethought this code can be written in a reusable manner to work in
conjunction with project painter-generated proxy classes. With the addition of RESTful
web service client-side infrastructure, PowerBuilder .NET clients can now enjoy the
same service-oriented interoperability as other .NET languages.
Long Live PowerBuilder!

Potrebbero piacerti anche