< Day Day Up > |
9.9 The Web Service InterfaceThe web service interface is even simpler to code than the console interface. The web service can provide two different access points: one for searching and one for indexing. The search method needs to return its entire result-set in a serializable format so that it can be returned across the wire via SOAP. The index method doesn't have to return any value at all; it only needs to accept the starting URL from the user to get the process rolling. We must define this interface in WSDL in order for it to be available as a web service. WSDL (Web Services Description Language) files simply define the access methods and data types necessary for communicating with a given web service. WSDL files can contain much more: since we have narrowed our requirements down so much, we don't require most of those extra services. The full WSDL file looks like this: <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="SiteSearch" targetNamespace="http://www.halloway.net/SiteSearch" xmlns:tns="http://www.halloway.net/SiteSearch"> <types> <xs:schema> <xs:complexType name="queryType"> <xs:sequence> <xs:element name="seachString" type="xs:string"/> <xs:element name="threshold" type="xs:float"/> </xs:sequence> </xs:complexType> <xs:complexType name="responseType"> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:element name="url" type="xs:anyURI"/> <xs:element name="score" type="xs:float"/> </xs:sequence> </xs:complexType> <xs:element name="query" type="tns:queryType"/> <xs:element name="queryResponse" type="tns:responseType" maxOccurs="unbounded"/> <xs:element name="index" type="xs:string"/> </xs:schema> </types> <message name="queryRequest"> <part name="request" element="tns:query"/> </message> <message name="queryResponse"> <part name="response" element="tns:queryResponse"/> </message> <message name="doIndex"> <part name="request" element="tns:index"/> </message> <portType name="SiteSearch"> <operation name="searchContents"> <input message="tns:queryRequest" name="queryRequest"/> <output message="tns:queryResponse" name="queryResponse"/> </operation> </portType> <portType name="SiteSearch"> <operation name="doIndex"> <input message="tns:doIndex" name="doIndex"/> </operation> </portType> <binding name="SiteSearchSoapHttp" type="tns:SiteSearch"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="searchContents"> <soap:operation soapAction="searchContents"/> <input name="queryRequest"> <soap:body use="literal"/> </input> <output name="queryResponse"> <soap:body use="literal"/> </output> </operation> <operation name="doIndex"> <soap:operation soapAction="doIndex"/> <input name="doIndex"> <soap:body use="literal"/> </input> </operation> </binding> <service name="SiteSearchService"> <port name="SiteSearchSoap" binding="tns:SiteSearchSoapHttp"> <soap:address location="http://localhost:8080/axis/services/SiteSearchSoap"/> </port> </service> </definitions> The <types> section defines any datatypes that need to be exchanged by clients and servers; the <queryType> wraps the two inputs into a search query (search term and threshold for limiting results based on relative rank). <queryResponse> defines the sequence of individual results of a search operation. After the datatypes, the individual messages are defined. Messages represent inputs to and outputs from individual web service endpoints. Three are defined here: <queryRequest> and <queryResponse> are the input message and output results of the search service, and <doIndex> is the input message to a return-less index service access point. After all these definitions, map the individual messages and datatypes to the methods of the implementation class. Note that the mapping of doIndex includes an input type but no output message. The implementation is even simpler; it only defines methods that match the WSDL (one for searchContents and one for doIndex): public ResponseType[] searchContents(QueryType request) throws RemoteException { try { ConfigBean config = new ConfigBean( ); ServletContext context = getServletContext( ); if (context == null) { throw new Error("null servlet context"); } QueryBean query = new QueryBean(config.getCurIndexPath( ), request.getSeachString( )); query.execute( ); HitBean[] fullResults = query.getResults( ); ArrayList result = new ArrayList( ); for (int n=0; n<fullResults.length; n++) { HitBean hit = fullResults[n]; if (hit.getScore( ) >= request.getThreshold( )) { ResponseType rt = new ResponseType( ); rt.setScore(hit.getScore( )); rt.setUrl(new URI(hit.getUrl( ))); result.add(rt); } } return (ResponseType[]) result.toArray(new ResponseType[result.size( )]); } catch (Exception e) { getServletContext( ).log(e, "fail"); throw new AxisFault(e.getMessage( )); } } public void doIndex(String indexUrl) { try { ConfigBean config = new ConfigBean( ); String nextIndex; try { nextIndex = config.getNextIndexPath( ); } catch(Exception ex) { return; } IndexLinks lts = new IndexLinks(nextIndex, config.getMaxLinks( ), config.getSkippedLinksFile( )); lts.initFollowPrefixesFromSystemProperties( ); lts.initAvoidPrefixesFromSystemProperties( ); lts.setInitialLink(indexUrl); config.flipIndexPath( ); } catch(Exception e) { //System.out.print(e.getStackTrace( )); } } These methods are similar to the methods defined in the console application, with minor differences in the types of exceptions thrown, as well as the creation of a the return value for searchContents. 9.9.1 Principles in Action
|
< Day Day Up > |