Using Web Services

   

When a web application needs to get information from an external source, it typically uses a remote procedure call mechanism. In recent years, web services have emerged as a popular technology for this purpose.

Technically, a web service has two components:

  • A server that can be accessed with the SOAP (Simple Object Access Protocol) transport protocol

  • A description of the service in the WSDL (Web Service Description Language) format

Fortunately, you can use web services, even if you know nothing at all about SOAP and just a little about WSDL.

To make web services easy to understand, we look at a concrete example: the Amazon Web Services, described at http://www.amazon.com/gp/aws/landing.html. The Amazon Web Services allow a programmer to interact with the Amazon system for a wide variety of purposes. For example, you can get listings of all books with a given author or title, or you can fill shopping carts and place orders. Amazon makes these services available for use by companies that want to sell items to their customers, using the Amazon system as a fulfillment backend. To run our example program, you will need to sign up with Amazon and get a free developer token that lets you connect to the service.

You also need to download and install the Java Web Services Developer Pack (JWSDP) from http://java.sun.com/webservices/webservicespack.html.

NOTE

graphics/note_icon.gif

You may already use the JWSDP for the examples in this book it bundles JSF, Tomcat, and Ant. If so, there is no need to reinstall it. If you use standalone versions of JSF, Tomcat, and Ant, you can install the JWSDP and continue to use the standalone versions to run this example.


A primary attraction of web services is that they are language-neutral. We will access the Amazon Web Services by using the Java programming language, but other developers can equally well use C++ or Visual Basic. The WSDL descriptor describes the services in a language-independent manner. For example, the WSDL for the Amazon Web Services (located at http://soap.amazon.com/schemas3/AmazonWebServices.wsdl) describes an AuthorSearchRequest operation as follows:

 

 <operation name="AuthorSearchRequest">    <input message="typens:AuthorSearchRequest"/>    <output message="typens:AuthorSearchResponse"/> </operation> ... <message name="AuthorSearchRequest">    <part name="AuthorSearchRequest" type="typens:AuthorRequest"/> </message> <message name="AuthorSearchResponse">    <part name="return" type="typens:ProductInfo"/> </message> 

Elsewhere, it defines the data types. Here is the definition of AuthorRequest:

 

 <xsd:complexType name="AuthorRequest">    <xsd:all>       <xsd:element name="author" type="xsd:string"/>       <xsd:element name="page" type="xsd:string"/>       <xsd:element name="mode" type="xsd:string"/>       <xsd:element name="tag" type="xsd:string"/>       <xsd:element name="type" type="xsd:string"/>       <xsd:element name="devtag" type="xsd:string"/>       <xsd:element name="sort" type="xsd:string" minOccurs="0"/>       <xsd:element name="locale" type="xsd:string" minOccurs="0"/>       <xsd:element name="keywords" type="xsd:string" minOccurs="0"/>       <xsd:element name="price" type="xsd:string" minOccurs="0"/>    </xsd:all> </xsd:complexType> 

When this description is translated into the Java programming language, the AuthorRequest type becomes a class.

 

 public class AuthorRequest {    public AuthorRequest(String author, String page, String mode, String tag,       String type, String devtag, String sort, String locale, String keyword,          String price) { ... }    public String getAuthor() { ... }    public void setAuthor(String newValue) { ... }    public String getPage() { ... }    public void setPage(String) { ... }    ... } 

To call the search service, construct an AuthorRequest object and call the authorSearchRequest of a "port" object.

 

 AmazonSearchPort asp = (AmazonSearchPort)    (new AmazonSearchService_Impl().getAmazonSearchPort()); AuthorRequest req = new AuthorRequest(name,    "1", "books", "", "lite", "", token, "", "", ""); ProductInfo pinfo = asp.authorSearchRequest(req); 

The port object translates the Java object into a SOAP message, passes it to the Amazon server, and translates the returned message into a ProductInfo object. The port classes are automatically generated.

NOTE

graphics/note_icon.gif

The WSDL file does not specify what the service does. It only specifies the parameter and return types.


To generate the required Java classes, place into an empty directory a config.xml file with the following contents:

 

 <?xml version="1.0" encoding="UTF-8"?> <configuration    xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">       <wsdl          location="http://soap.amazon.com/schemas3/AmazonWebServices.wsdl"          packageName="com.corejsf.amazon" /> </configuration> 

Then run these commands:

 

 jwsdp/jaxrpc/bin/wscompile.sh -import config.xml jwsdp/jaxrpc/bin/wscompile.sh -gen config.xml jar cvf aws.jar . 

Here, jwsdp is the directory into which you installed the JWSDP, such as /usr/local/jwsdp-1.3 or c:\jwsdp-1.3. (As usual, Windows users need to use \ instead of /.)

Place the resulting JAR file into the WEB-INF/lib directory of any JSF application that uses the Amazon Web Services.

NOTE

graphics/note_icon.gif

If you like, you can also run the wscompile program from inside Ant. See the jwsdp/jaxrpc/samples/HelloWorld directory for an example.


Our sample application is straightforward. The user specifies an author name and clicks the "Search" button (see Figure 10-19).

Figure 10-19. Searching for Books with a Given Author

graphics/10fig19.jpg


We simply show the first page of the response in a data table (see Figure 10-20). This shows that the web service is successful. We leave it as the proverbial exercise for the reader to extend the functionality of the application.

Figure 10-20. A Search Result

graphics/10fig20.jpg


Figure 10-21 shows the directory structure of the application. Note the JAR file in the WEB-INF/lib directory.

Figure 10-21. Directory Structure of the Web Service Test Application

graphics/10fig21.jpg


You need different build files for this application since a large number of additional libraries are required for the SOAP calls see Listings 10-27 and 10-28. As always, you need to customize build.properties. If you use the JWSDP instead of the standalone Tomcat server, you don't need to include the jwsdp-shared files in the copy target.

The bean class in Listing 10-29 contains the call to the web service. The call returns an object of type ProductInfo. We stash away the Details array contained in the returned object.

Note how the developer token is set in faces-config.xml (Listing 10-30). Be sure to supply your own ID in that file.

Listings 10-31 through 10-33 show the JSF pages. The result.jsp page contains a data table that displays information from the Details array that was returned by the search service.

Finally, Listing 10-34 is the message bundle.

Listing 10-27. amazon/build.xml
  1. <project default="install">  2.  3.    <property file="build.properties"/>  4.    <property name="appdir" value="${basedir}"/>  5.    <property name="builddir" value="${appdir}/build"/>  6.    <property name="appname" value="amazon"/>  7.    <property name="warfile" value="${builddir}/${appname}.war"/>  8.  9.   <path > 10.       <pathelement location="${servlet.api.jar}"/> 11.       <pathelement location="${jsp.api.jar}"/> 12.       <fileset dir="${builddir}/WEB-INF/lib"> 13.          <include name="*.jar"/> 14.       </fileset> 15.    </path> 16. 17.    <target name="init"> 18.       <tstamp/> 19.    </target> 20. 21.    <target name="copy" depends="init" 22.       description="Copy files to build directory."> 23.       <mkdir dir="${builddir}"/> 24.       <copy todir="${builddir}"> 25.          <fileset dir="${appdir}"> 26.             <exclude name="**/*.java"/> 27.             <exclude name="build/**"/> 28.             <!-- for Eclipse --> 29.             <exclude name="bin/**"/> 30.             <exclude name=".*"/> 31.          </fileset> 32.       </copy> 33.       <copy todir="${builddir}/WEB-INF/lib"> 34.          <fileset dir="${jsf.lib.dir}" includes="${jsf.libs}"/> 35.          <fileset dir="${jstl.lib.dir}" includes="${jstl.libs}"/> 36.          <fileset dir="${commons.lib.dir}" includes="${commons.libs}"/> 37.          <fileset dir="${jaxrpc.lib.dir}" includes="*.jar"/> 38.          <fileset dir="${saaj.lib.dir}" includes="*.jar"/> 39.          <fileset dir="${jwsdp-shared.lib.dir}" includes="${jwsdp-shared.libs}"/> 40.       </copy> 41.    </target> 42. 43.    <target name="compile" depends="copy" 44.       description="Compile source files."> 45.       <javac 46.          srcdir="${appdir}/WEB-INF/classes" 47.          destdir="${builddir}/WEB-INF/classes" 48.          debug="true" 49.          deprecation="true"> 50.          <include name="**/*.java"/> 51.          <classpath ref/> 52.       </javac> 53.    </target> 54. 55.    <target name="war" depends="compile" 56.       description="Build WAR file."> 57.       <delete file="${warfile}"/> 58.       <jar jarfile="${warfile}" basedir="${builddir}"/> 59.    </target> 60. 61.    <target name="install" depends="war" 62.       description="Deploy web application."> 63.       <copy file="${warfile}" todir="${tomcat.dir}/webapps"/> 64.    </target> 65. 66. </project> 

Listing 10-28. amazon/build.properties

  1. jsf.dir=/usr/local/jsf-1_0  2. tomcat.dir=/usr/local/jakarta-tomcat-5.0.19  3.  4. username=me  5. password=secret  6. manager.url=http://localhost:8080/manager  7.  8. servlet.api.jar=${tomcat.dir}/common/lib/servlet-api.jar  9. jsp.api.jar=${tomcat.dir}/common/lib/jsp-api.jar 10. 11. jsf.lib.dir=${jsf.dir}/lib 12. jstl.lib.dir=${tomcat.dir}/webapps/jsp-examples/WEB-INF/lib 13. commons.lib.dir=${tomcat.dir}/server/lib 14. 15. jsf.libs=jsf-api.jar,jsf-impl.jar 16. jstl.libs=jstl.jar,standard.jar 17. commons.libs=commons-beanutils.jar,commons-digester.jar 18. 19. jwsdp.dir=/home/apps/jwsdp-1.3 20. jaxp.lib.dir=${jwsdp.dir}/jaxp/lib 21. jaxrpc.lib.dir=${jwsdp.dir}/jaxrpc/lib 22. saaj.lib.dir=${jwsdp.dir}/saaj/lib 23. jwsdp-shared.lib.dir=${jwsdp.dir}/jwsdp-shared/lib 24. jaxp.api.jar=${jaxp.lib.dir}/jaxp-api.jar 25. jwsdp-shared.libs=jax-qname.jar,namespace.jar,activation.jar,jaas.jar,mail.jar,xsdlib graphics/ccc.gif.jar,providerutil.jar 

Listing 10-29. amazon/WEB-INF/classes/com/corejsf/AmazonSearchBean.java
  1. package com.corejsf;  2.  3. import com.corejsf.amazon.AmazonSearchPort;  4. import com.corejsf.amazon.AmazonSearchService_Impl;  5. import com.corejsf.amazon.AuthorRequest;  6. import com.corejsf.amazon.Details;  7. import com.corejsf.amazon.ProductInfo;  8.  9. public class AuthorSearchBean { 10.    private String name; 11.    private String type; 12.    private Details[] details; 13.    private String token; 14. 15.    public String getName() { return name; } 16.    public void setName(String newValue) { name = newValue; } 17. 18.    public void setToken(String newValue) { token = newValue; } 19. 20.    public String search() { 21.       try{ 22.          AmazonSearchPort asp = (AmazonSearchPort) 23.             (new AmazonSearchService_Impl().getAmazonSearchPort()); 24. 25.          AuthorRequest req = new AuthorRequest(name, 26.              "1", "books", "", "lite", "", token, "", "", ""); 27.          ProductInfo pinfo = asp.authorSearchRequest(req); 28.          details = pinfo.getDetails(); 29.          return "success"; 30.        } catch(Exception e) { 31.           e.printStackTrace(); 32.           return "failure"; 33.        } 34.    } 35. 36.    public Details[] getDetails() { return details; } 37. } 

Listing 10-30. amazon/WEB-INF/faces-config.xml
  1. <?xml version="1.0"?>  2.  3. <!DOCTYPE faces-config PUBLIC  4.   "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"  5.   "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">  6.  7. <faces-config>  8.  9.     <navigation-rule> 10.       <from-view-id>/index.jsp</from-view-id> 11.       <navigation-case> 12.          <from-outcome>success</from-outcome> 13.          <to-view-id>/result.jsp</to-view-id> 14.       </navigation-case> 15.       <navigation-case> 16.          <from-outcome>failure</from-outcome> 17.          <to-view-id>/error.jsp</to-view-id> 18.       </navigation-case> 19.    </navigation-rule> 20.    <navigation-rule> 21.       <from-view-id>/result.jsp</from-view-id> 22.       <navigation-case> 23.          <from-outcome>back</from-outcome> 24.          <to-view-id>/index.jsp</to-view-id> 25.       </navigation-case> 26.    </navigation-rule> 27.    <navigation-rule> 28.       <from-view-id>/error.jsp</from-view-id> 29.       <navigation-case> 30.          <from-outcome>continue</from-outcome> 31.          <to-view-id>/index.jsp</to-view-id> 32.       </navigation-case> 33.    </navigation-rule> 34. 35.    <managed-bean> 36.       <managed-bean-name>authorSearch</managed-bean-name> 37.       <managed-bean-class>com.corejsf.AuthorSearchBean</managed-bean-class> 38.       <managed-bean-scope>session</managed-bean-scope> 39.       <managed-property> 40.          <property-name>token</property-name> 41.          <value>Your token goes here</value> 42.       </managed-property> 43.    </managed-bean> 44. 45. </faces-config> 

Listing 10-31. amazon/index.jsp
  1. <html>  2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>  3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>  4.    <f:view>  5.       <head>  6.          <f:loadBundle basename="com.corejsf.messages" var="msgs"/>  7.          <link href="styles.css" rel="stylesheet" type="text/css"/>  8.          <title><h:outputText value="#{msgs.title}"/></title>  9.       </head> 10.       <body> 11.          <h:form> 12.             <h1><h:outputText value="#{msgs.authorSearch}"/></h1> 13.             <h:outputText value="#{msgs.author}"/> 14.             <h:inputText value="#{authorSearch.name}"/> 15.             <h:commandButton value="#{msgs.search}" 16.                action="#{authorSearch.search}"/> 17.          </h:form> 18.       </body> 19.    </f:view> 20. </html> 

Listing 10-32. amazon/result.jsp
  1.<html>  2.   <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>  3.   <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>  4.   <f:view>  5.      <head>  6.         <f:loadBundle basename="com.corejsf.messages" var="msgs"/>  7.         <title><h:outputText value="#{msgs.title}"/></title>  8.      </head>  9.      <body> 10.         <h:form> 11.            <h1><h:outputText value="#{msgs.searchResult}"/></h1> 12.            <h:dataTable value="#{authorSearch.details}" var="detail" 13.               border="1"> 14.               <h:column> 15.                  <f:facet name="header"> 16.                     <h:outputText value="#{msgs.author1}"/>  1.  2.                   </f:facet>  3.                   <h:outputText value="#{detail.authors[0]}"/>  4.                </h:column>  5.                <h:column>  6.                   <f:facet name="header">  7.                      <h:outputText value="#{msgs.title}"/>  8.                   </f:facet>  9.                   <h:outputText value="#{detail.productName}"/> 10.                </h:column> 11.                <h:column> 12.                   <f:facet name="header"> 13.                      <h:outputText value="#{msgs.publisher}"/> 14.                   </f:facet> 15.                   <h:outputText value="#{detail.manufacturer}"/> 16.                </h:column> 17.                <h:column> 18.                  <f:facet name="header"> 19.                      <h:outputText value="#{msgs.pubdate}"/> 20.                   </f:facet> 21.                   <h:outputText value="#{detail.releaseDate}"/> 22.                </h:column> 23.             </h:dataTable> 24.             <h:commandButton value="#{msgs.back}" action="back"/> 25.          </h:form> 26.       </body> 27.    </f:view> 28. </html> 

Listing 10-33. amazon/error.jsp
  1. <html>  2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>  3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>  4.    <f:view>  5.       <head>  6.          <f:loadBundle basename="com.corejsf.messages" var="msgs"/>  7.          <title><h:outputText value="#{msgs.title}"/></title>  8.       </head>  9.       <body> 10.          <h:form> 11.             <h1><h:outputText value="#{msgs.internalError}"/></h1> 12.             <p><h:outputText value="#{msgs.internalError_detail}"/></p> 13.             <p> 14.                <h:commandButton value="#{msgs.continue}" action="login"/> 15.             </p> 16.          </h:form> 17.       </body> 18.    </f:view> 19. </html> 

Listing 10-34. amazon/WEB-INF/classes/com/corejsf/messages.properties
  1. title=A Faces Application that Invokes a Web Service  2. authorSearch=Author Search at Amazon  3. author=Author  4. format=Format  5. search=Search  6. searchResult=Search Result  7. internalError=Internal Error  8. internalError_detail=To our chagrin, an internal error has occurred. \  9.    Please report this problem to our technical staff. 10. continue=Continue 11. author1=First Author 12. title=Title 13. publisher=Publisher 14. pubdate=Publication Date 15. back=Back 

You have now seen how your web applications can connect to external services, such as databases, directories, and web services. Here are some general considerations to keep in mind.

  • Libraries are placed either in the WEB-INF/lib directory of the web application or in the common/lib directory of the servlet container. You would do the latter only for libraries that are used by many applications, such as JDBC drivers.

  • Servlet containers typically provide common services for database connection pooling, authentication realms, and so on. JNDI provides a convenient mechanism for locating the classes that are needed to access these services.

  • Configuration parameters can be placed into faces-config.xml or web.xml. The former is more appropriate for parameters that are intrinsic to the web application; the latter should be used for parameters that are determined at deployment time.



core JavaServer Faces
Core JavaServer Faces
ISBN: 0131463055
EAN: 2147483647
Year: 2003
Pages: 121

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net