<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Adam Trachtenberg &#187; Web Services</title>
	<atom:link href="http://www.trachtenberg.com/blog/tag/web-services/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.trachtenberg.com/blog</link>
	<description>Thoughts on PHP, eBay, and too many technical topics for my family's liking.</description>
	<lastBuildDate>Tue, 24 Aug 2010 21:39:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>REST Web Services, the Book</title>
		<link>http://www.trachtenberg.com/blog/2006/11/06/rest-web-services-the-book/</link>
		<comments>http://www.trachtenberg.com/blog/2006/11/06/rest-web-services-the-book/#comments</comments>
		<pubDate>Mon, 06 Nov 2006 07:29:08 +0000</pubDate>
		<dc:creator>Adam Trachtenberg</dc:creator>
				<category><![CDATA[Web Services]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.trachtenberg.com/blog/2006/11/06/rest-web-services-the-book/</guid>
		<description><![CDATA[Sam Ruby and Leonard Richardson are writing a book on <a href="http://www.intertwingly.net/blog/2006/11/03/REST-Web-Services">REST Web services</a>. Very exciting. I love reading Sam's blog and watching him untangle standards.

Looking at the <a href="http://www.crummy.com/writing/REST-Web-Services/">Table of Contents</a>, I'm particularly interested in "Appendix A: HTTP status codes and when to use each one." (Yes, I am serious.)]]></description>
			<content:encoded><![CDATA[<p>Sam Ruby and Leonard Richardson are writing a book on <a href="http://www.intertwingly.net/blog/2006/11/03/REST-Web-Services">REST Web services</a>. Very exciting. I love reading Sam&#8217;s blog and watching him untangle standards.</p>
<p>Looking at the <a href="http://www.crummy.com/writing/REST-Web-Services/">Table of Contents</a>, I&#8217;m particularly interested in &#8220;Appendix A: HTTP status codes and when to use each one.&#8221; (Yes, I am serious.)<br />
<span id="more-664"></span><br />
When I designed &#8220;<a href="https://www.dudewheresmyusedcar.com/">Dude, Where&#8217;s My Used Car</a>,&#8221; my mashup between eBay Motors and Google Maps, I churned through a number of different ways to signal failure. My biggest issue is that there&#8217;s so many places my request can fail, I&#8217;m not sure how to &#8220;correctly&#8221; represent that back inside my mashup.</p>
<p>For example, in response to a user-generated action (such as filling out a form and clicking submit), my mashup initiates a HTTP GET AJAX request (well, AJAJ because I&#8217;m using JSON instead of XML) which hits my web server. I then use PHP to parse the request, generate a corresponding SOAP request to eBay&#8217;s web service gateway, wait for result, pick it apart and convert the bits I want to JSON. This data is then passed back to the browser, where I (well, <a href="http://dojotoolkit.org/">Dojo</a>, actually) evals it.</p>
<p>When everything works, everything works.</p>
<p>But what happens when the user enters an invalid ZIP Code? eBay will return an error, and I&#8217;d like to proxy this back to the application, so I can toss up a message.</p>
<p>Should I return 200 OK and pass back the message? That&#8217;s one option, but I&#8217;d prefer not to need to check the data structure to see if I got the normal data I expected or some nasty error instead.</p>
<p>Besides, Dojo lets me specify a separate error handler callback function. It seems a cleaner design to handle all the errors there. But then I can&#8217;t return 200. What to use instead? 400 Bad Request?</p>
<p>Then there&#8217;s cases where the error is not the user&#8217;s fault, but either my fault or eBay&#8217;s fault. What should I do if eBay returns a SOAP envelope my PHP script can&#8217;t parse? 502 Bad Gateway? Or if the eBay server returns a SOAP Fault? The same 500 Internal Server Error I got back from eBay?</p>
<p>Should I not let my web server&#8217;s interaction with eBay bleed back into browser?</p>
<p>Here&#8217;s another example: when eBay&#8217;s server is too busy, it returns <a href="http://developer.ebay.com/DevZone/migration/docs/BestPractices/RetryCode.htm">Error Code 10007</a>. I can retry (and hopefully fix the problem) inside of my PHP script without even needing to message back to the browser. But if I did ultimately give up retrying, should I pass back 503 Service Unavailable? Am I on the hook for translating between SOAP and REST in my server-side proxy PHP script?</p>
<p>Maybe I can use 4xx codes for problems which are &#8220;user generated&#8221; in some form. These are things which require the user to take an action to remedy. And for things which are broken but otherwise outside of the control of the user (such as my SOAP client being unable to understand eBay&#8217;s SOAP response) I can use 5xx.</p>
<p>I actually like this idea, but I&#8217;m wondering if there&#8217;s a &#8220;standard&#8221; way to indicate errors and failures in a AJAX application. I can&#8217;t find one, but I&#8217;m not very familiar with what&#8217;s out there.</p>
<p>PS: My vote is to leave off the &#8220;With Ruby&#8221; part of the title, and go with plain &#8220;REST Web Services&#8221;.</p>
<img src="http://www.trachtenberg.com/blog/?ak_action=api_record_view&id=664&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.trachtenberg.com/blog/2006/11/06/rest-web-services-the-book/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>eBay SOAP Update: Syntax Matters</title>
		<link>http://www.trachtenberg.com/blog/2005/10/24/ebay-soap-update/</link>
		<comments>http://www.trachtenberg.com/blog/2005/10/24/ebay-soap-update/#comments</comments>
		<pubDate>Mon, 24 Oct 2005 07:04:48 +0000</pubDate>
		<dc:creator>Adam Trachtenberg</dc:creator>
				<category><![CDATA[Web Services]]></category>
		<category><![CDATA[ebay]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[upgrading to php 5]]></category>

		<guid isPermaLink="false">http://www.trachtenberg.com/blog/2005/10/23/ebay-soap-update/</guid>
		<description><![CDATA[I saw a request for some actual SOAP code, so I will try and oblige. I don&#8217;t want to publish the entire code because there&#8217;s lots of messy stuff that&#8217;s specific to eBay&#8217;s SOAP API. I&#8217;ll talk about that some other time, but for now, those details just get in the way.
Therefore, I&#8217;ll pull out [...]]]></description>
			<content:encoded><![CDATA[<p>I saw <a href="http://www.phpdeveloper.org/news/4128">a request for some actual SOAP code</a>, so I will try and oblige. I don&#8217;t want to publish the entire code because there&#8217;s lots of messy stuff that&#8217;s specific to eBay&#8217;s SOAP API. I&#8217;ll talk about that some other time, but for now, those details just get in the way.</p>
<p>Therefore, I&#8217;ll pull out a few lines, combine that with some hand waving, and just hope for the best. Here&#8217;s the before:</p>
<pre><code>
$wsdl = 'http://developer.ebay.com/webservices/latest/eBaySvc.wsdl';
$client = new SoapClient($wsdl);

$params = array('Query' => 'ipod');
$results = $client->GetSearchResults($params);

foreach ($results->SearchResultItemArray->SearchResultItem as $item) {
  print $item->Item->Title . &quot;\n&quot;;
}
</code></pre>
<p>Without the <tt>classmap</tt> option, I create a <tt>SoapClient</tt>, make my request, and then iterate through the results to print out the titles of the matching items. This isn&#8217;t complex; however, the iteration is a little klunky due to limitations of SOAP and the design of eBay&#8217;s Web service.</p>
<p>For example, the <tt>SearchResultItemArray</tt> only contains <tt>SearchResultItem</tt>, so it&#8217;s kludgy to reference <tt>SearchResultItemArray->SearchResultItem</tt>. Likewise, when I&#8217;m just getting a quick dump of <tt>Item</tt> information, it&#8217;s not so nice to specifically access the <tt>Title</tt> element.</p>
<p>By defining a couple of classes and telling the SoapClient object map them to the return data, I can clean this up:</p>
<pre><code>
class eBaySearchResultItemArrayType implements IteratorAggregate {
  public function getIterator( ) {
    return new ArrayObject($this->SearchResultItem);
  }
}

class eBaySearchResultItemType {
  public function __toString() {
    return $this->Item->Title . &quot;\n&quot;;
  }
}

$wsdl = 'http://developer.ebay.com/webservices/latest/eBaySvc.wsdl';
$options = array('classmap' => array(
  'SearchResultItemArrayType' => 'eBaySearchResultItemArrayType',
  'SearchResultItemType' => 'eBaySearchResultItemType',
  ),
);

$client = new SoapClient($wsdl, $options);

$params = array('Query' => 'ipod');
$results = $client->GetSearchResults($params);

foreach ($results->SearchResultItemArray as $item) {
  print $item;
}
</code></pre>
<p>To solve my first problem, the iteration, I make  <tt>eBaySearchResultItemArrayType</tt> implement the <tt>IteratorAggregate</tt> interface. When a PHP 5 class implements this interface, PHP will invoke the <tt>getIterator()</tt> method during a <tt>foreach</tt> loop.</p>
<p>In this case, I return <tt>$this->SearchResultItem</tt>, wrapping it inside an <tt>ArrayObject</tt> to make the array iterable.</p>
<p>For the pretty-printing issue, I define a <tt>__toString()</tt> method inside of <tt>eBaySearchResultItemType</tt>. Now, when I print an instance of this class, PHP calls that method instead.</p>
<p>With my classes defined, I use the <tt>classmap</tt> option to map the PHP classes to the SOAP complexTypes, and pass this mapping along as part of the second parameter to the <tt>SoapClient</tt> constructor.</p>
<p>Once this is set up, everything else in the request is identical. However, when I print out the results, the syntax is clean:</p>
<pre><code>
foreach ($results->SearchResultItemArray as $item) {
  print $item;
}
</code></pre>
<p>At one level, this is just syntax and icing. However, I don&#8217;t think you should dismiss syntax with a wave of your hand. To quote Sam Ruby on <a href="http://www.intertwingly.net/blog/2005/09/29/Ruby-1-8-vs-LINQ">C# and LINQ</a>:</p>
<blockquote><p>[S]yntax matters.  Very much so.</p></blockquote>
<p>So, I am convinced that this is a good thing to spend time on. There are a couple other tricks I&#8217;ve pulled out, such as:</p>
<pre><code>
class eBayFeesType implements ArrayAccess {

  public function offsetGet($offset) {
    foreach ($this->Fee as $value) {
      if ($value->Name == $offset) {
        return $value;
      }
    }
  }

  /* and the other interface methods... */
}

class eBayFeeType {
  public function __toString() {
    return (string) $this->Fee->_;
  }
}
</code></pre>
<p>This lets me do:</p>
<pre><code>
echo &quot;Listing fee is: &quot;, $results->Fees['ListingFee'], &quot;\n&quot;;
</code></pre>
<p>Which I must say is far nicer than either iterating in place or even calling out to a utility method.</p>
<p>I was interested to discover that I needed to manually cast <tt>$this->Fee->_</tt> to a string because I thought it was a string. Actually, it is a float, and PHP won&#8217;t autocast floats to strings in this instance.</p>
<p>Personally, I think if PHP should autocast here, but I can see the logic. If you&#8217;re promising to return a string, you should actually return one.</p>
<p>At first, I was writing each class by hand. But that got boring and wasn&#8217;t scalable. Therefore, my new goal is to automate this process. I am writing a script to read the WSDL file, parse out the complexTypes, and then convert them to PHP classes.</p>
<p>My original script was using the <tt>SoapClient::__getTypes()</tt> method as a pre-processor, but I needed to parse that output again to get it into a usable format. After a little digging, I discovered that PEAR::SOAP implements its own parsing routines and gives me a far more flexible PHP data structure to manipulate. So, I am going in that direction instead.</p>
<p>Since this is a one-time action, speed isn&#8217;t vital, so it&#8217;s okay that PEAR::SOAP is written in PHP.</p>
<p>If you&#8217;re interested in more details on these new PHP 5 features, they&#8217;re documented in the <a href="http://www.php.net/manual">PHP Manual</a>. Alternatively, in a shameless plug, you can check out my book <a href="http://www.amazon.com/exec/obidos/ASIN/0596006365/ref=nosim/trachtenberg-20">Upgrading to PHP 5</a>.</p>
<img src="http://www.trachtenberg.com/blog/?ak_action=api_record_view&id=325&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.trachtenberg.com/blog/2005/10/24/ebay-soap-update/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Programming eBay Web Services with PHP 5 and Services_Ebay</title>
		<link>http://www.trachtenberg.com/blog/2005/01/29/programming-ebay-web-services-with-php-5-and-services_ebay/</link>
		<comments>http://www.trachtenberg.com/blog/2005/01/29/programming-ebay-web-services-with-php-5-and-services_ebay/#comments</comments>
		<pubDate>Sun, 30 Jan 2005 03:21:00 +0000</pubDate>
		<dc:creator>Adam Trachtenberg</dc:creator>
				<category><![CDATA[Web Services]]></category>
		<category><![CDATA[Writing]]></category>
		<category><![CDATA[ebay]]></category>
		<category><![CDATA[pear]]></category>

		<guid isPermaLink="false">http://www.trachtenberg.com/wordpress/?p=7</guid>
		<description><![CDATA[My latest article is now available on the O&#8217;Reilly Network. &#34;Programming eBay Web Services with PHP 5 and Services_Ebay&#34; provides an introduction to eBay Web services and Stephan Schmidt&#8217;s awesome PEAR package, Services_Ebay.
As I&#8217;ve blogged before, Services_Ebay is a PHP 5-only module that makes it drop dead simple to interact with eBay Web services. This [...]]]></description>
			<content:encoded><![CDATA[<p>My latest article is now available on the O&#8217;Reilly Network. &quot;<a href="http://www.onlamp.com/pub/a/php/2005/01/27/ebay_webservices.html">Programming eBay Web Services with PHP 5 and Services_Ebay</a>&quot; provides an introduction to <a href="http://developer.ebay.com">eBay Web services</a> and <a href="http://www.php-tools.net">Stephan Schmidt&#8217;s</a> awesome <a href="http://pear.php.net">PEAR</a> package, <a href="http://pear.php.net/package/Services_Ebay">Services_Ebay</a>.</p>
<p>As I&#8217;ve <a href="http://www.trachtenberg.com/blog/programming/php/services-ebay.html">blogged before</a>, Services_Ebay is a PHP 5-only module that makes it drop dead simple to interact with eBay Web services. This piece walks you through getting started with Services_Ebay, shows you how to search the eBay listing database, and then displays the found items in a variety of ways.</p>
<p>As a extra special bonus, I highlight all the cool behind-the-scenes PHP 5 magic that&#8217;s taking place. I also do some nifty stuff by overriding Stephan&#8217;s model classes to provide an alternative data view. I&#8217;m sure this will lead to nasty comments from the peanut gallery about my lack of respect for MVC.</p>
<img src="http://www.trachtenberg.com/blog/?ak_action=api_record_view&id=7&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.trachtenberg.com/blog/2005/01/29/programming-ebay-web-services-with-php-5-and-services_ebay/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
