Randy J Ray


WebService::ISBNDB::Agent - Base class for data-retrieval agents


    package WebService::ISBNDB::Agent::REST;

    use strict;
    use warnings;
    use base 'WebService::ISBNDB::Agent';


The WebService::ISBNDB::Agent class is a base class for all the classes that provide actual communication protocol support for the WebService::ISBNDB::API module. Unlike the API class, this class is not usable on its own except as a factory to create instances of classes that derive from it.

The agent classes are responsible for actually setting up the web requests to retrieve data, parsing the results of those calls, and returning the data in formats usable by the API classes.

This class (and all sub-classes of it) are based on the Class::Std inside-out objects pattern. See Class::Std for more detail.

All error conditions in the methods of this class are handled using the exception model provided by the Error module. Most errors are thrown in the form of Error::Simple exception objects. See Error for more detail.


The following methods are implemented (or in some cases, stubbed) in this base class. In some cases, the method requires that an implementation class override it in order to work. This is noted when it applies.


The constructor for this class should only ever be called to act as a factory constructor. Instantiating this class directly is not permitted, and will cause an exception to be thrown.

new($PROTO [ , $ARGS ])

Create a new object of the specified protocol and return a referent to it. If $args is passed, it is passed along to the protocol class' constructor. If the protocol referred to by $PROTO is unknown, or if $PROTO is not passed, an exception will be thrown.


The accessor methods are used to set and retrieve the attributes (instance data) stored on the object. While a few of them have special behavior, most operate as simple get or set accessors as described in Class::Std. The attributes for this class are:


The user-agent (an instance or derivative of LWP::UserAgent) used to make all the HTTP requests to the service. Unless explicitly provided by the user, this value is not initialized until the first request made to it. The next attribute allows the user to specify arguments to the constructor when the object is finally instantiated.


A hash reference of parameters to be passed to the constructor of the agent when it is created. The LWP::UserAgent constructor takes ordinary key/value pairs as arguments, not a single hash reference like classes derived from Class::Std. This value will be "flattened" when the constructor is called. Value within it, however, will not be. You must make certain that the values for any keys specified match the expected format within LWP::UserAgent.

The following accessor methods are provided by this class:


Retrieve the user-agent this object uses for HTTP communication. The creation of this object is delayed until the first request to fetch it (unless the user has explicitly set the agent, or provided an agent in the construction of the WebService::ISBNDB::Agent-derived object).


Explicitly set the user-agent for this object to use. The new value must be an instance of LWP::UserAgent, or an object of a class that is derived from that one. If it isn't, an exception will be thrown.


Get the current value of the arguments used in the creation of a user-agent instance. If none have been set, the value returned will be undef.


Set a new hash reference of arguments to be used when the user-agent is instantiated. Note that the object will instantiate the user-agent at most once, so setting this after the first call to get_useragent (or after explicitly setting the agent attribute) will have no effect. The value of $ARGS must be a hash reference, or an exception will be thrown.

Managing Protocols

For communication protocols, the only built-in protocol is:


The web services protocol known as REpresentational State Transfer, this protocol uses the URL exclusively for data-fetch operations (which, since isbndb.com is a read-only source, is all this module does). All parameters for searches and data retrieval are passed as query parameters in the URL in the request.

All protocol names are treated as upper-case strings. The values are forced to upper-case within the following methods:

add_protocol($PROTO, $CLASS)

Add a mapping of the new protocol specified by $PROTO to the class given as $CLASS. As with types, you can use this to override the class that will be instantiated for any of the built-in protocols. You cannot delete mappings for any core protocols, so if you wish to temporarily override the class, you must save the existing map value (with class_for_protocol, below) and re-assign it yourself.


Returns the class-name for the given protocol. If $PROTO is not know, then an exception (of type Error::Simple ) is thrown.


Removes the mapping for $PROTO from the internal table. You cannot remove the mapping for a core protocol (an exception will be thrown if you try to). You can only override it with another call to add_protocol.


Return the protocol this object implements, or test a given string to see if to matches the implemented protocol. If $PROTO is passed in, the method will return either a true or false value, depending on whether the value matches the protocol of this object. If $PROTO is not passed in, the return value is a string representation of the module's protocol.

The protocol-oriented methods are intended for the future, if/when isbndb.com should offer other methods besides REST. These class methods can be used by separate modules to register their protocols with this class.

As with the type-map methods in WebService::ISBNDB::API, all of the protocol-map methods may be called as static methods.

Making Requests

The role of the agent classes is to make the requests for data from the isbndb.com service, parse the body of the response and convert that data to objects from the WebService::ISBNDB::API hierarchy. To do this, this base class provides methods for making the requests, which themselves are composed of several methods restricted to the WebService::ISBNDB::Agent hierarchy.

The methods are:

request_single($OBJ, $ARGS)

Make a request of the service, returning a single object as a result. $OBJ controls the type of object returned, as well as the type of request sent. $OBJ can be one of three types of values:

WebService::ISBNDB::API-derived object

If the value is an object from one of the API classes (excluding WebService::ISBNDB::API itself), it is used not only to control the type of request, but it is also overwritten with the result of the request. It is also the return value of the call when successful.

Type name

If the value is a type recognized by the WebService::ISBNDB::API class, the class itself is retrieved via the class_for_type method. That class is used to provide the type-specific data that would otherwise be retrieved through an existing object, and it is used to instantiate the new object with the data returned by the request.

Class name

If the value is a full class name, it is first tested to see that the class is a decendant of WebService::ISBNDB::API. If so, it is used in the same way as the class derived from the previous case.

The $ARGS parameter provides the arguments used in making the specific request. It is a hash reference, whose keys and values are dependent on the specific implementation class.

If the request returns more than one value, the first one is taken and the rest are discarded. If the request returns no data, undef is returned. If there is an error of any sort, an exception is thrown.

request_all($OBJ, $ARGS)

This method sends the request, and returns all the resulting records from the service. The arguments and behavior are identical to that of request_single, except that the return value includes all records returned by the query.

Presently, the return value for a successful query is an array reference containing the objects representing the matched records. This reference may contain only one object, or even none, depending on whether the query returned any data. In future versions, the return value will be an iterator that manages the list internally, for faster response time and better memory usage.

resolve_obj($OBJ) (R)

Resolves the disposition of the argument $OBJ. This is what gets called by request_single and request_all to determine how to interpret the first argument.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

raw_request($OBJ, $ARGS) (R)

This method is what gets called to actually assemble the request from the next four methods, make the request, and return the content. In this class, the return value is a scalar reference to the content of the HTTP response. In case of error (either from information missing from the following methods or from HTTP communication failure), an exception is thrown. No parsing of the content is done by this method.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

request($OBJ, $ARGS [ , $SINGLE ]) (R)

This method must be overridden in the protocol implementation class. If the base class version is called, it will always throw an exception.

This method is expected to fetch the content from raw_request, above, and return a suitable object created from the content. The $OBJ and $ARGS parameters are the same as for request_single and request_all. The optional argument $SINGLE signifies that the request should only return a single object, not a list of all objects returned by the service.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

request_method($OBJ, $ARGS) (R)

Returns the type of HTTP request (GET or POST) that should be used in making the request, as a string. Throws an exception in case of error. The An exception is thrown in case of error (such as $OBJ not being valid). The $OBJ and $ARGS parameters fulfill the same roles as defined for request_single.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

request_uri($OBJ, $ARGS) (R)

Returns the complete URL to use in making the request, as a URI instance. An exception is thrown in case of error (such as $OBJ not being valid). The $OBJ and $ARGS parameters fulfill the same roles as defined for request_single.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

request_headers($OBJ, $ARGS) (R)

Returns an array reference of any additional headers needed for the request. The format is a series of values in key/value order. The reference may be an empty array, if no additional headers are needed. An exception is thrown if there is an error. The $OBJ and $ARGS parameters are the same as defined for request_single.

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

request_body($OBJ, $ARGS) (R)

Returns the request body needed for making the request, as a scalar reference. The scalar may be zero-length, if no data is needed in the request body. An exception is thrown if there is an error. The arguments are the same as for request_single (and all the other methods in this group).

This method is restricted to the WebService::ISBNDB::Agent class and its decendents.

All of the request-construction methods (request_uri(), request_headers(), request_body() and request_method()) return no content (or null content) from their versions in this class. It is expected that implementation classes will override those that need to have content (certainly request_uri and request_method), and leave those that are not relevant to the protocol (REST, for example, does not need a request body or additional headers).


WebService::ISBNDB::API, WebService::ISBNDB::Agent::REST, LWP::UserAgent, URI


Randy J. Ray <rjray@blackperl.com>


This module and the code within are released under the terms of the Artistic License 2.0 (http://www.opensource.org/licenses/artistic-license-2.0.php). This code may be redistributed under either the Artistic License or the GNU Lesser General Public License (LGPL) version 2.1 (http://www.opensource.org/licenses/lgpl-license.php).