Module 3 Task 1: Retrieving Media Using Web Services
- Highlights
-
- Use
HttpRequest - Use
PullParser - Get metadata from search results
- Use
Introduction
This task uses the Web Services API to search for media using the Yahoo! Search service.
Running the Project
- Download the Module 3 Task 1 NetBeans project
- Run the project.
The functionality is the same as in previous tasks. The only difference is that the data is obtained with internet search. Figure 1 shows the result.
The application search query is predefined to be "Sun Microsystems", and a maximum of 50 objects are found. In a future project you will create a search text box so users can enter a search query.
Figure 1
Architecture
For the first time this tutorial assembles metadata from search results. This requires two new classes, YahooAPI.fx and WebSearch.fx, as shown in Figure 2.
- The new
YahooAPI.fxclass is a "custom" class created to interface with the Yahoo! API. Typically you create a custom class such as this for each Web Services API you use. WebSearch.fxusesjavafx.io.http.HttpRequestto send an HTTP GET request to the web service API andjavafx.data.pullis used to parse the response. WebSearch handles the interaction betweenjavafx.data.pullandjavafx.io.http.HttpRequest.
Figure 2
Using Yahoo! Web Services
In this application you search the web with Yahoo! services. To do this you construct a Representational State Transfer query (REST). You can read about the query format for the Yahoo APIs at http://developer.yahoo.com/search/image/V1/imageSearch.html.
Look at Figure 2 to get an idea of what you need to do to make this work.
Being familiar with the API for javafx.data.pull and javafx.io.http will help you understand this task. Consult the API documentation which has excellent examples of how the API is used.
WebSearch creates the input stream that handles the GET request. The HttpRequest onInput variable is implemented to call the PullParser's parse() function. The PullParser's onEvent function is implemented to call the WebSearch API's abstract function onPullEvent(). is implemented in the concrete class YahooAPI. As YahooAPI's implementation of onPullEvent processes events from the PullParser, new MetaData objects are created and inserted into the WebSearch results var. In Wall, the metaData variable is bound to WebSearch.results. The following sections examine these steps in greater detail.
Updating MetaData.fx
In this task the MetaData sequence is bound to the Yahoo search results. The data model includes the response fields that are useful in this application. The public classes Thumb and MetaData form the responses into URLs. Thumb encapsulates the web search results data that corresponds to the thumbnail image. For example, the thumbnail URL. MetaData encapsulates those parts of the web search results that are of interest to the application. For example, the media URL and the Thumb data. This application doesn't use all of this information, but it is worth exploring.
Using HttpRequest to Get the Input Stream
WebSearch handles the GET request that fetches results for the search. It uses a local instance of HttpRequest to send the request. When the response to the request comes back, HttpRequest calls the onInput function, if it is defined. In the instance of HttpRequest in WebSearch.fx, the onInput() function is defined to call the PullParser's parse method, which parses the input stream.
HttpRequest calls onInput when the input stream response is ready. By providing a function for onInput you can tell the parser to parse the input stream.
As PullParser parses the input stream, the parser calls the onEvent function of the PullParser instance when the start or end of an element is encountered. In WebSearch, the onEvent variable is bound to an abstract WebSearch function onPullEvent().
Because the method is abstract, it must be implemented in a class that
extends from WebSearch. In this case, that class is YahooAPI.
def pullParser = PullParser {
documentType: PullParser.XML;
// Forward events to the YahooAPI onPullEvent function
onEvent: onPullEvent
}
The HttpRequest has a location variable, which is the URL of the search API. This is bound to the searchLocation variable in WebSearch. By overriding searchLocation in YahooAPI, you effectively set the location for HttpRequest.
/** Refer to the javadoc for javafx.io.HttpRequest */
def httpRequest : HttpRequest = HttpRequest {
method: HttpRequest.GET
location: bind searchLocation
onResponseMessage: function(msg:String) {
if ( httpRequest.responseCode != 200 ) {
println("HTTP response {httpRequest.responseCode}: {msg}");
}
}
In addition to location, the other thing you need is a search query. WebSearch declares a searchQuery variable for this purpose. Notice that YahooAPI overrides searchQuery. In YahooAPI, if the searchQuery changes, the searchLocation is updated. Thus, when the search() function is executed, the HttpRequest's location variable will have the correct URL for the query.
onInput: function(is: InputStream) {
try {
pullParser.input = is;
pullParser.parse();
} finally {
is.close();
}
}
The code above sets pullParser.input to the input stream coming back from this function, and calls pullParser.parse. The pullParser parse method starts the parser working , calling onEvent as it encounters events.
Building the REST Query for Yahoo Image Search
YahooAPI.fx extends WebSearch.fx to create the REpresentational State Transfer (REST) query.
The variables searchLocation and searchQuery
both override the WebSearch base class definition. You cannot redefine
base class variables — they must be overridden. The variable should be
a well known attribute that all APIs use, so searchQuery is used here. The 'on replace' trigger for searchQuery replaces all spaces with the + character (denotes include).
override var searchQuery on replace {
yahooSearchQuery = searchQuery.trim().replaceAll(" ","+");
}
onPullEvent is the abstract function from WebSearch.fx that you are overriding. Again, you must override the base class variables because they cannot be redefined. onPullEvent() looks for PullParser.START_ELEMENT and PullParser.END_ELEMENT, dispatching starts to processStart() and ends to processEnd().
override function onPullEvent(event : Event) : Void {
if (event.type == PullParser.START_ELEMENT) {
processStart(event)
} else if (event.type == PullParser.END_ELEMENT) {
processEnd(event)
}
}
The javafx.data.pull.Event level is important because
XML elements can be nested. The XML root element, for example, is at
level 0. Result is a top level event whose level is 1. Thumbnail is
nested in the Result element so its event level is 2.
processEnd() is called when you encounter an PullParser.END_ELEMENT. If the tag is Result you have a complete piece of metadata. You can put result into the results Sequence, causing the results to be pushed to the wall:
if ("Result".equals(event.qname.name) and event.level == 1) {
insert result into results;
Calling Search and Getting MetaData
This section describes how search data becomes available for display.
In Wall.fx, metaData is simply bound to the WebSearch results (metaData no longer needs to be package accessible, so the package keyword isn't necessary):
var metaData : MetaData[] = bind webSearch.results;
In Main, webSearch is bound to an instance of the YahooAPI. Also in Main, a WebSearch object is created as follows:
def yahoo : WebSearch = YahooAPI {
searchQuery: "Sun Microsystems"
}
In effect, webSearch is a Yahoo instance.
Later on in Main, the default search uses the Yahoo instance:
yahoo.search();
WebSearch.fx contains the search function, which simply queues the httpRequest:
package function search() {
httpRequest.enqueue();
}
In YahooApi, processEnd() inserts metadata into the WebSearch results sequence, which is bound to metaData in Wall. In Wall, the thumbnails sequence is also bound to metaData,
but in a way that causes a new Thumbnail instance to be created as
MetaData is inserted. Thus, MetaData from the WebSearch ends up as
Thumbnails on the Wall.
insert result into results
Metadata comes from web search results and is available to populate the wall.
Try It
- The standard Sun Microsystems search happens to yield all JPEGs. To
see a different format, go to YahooAPI and set yahooSearchQuery to png
or some other supported format.
- To see how the pull parser works, print out the event in the
onPullEventcode in YahooAPI and also print out the MetaData before it is inserted in theresultssequence in YahooAPI.
- After the onPullEvent if/else-if statement, insert:
javafx.lang.FX.println("pullParser event: {event}"); - Before insert result into results, enter this line:
println("insert {result}");
- After the onPullEvent if/else-if statement, insert:
We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of repliesyour information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.
