SOAP based AXIS Client for Amazon Search

Introduction

This is a client that used to perform Amazon search. It facilitates user to enter words as query parameters in the given TextField of the GUI and in a moment is shows the search results in the TextPane of the GUI. The most special feature of this client is, when user press space after typing a word it starts searching for that word and displays the results while the user types the next word. This feature is obtained by using the InvokeNonBlocking operation of Axis2.

Getting Started

Amazon search operation is done by means of Amazon Web API. (You can learn more and create your own account in Amazon Web API here http://www.amazon.com/gp/aws/registration/registration-form.html ). If you need to build your own client using this Web API, first you should have license key. You can get the license key at Amazon Web API page. Only one key is generated for each email address. Then you have to download the WSDL file which has described the web service. Finally you can build your own SOAP based clients.

When you work with this client, you can use the given license key with this release (You can find the license key at Modules/samples/key.properties file). But it is convenient for you to get a license key for you.

To use this client you have to compile and build the jars. You can do this with Maven. All you have to do is go to Modules/Samples and type maven in the command prompt. This will compile and will build all the jars required. Then you can run this code using ANT. After building with maven, type the command “ant AmazonSearch” in the command prompt. Then you can see the GUI.

Operation

Now you can do Amazon search. Just type the word you want to search in the small textField in the GUI. After you press enter or space, client starts the searching and you can see the results displaying in few seconds. But this client is using the default license key. If you have got your own license key, you can set it by Set->key menu command. Then your key is saved in a property file permanently and from that onward it is using your key to access the Amazon Web API.

You can also set the number of results per page from the set menu. Maximum is 1000 results.

Architecture of the code

This client is build from five classes.

  1. AsynchronousCleint:- This class is responsible for sending requests,
  2. ClientUtil:- Build the soap envelope and the messageContext;
  3. ClientCallbackHandler:- receives the response messages and process it to extract the required content.
  4. LinkFollower:- Listening to the hyperlink events and produce new windows to open relevant URLs.
  5. GUIHandler:- Build & Show GUI, Listnening to the events in the GUI,

The main method is inside the AsynchronousClient class. First it objects of LinkFollower and GUIHandler and set them as threads. Later you will understand why do we need those. Then the main program calls to the GUIHandler to display the GUI. After that, the program is running according to the events fired by the GUI. KeyListner is listening to the characters typed in the textField. When it detects a space or Enter key pressing, it sets the flag “doSearch”. Then a thread will soon detect it and reset it and send a request to search for that word. It don't use much time to send a request, but here it's done by a separate thread because it's important to isolate the GUI from internal actions. Then the user never gets interrupted in anyway. So the user can type the query terms continuously on the GUI while the program do the search for the query terms that already typed by the user and displays the results.

The use of the other thread comes when the user click on a hyperlink. Then the program should open the URL in a new window. That consumes little bit time. So a separate thread is used for that. That's how we need that LinkFollower object as a Thead.

Now we have two threads, one is for prepairing and sending the soap request without interrupting the user and other is to open new windows for clicked urls. But there is another important action. That is processing the received response and displaying the results. That is done in the ClientCallbackHandler. This is a important feture of InvokeNonBlocking operation of Axis2. It let you to have an additional thread in the callbackHandler class. All you have to do is sending an object of that class as a parameter when you send the message. How it is done in the programme is as follows.

call.invokeNonBlocking(opdesc, requestContext, new ClientEchoCallbackHandler());

opDesc – is a QName which caries the operation name and relevant namespace.

requestContext – is a MessageContext that holds the request soap envelope.

ClientEchoCallbackHandler – is a class that receives the response soap envelope.

Briefly it is client thread is just sending the requests and do not wait for the response. So this client can send any amount of request sequentially irrespective of whether the responses are received or not. ClientEchoCallbackHandler is responsible for receiving response message and process it. It extracts the required details from the message and display it in the TextPane of the GUI.

The request soap message is built at the ClientUtil class. According to the Amazon Web API wsdl file, required namespaces are selected and attached to the envelope. We don't have to include anything in the header. The name of the first child element of the body should be operation name and it should be namespace qualified. We also have to include the binding namespace to this element. Here it is attached as an attribute to that element,

OMElement opration = omFactory.createOMElement("doAmazonSearch", "urn:AmazonSearch", "ns1");

opration.addAttribute("SOAP-ENV:encordingStyle", "http://schemas.xmlsoap.org/soap/encoding/", null);

All the child elements of the operation element are carrying required parameters such as license key, query terms, results per page, etc. (for more information, click here),

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://webservices.amazon.com/AWSAlexa/2005-02-01" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<soapenv:Header></soapenv:Header>
<soapenv:Body>
<tns:Search>
<SubscriptionId xmlns="">0Y6WJGPB6TW8AVAHGFR2</SubscriptionId>
<Request xmlns="">
<ResponseGroup>Web</ResponseGroup>
<Query>axis</Query>
<Count>2</Count>
<IgnoreWords>90</IgnoreWords>
<AdultFilter>yes</AdultFilter>
</Request>
</tns:Search>
</soapenv:Body>
</soapenv:Envelope>

ClientCallbackHandler processing response soap and extract elements which have the local name as "NavigableURL". It has to work with Object Model(OM). You can notice that it uses several Iteraters to go through the children of an OMElement. You are returned and Object from the Iterater that can be casted to a OMNode. Since you can't call for the children of an OMNode we have to cast it to a OMElement. Before that we have to check it whether it is an OMElement, as follows.

Iterator iterator0 = operation.getChildren();

while (iterator0.hasNext()) {

OMNode node = (OMNode) iterator0.next();

if (node.getType() == OMNode.ELEMENT_NODE) {

OMElement elem = (OMElement) node;

The response soap message is as follows, it is contains just two search results.

<SOAP-ENV:

Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/e
nvelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XML Schema">
<SOAP-ENV:Body>
<SearchResponse xmlns="http://webservices.amazon.com/AWSAlexa/2005-02-01">
<OperationRequest>
<RequestId>03YF6QNSD5A04HQM1QMR</RequestId>
</ OperationRequest>
<SearchResult>
<Request> <IsValid>True</IsValid> </Request>

<Alexa>
<WebSearch>
<SearchPhrase>gayan</SearchPhrase>
<TotalCount>32376</TotalCount>
<Results>

<Result>
<DataUrl type="navigable">http://twexus.com/</DataUrl>
<NavigableUrl> http://twexus.com/</NavigableUrl>
<Number>1</Number>
<Title>Images: Tuesday, May 2 4, 2005</Title>
<Score>71060</Score>
<CrawlData>
<Size>58014</Size>
<MD5Checksum>65e f724f051197d43fc64e70d5a14d9d</MD5Checksum>
</CrawlData>
</Result>

<Result>
<DataUrl type="navigable">http://www.live365.com/stations/toonsee</DataUrl>
<NavigableUrl>http://www.live365.com/stations/toonsee</NavigableUrl>
<Number>2</Number>
<Title>
Online African Radio Station - Live365 Internet Radio - Arabix</Title>
<Score>709
87</Score>
<CrawlData>
<Size>32174</Size>
<MD5Checksum>67c7979db66ee2e3ec197f0ec583 9e3a</MD5Checksum>
</CrawlData>
</Result>


</Results>
</WebSearch>
</Alexa>
</SearchResult>
</SearchResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 

Extending the Client

If you observe the WSDL file of the Amazon API, you can find two more operations other than “doAmazonSearch”. Those are

You can extend this program to work these operations too. Because the soap requests and responses are different, it will need separate ClientUtil classes and ClientCallbackHandler classes to fulfill this task. Anyway you can define those classes with any name and the only condition is when you invoke the operation you have to send an object of relevant CallbackHandler class and it should extend the CallbackHandler too.