I spent a good part of this evening (can you call it evening when it’s well past midnight?) trying to learn how to do a simple Java-based query using Amazon’s Product Advertising API. This entire exercise could have been finished within an hour had there been clear, concise documentation. Instead of one recipe for success, Amazon presents a dizzying array of approaches that lead to many dead ends.
In hopes of saving others from encountering these difficulties, I present you with my findings. For those of you that just want the recipe. Jump to the bottom.
Lesson 1 – Don’t Trust the Getting Started Guide
Admittedly the getting started guide gives a useful overview of the functionality and the approach to using the API. However, following the instructions step by step will only lead to frustration. The Java example for
Implementing a Product Advertising API Request DOES NOT WORK!. One would think that simply swapping in the proper access key where it says “YOUR ID” would be all that is needed, but upon execution I found it yields the following:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 400: Bad Request
Thinking I had omitted something small, I looked into resolving this error only to discover:
Lesson 2 – APA API’s Authentication has changed
As of August 15, 2009, the API requires a signature mechanism for authentication. In addition to invalidating all the code from the getting started guide, it also adds additional poorly documented steps to the process. Amazon does provide some detail, but it’s probably not the quickest path to get up and running.
Lesson 3 – There are some semi-functional examples
After digging around in the documentation, I found these two examples: Product Advertising API Signed Requests Sample Code – Java REST/QUERY and Product Advertising API Signed Requests Sample Code – Java SOAP. Since everything I had tried up until this point had been SOAP-centric, I decided to try the SOAP example first. Upon the code into Eclipse, I found that this example was fraught with too many errors and dependencies, so I turned to the REST example.
The REST code was clear and mostly error free. The few errors I saw were caused by the absence of the Apache Commons Codec library. After downloading this jar and adding it to my classpath, the example code finally compiled. Unfortunately, when I went to run it, I was greeted with this exception:
Server returned HTTP response code: 403 for URL: http://ecs.amazonaws.com/onca/xml?....
Lesson 4 – Apache Commons Codec 1.3 and 1.4 are different
After crawling through the forums looking for answers, I found out that the REST example above depended on Apache Commons Codec version 1.3, whereas the version I downloaded was 1.4. It turns out the old version appended extra CRLF (\r\n) characters onto the authentication signature, and the workaround is to force the new codec to exhibit the same behavior. If you read the codec’s documentation, you’ll see that the default behavior comes when you set the line length to 76 characters. To fix the REST example change line 183 of SignatureRequestHelper to:
Base64 encoder = new Base64(76, new byte);
After doing all this, I finally got a small victory in the form of real output:
Map form example: Signed Request is "http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=...." Signed Title is "Harry Potter and the Deathly Hallows (Book 7)" String form example: Request is "http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=...." Title is "Harry Potter and the Deathly Hallows (Book 7)"