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)

{ 8 comments… read them below or add one }

Anil Pal October 19, 2009 at 3:28 am

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?

Reply

Jos Nieuwenhuis October 19, 2009 at 10:21 pm

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/

Reply

bo xu December 1, 2009 at 7:16 pm

Do you use x.509 ?
It looks like from the sample code you are using access keys.

Reply

Jos Nieuwenhuis December 2, 2009 at 9:50 am

The Procuct Advertising allows two ways of authenticating requests: with WS-Security (X.509 Certificates) or without WS-Security (which uses your AWS identifiers and an HMAC-SHA256 signature). The blog post only describes authentication without WS-Security.

If you need more information on using X.509 certificates please read the Amazon documentation: http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/WSSecurity.html

Reply

Ashwin July 30, 2010 at 1:02 pm

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

Reply

Jos Nieuwenhuis August 2, 2010 at 5:46 pm

Hi Aswin,

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

Reply

Anand Sagar August 27, 2011 at 1:02 pm

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

Reply

Tudor January 4, 2014 at 8:57 pm

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…

Reply

Leave a Comment

 

{ 2 trackbacks }

Previous post:

Next post:

About Whitehorses
Company profile
Services
Technology

Whitehorses website

Home page
Whitebooks
Jobs

Follow us
Blog post RSS
Comment RSS
Twitter