Follow Us on Twitter

Using Amazon’s Product Advertising API

by Jos Nieuwenhuis on October 18, 2009 · 10 comments

Amazon has a very useful web service you can use for free: the Product Advertising API (or AWSECommerceService). This web service is very useful for obtaining product details, e.g. books. Several years I could use this API without any problems. However, recently Amazon changed its authentication mechanism. Of course, my application stopped working. Instead of trying to fix the application I decided to start over again.

Even though REST is considered to be more easy to use, I decided to stick with SOAP. Amazon offers two ways of authentication: with or without WS-Security. Authentication of SOAP requests without WS-Security uses your AWS identifiers and an HMAC-SHA256 signature. This signature should be included in the SOAP Header.

Preferably, the resulting application code should be tool independent. I like the idea of creating libraries to be stored in a Maven repository. For this occasion my tool of choice is NetBeans IDE 6.7. Generating the java web service code turned out to be very straight forward. Just start a new Maven project. In this project you can create a Web Service Client (JAX-WS Style) based on a WSDL. The resulting pom file looks something like this.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.amazon.webservices</groupId>
  <artifactId>aws-ecommerce-service</artifactId>
  <packaging>jar</packaging>
  <version>2009_10_01</version>
  <name>AWSECommerceService</name>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.0.2</version>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxws-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <goals>
              <goal>wsimport</goal>
            </goals>
            <configuration>
              <wsdlFiles>
                <wsdlFile>AWSECommerceService.wsdl</wsdlFile>
              </wsdlFiles>
              <staleFile>${project.build.directory}
              /jaxws/stale/AWSECommerceService.stale</staleFile>
            </configuration>
            <id>wsimport-generate-AWSECommerceService</id>
            <phase>generate-sources</phase>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>javax.xml</groupId>
            <artifactId>webservices-api</artifactId>
            <version>1.4</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>com.sun.xml.ws</groupId>
      <artifactId>webservices-rt</artifactId>
      <version>1.4</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

Maven command mvn clean install will generate, compile en install the library in the local Maven repository. This library I used in another Maven project which contains a BookService component. The interface is very simple:

public interface BookService {
  public abstract Book findByISBN(String isbn);
}

Implementing the authentication code turned out to be quite a hassle. One possibility is adding a Java class which performs the SOAP Handling: AmazonSOAPHandler. This class adds the required Header elements to the SOAP Message.

public Book findByISBN(String isbn) {
  if (isbn == null || isbn.length() != 10) {
    return null;
  }
  AWSECommerceService awsecommerceservice = new AWSECommerceService();
  awsecommerceservice.setHandlerResolver(new HandlerResolver() {
    @Override
    public List<Handler> getHandlerChain(PortInfo portInfo) {
      List<Handler> handlerList = new ArrayList<Handler>();
      handlerList.add(new AmazonSOAPHandler());
      return handlerList;
    }
  });
  AWSECommerceServicePortType awsecommerceserviceport =
      awsecommerceservice.getAWSECommerceServicePort();
  List<ItemLookupRequest> request = createItemLookupRequest(isbn);
  Holder<List<Items>> items = new Holder<List<Items>>();
  awsecommerceserviceport.itemLookup(null, AWS_ACCESS_KEY_ID, null, null,
      null, null, null, request, null, items);
  return parseResults(items);
}

AmazonSOAPHandler will ‘handle’ the SOAP Message: it will include the header information. Something like this:

public boolean handleMessage(SOAPMessageContext context) {
  Boolean outboundProperty =
      (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  if (outboundProperty.booleanValue()) {
    try {
      AmazonSOAPHeaderData factory = new AmazonSOAPHeaderData();
      SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
      SOAPHeader header = envelope.addHeader();
      factory.addInformationToSOAPHeader(header);
    } catch (Exception ex) {
      Logger.getLogger(AmazonSOAPHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  return true;
}

Details on how to calculate the signature can be found on Amazon’s Product Advertising API website. The only alteration I had to make in order to make it work was adding the trim operation on the resulting signature:

private String hmac(String stringToSign) {
  String sig = "";
  byte[] data;
  byte[] rawHmac;
  try {
    data = stringToSign.getBytes(UTF8_CHARSET);
    rawHmac = mac.doFinal(data);
    Base64 encoder = new Base64();
    sig = new String(encoder.encode(rawHmac));
  } catch (UnsupportedEncodingException e) {
    throw new RuntimeException(UTF8_CHARSET + " is unsupported!", e);
  }
  return sig.trim();
}

On my personal blog you can read this item in Dutch.

Using Amazon's Product Advertising API, 5.0 out of 5 based on 1 rating

Ratings:
VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)

10 comments on “Using Amazon’s Product Advertising API

  1. Anil Pal on said:

    Thank you thank you thank you. I’ve been trying to figure this out
    for the whole day, this has helped me out tremendously.

    One question, are your complete code examples available anywhere?

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. Pingback: Tweets die vermelden Using Amazon’s Product Advertising API -- Topsy.com

  3. Hi Anil,
    You can download the code from this URL:
    http://blog.josnieuwenhuis.nl/download/aws-ecommerce-client-code.tar.gz
    Of course you will need to insert your own awsAccessKeyId and awsSecretKey in the class AmazonSOAPHeaderData. For instructions on how to get your own Access ID and Secret Key please go to the Amazon AWS website: http://aws.amazon.com/

    VN:F [1.9.22_1171]
    Rating: +1 (from 1 vote)
  4. Do you use x.509 ?
    It looks like from the sample code you are using access keys.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  5. Pingback: Amazon Advertising API – JAVA « Tutoriales para principiantes

  6. Hey,

    Thanks for the sample code . But when i try using this sample i get 403 forbidden probelm though my Rest call work fine. SOAP is not working good for me

    Kindly Let me know if you have any reasons for that

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • Hi Aswin,

      A 403 message can be caused by an incorrect authentication. Did you include your awsAccessKeyId and awsSecretKey in the AmazonSOAPHeaderData.java file?

      VN:F [1.9.22_1171]
      Rating: 0 (from 0 votes)
  7. Anand Sagar on said:

    Hi Aswin,
    I am very new to this API. I downloaded your code but when i try to open it in Eclipse i get errors on import com.amazon.webservices * statements . I feel i dont have required library files for this to compile. Can you please help me up in this..

    Thanks

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  8. Hello,

    I get 403 forbidden error code when I’m trying to make a simple search. It worked 2 hours ago and now it does not…This web-service kinda sucks…

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

* Copy This Password *

* Type Or Paste Password Here *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 

Previous post:

Next post:

About Whitehorses
Company profile
Services
Technology

Whitehorses website

Home page
Whitebooks
Jobs

Follow us
Blog post RSS
Comment RSS
Twitter