|
A consumer, as mentioned in previous chapters, is a piece of software or a Web page that actually utilizes a Web Service. In this chapter, the consumers will be a command line Java application, a servlet, and a Java Server Page (JSP).
The command line application in this chapter is similar to the first C# application shown in Chapter 6. The first three import statements are just general Java functionality needed to read and write files along with handling URLs.
Note | Unlike C#, the file that you compile for this small application must be named after the class. In this case, the class is GetQuote so the file must be called GetQuote.java. |
All the functionality in this example occurs in the main method. The code starts off by defining the SOAP encoding style and the URL to call the Web Service. It then puts the one command line argument into the string symbol.
Then the actual call to the Web Service is created. The particular Web Service called is defined as urn:simple-stock-quote. Remember that this is the unique identifier created in the deployment descriptor shown earlier in the chapter.
The vector params is the structure into which the value of symbol is placed. Once in the vector, the SetParams method adds params to the call. Next, the response object receives the values returned by the invoke method of the call object. Finally, there is some error handling to catch errors generated by the SOAP request. If there is no error, the following snippet displays the result.
Parameter result = resp.getReturnValue (); System.out.println (result.getValue ());
The complete code example:
import java.io.*; import java.net.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.rpc.*; public class GetQuote { public static void main (String[] args) throws Exception { String encodingStyleURI = Constants.NS_URI_SOAP_ENC; //specify the URL of the Web Service URL url =new URL ("http://localhost:8080/soap/servlet/rpcrouter"); //Get the string passed in at the command line. String symbol = args[0]; System.out.print("****" + symbol + "****"); //Create the call to get a specific Web Service Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); //Create the vector that has the string value. Vector params = new Vector (); //Add the string to the vector params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); //grab the response Response resp = call.invoke ( url,"" ); //if there's a fault, catch it. //else display the result if (resp.generatedFault ()) { Fault fault = resp.getFault (); System.err.println("Generated fault: " + fault); } else { Parameter result = resp.getReturnValue (); System.out.println (result.getValue ()); } } }
The next section takes this example one step further by taking the code and making a GUI application using Java Swing™.
Creating a GUI that calls the Web Service in Java is just slightly more work that the command line application shown in the previous example. You need to create the different components that make up the GUI, and then use an event listener to listen for actions happening within the application.
The first step is to import all the proper libraries. In this case, you need to import not only the classes for the Apache SOAP but also for Swing and AWT™. Swing and AWT are the libraries within Java that allow you to create Windows applications that are cross platform. The AWT library is more operating-system-dependent than Swing, but it still supports many of the Swing objects. The rest of the imports are used in the previous examples in this chapter.
The next step is to define the class called WebSvcGui. Notice the keywords extends and implements in the class definition. Extends indicates that the class inherits either all or some of the Frame class whereas implements indicates that the class adheres to the interface defined in ActionListener.
After the class definition, the constructor for the class creates the GUI. Notice the definitions for all the frames and buttons used in the GUI. There are two JTextField definitions and this is where values are read from and written to. The action listener calls the Web Service’s static method callService(). The action listener waits for something to happen to one of the objects in the GUI, which is the valueButton object. The callService() method is static so you don’t need to instantiate another copy of the object to call the method from the constructor.
Notice that the definition for the callService method is doing more error handling than the command line application. The Swing classes require this extra error handling so the GUI knows how to react. Other than the handling this, the code to call the Web Service isn’t different than the previous example.
Then, main method creates an instance of WebSvcGui and makes it visible. Remember that all actions that occur in the GUI are taken care of by an action listnener.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.net.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.rpc.*; public class WebSvcGui extends Frame implements ActionListener { public WebSvcGui () { //name the window super("Web Service Gui Example"); setSize(400,116); //create panel and size JPanel myPanel = new JPanel(); myPanel.setLayout(new GridLayout(3,2,5,5)); JLabel symbol = new JLabel("Symbol:", JLabel.RIGHT); final JTextField symbolField = new JTextField(10); JLabel result = new JLabel("Result", JLabel.RIGHT); final JTextField resultField = new JTextField(10); //add a button JButton valueButton = new JButton("Get Value"); //create a listener for the button. It's listening //for the button to be clicked. //Call the Web Service from the listener valueButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { String symbol = symbolField.getText(); //call the static Web Service method String returned = WebSvcGui.callService(symbol); resultField.setText(returned); } }); myPanel.add(symbol); myPanel.add(symbolField); myPanel.add(result); myPanel.add(resultField); myPanel.add(valueButton); //add the panel to the gui. add(myPanel, BorderLayout.SOUTH); } public void actionPerformed(ActionEvent ae) { System.out.println(ae.getActionCommand()); } //static so we can call it without creating an WebSvcGui //object static String callService(String symbol) { String encodingStyleURI = Constants.NS_URI_SOAP_ENC; URL url = null; //set up URL to call try { url = new URL ("http://homer:8080/soap/servlet/rpcrouter"); } catch (MalformedURLException e){ System.out.println("Error:" + e); } //set up to the call to the Web Service Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; //try to call the Web Service, if successful return the //value try { resp = call.invoke ( url, "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); System.out.println("fault: " + fault ); return("-1"); } else { Parameter result = resp.getReturnValue (); return(result.getValue().toString()); } } catch (SOAPException e) { System.out.println("Error:" + e); } } public static void main(String args[]) { WebSvcGui myGui = new WebSvcGui(); myGui.setVisible(true); } }
Figure 7.7 reveals how the GUI appears running under Windows 2000.
Figure 7.7: How the WebSvcGui example appears under Windows 2000.
The previous two examples focus on creating Java applications with Web Services. In the next couple of sections, the examples focus on consumers that communicate with a Web browser.
A servlet is a chunk of Java code that executes on the server side for a request from a Web browser in a container such as Tomcat. A servlet implementation routes requests to the various Web Services within Apache SOAP.
The main difference between the following example and the previous is that a servlet has no main method. It executes as an extension of HttpServlet which the extends statement defines. In addition, there are more include files because you need all the functionality that any other servlet would normally have.
After the definition of the class SimpleStockClient, two methods must be defined: doGet and doPost. These are necessary for the servlet to understand requests from a browser.
Note | A browser can send two different types of requests to a Web site. The Post method is one way a browser sends information, usually through a form in the body of the submission. The other is a Get and this occurs when a URL contains data in the query string. |
In this example, the doGet method contains all the functionality, and then the doPost method just routes the request to doGet, as the following code snippet shows.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doGet(request, response); }
Modifying this example to do different things dependent on the type of request simply involves modifying the doPost method.
This example must handle HTML because the response from this example is sent to the browser, and you can see there are several println statements sending HTML back to the browser. This makes the servlet code hard to read and this is one of the reasons JSP was created. There are some JSP examples later in the chapter.
import java.io.*; import java.net.*; import java.text.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.rpc.*; import javax.servlet.*; import javax.servlet.http.*; //define the servlet public class SimpleStockClient extends HttpServlet { //handle a get request public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //start the HTML response response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); String title = "Get Simple Stock Quote"; out.println("<title>" + title + "</title>"); out.println("</head>"); out.println("<body bgcolor=\"white\">"); out.println("<body>"); out.println("<h1>" + title + "</h1>"); String encodingStyleURI = Constants.NS_URI_SOAP_ENC; //the java code should now resemble the //small app shown previously URL url =new URL ("http://homer:8080/soap/servlet/rpcrouter"); String symbol = "C"; out.println("****" + symbol + "****"); Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; //catch any errors. try { resp = call.invoke ( url, "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); out.println("<h2><font color=\"red\"> Generated fault: " + fault + " </font></h2>"); } else { Parameter result = resp.getReturnValue (); out.print("Result of Web Service call: "); out.println (result.getValue ()); } } catch ( SOAPException e ) { out.println(" unable to call Web Service " + e); } out.println("</body>"); out.println("</html>"); } }
Figure 7.8 displays the output of the first example servlet in Internet Explorer.
Figure 7.8: The output of the first example servlet in Internet Explorer.
The next example is a little more functional because it allows you to enter a value and submit it to the server to get a response. This is just a matter of adding some more println statements that have the appropriate HTML code for a form. Then an if statement tests to see if symbol has a value. If it does, it calls the appropriate Web Service with the value for symbol.
import java.io.*; import java.net.*; import java.text.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.rpc.*; import javax.servlet.*; import javax.servlet.http.*; public class SimpleStockClientForm extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); String title = "Get Simple Stock Quote"; out.println("<title>" + title + "</title>"); out.println("</head>"); out.println("<body bgcolor=\"white\">"); out.println("<body>"); out.println("<h1>" + title + "</h1>"); out.println("<P>"); //This begins the definition of the form so //that you can send data to the servlet. out.println("<form action=\"./SimpleStockClientForm\" method=POST>"); out.print("Please Enter a Stock Symbol:"); out.println("<input type=text size=20 name=symbol>"); out.println("<input type=submit>"); out.println("</form>"); //most of the code is similar to the last //servlet example. String encodingStyleURI = Constants.NS_URI_SOAP_ENC; URL url =new URL ("http://homer:8080/soap/servlet/rpcrouter"); String symbol = request.getParameter("symbol"); //if a value has been sent by the form go ahead //process the data. if(symbol != null && symbol.length() != 0) { Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; try { resp = call.invoke (/* router URL */ url, /* actionURI */ "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); out.println("<h2><font color=\"red\"> Generated fault: " + fault + " </font></h2>"); } else { Parameter result = resp.getReturnValue (); out.print("Result of Web Service call: "); out.println (result.getValue ()); } } catch ( SOAPException e ) { out.println(" unable to call Web Service " + e); } } out.println("</body>"); out.println("</html>"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doGet(request, response); } }
By adding the form functionality, this example becomes more realistic. Figure 7.9 shows this example in Internet Explorer.
Figure 7.9: The output of the servlet form example after entering “C” in the text box.
Servlets are very useful for delivering the output of complex Java code to a browser, but if you have a lot of HTML to deliver the coding becomes difficult. JSP pages allow you to separate coding from content, and thus may provide you a little more flexibility as a Web Services consumer.
JSP simplifies server-side Java coding because it allows you to develop separate complex Java code from the actual display of information. Servlets display HTML with a series of println statements, but JSP pages mix the HTML with the Java code.
Note | It is interesting to note that the first time JSP code executes the Java server, such as Apache Tomcat, actually generates servlet code from the template the JSP page defined. The servlet code then compiles and executes, and it sends the response back to the browser. |
JSP can use Java code, but it also implements many HTML-like tags to perform many of the same functions as the Java code. Take a look at the first JSP consumer and compare it to one of the servlet examples, and you’ll find that they are very different.
The following code example shows how different JSP code is. The import statements are replaced with <%@ page import .. %>. Instead of using println statements to display HTML, the HTML mixes in with the JSP elements. Then the Java code that calls the Web Service is the same code used in the previous examples. The difference here is that the code appears between the <% %> tags. Code that appears between these tags are referred to as scriptlets.
<%@ page import = "java.io.*, java.net.*, java.util.*, org.apache.soap.*, org.apache.soap.rpc.*, java.util.*" %> <HTML> <HEAD> <TITLE>JSP Web Services Page</TITLE> </HEAD> <BODY> <H2>JSP Web Services Page</H2> <% String encodingStyleURI = Constants.NS_URI_SOAP_ENC; URL url =new URL ("http://homer:8080/soap/servlet/rpcrouter"); String symbol = "C"; Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; try { resp = call.invoke ( url, "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); out.println("<h2><font color=\"red\">Generated fault: " + fault + " </font></h2>"); } else { Parameter result = resp.getReturnValue (); out.print("Result of Web Service call: "); out.println (result.getValue ()); } } catch ( SOAPException e ) { out.println(" unable to call Web Service " + e); } %> </BODY> </HTML>
Figure 7.10 shows Internet Explorer viewing the JSP response.
Figure 7.10: The first JSP example displaying the value from the Web Service.
The goal of JSP is to separate content from functionality. In the last example, much of the Java code still mixes in with the JSP and HTML elements. One way around having all the Java within the scriplet tags <% and %> is to use a jsp:include directive and have all the Java code appear in the separate file.
Consider the following simple JSP page.
<HTML> <HEAD> <TITLE>JSP Include Example</TITLE> </HEAD> <H2>JSP Include Example</H2> <jsp:include page="IncludeExample.jsp" flush="true"/> </HTML>
It simply includes a JSP page, which contains the following code.
<%@ page import = "java.io.*, java.net.*, java.util.*, org.apache.soap.*, org.apache.soap.rpc.*, java.util.*" %> <% String encodingStyleURI = Constants.NS_URI_SOAP_ENC; URL url =new URL ("http://homer:8080/soap/servlet/rpcrouter"); String symbol = "C"; Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; try { resp = call.invoke (url, "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); out.println("<h2><font color=\"red\">Generated fault: " + fault + " </font></h2>"); } else { Parameter result = resp.getReturnValue (); out.print("Result of Web Service call: "); out.println (result.getValue ()); } } catch ( SOAPException e ) { out.println(" unable to call Web Service " + e); }
This is the same code that appears in the first JSP example, but it appears in a separate JSP file. The output in Internet Explorer still appears the same.
Another way of separating complex Java code from the internal workings of a JSP is to put that code in a Bean. A Bean is a library of Java code that is similar to a dll in Microsoft implementations. It is accessible to JSP pages via Tomcat, and by using set and get methods the Bean and JSP page are able to communicate.
Note | Tomcat looks for Beans in the classes subdirectory of WEB-INF. Within that directory you need to create a subdirectory and place your Bean within it. The name of that directory (or an entire path from the class’s directory) needs to be defined with a package directive at the beginning of the Bean. If it isn’t in a subdirectory, Tomcat attempts to load the class file as a servlet. |
By using Beans, the JSP pages you implement become very clean because all the complex Java code is hidden. In the following JSP example, there is not scriptlet code. All the communications with Java is done with the jsp:usebean, jsp:setProperty, and the jsp:getProperty tags.
The jsp:usebean tag has a opening and closing element so that the properties of the Bean can be set. You’ll notice that the Bean only has one property set, but there could be several.
Now that the values are set, it is just a matter of using jsp:getProperty and the browser displays the value.
<HTML> <HEAD> <TITLE>Bean Example</TITLE> </HEAD> <BODY> <H2>XPlatform Bean Example</H2> <jsp:useBean > <jsp:setProperty name="getQuote" property="symbol" value="C" /> </jsp:useBean> Value:<jsp:getProperty name="getQuote" property="price"/> </BODY> </HTML>
The Bean code still has much of the same Web Service code in it that has been used throughout the examples found in this chapter, but now it appears within a get method named getPrice. By using standard get and set methods the JSP easily communicates with the Bean. Notice that there aren’t any getSymbol or setPrice methods because they are not needed for this example. This is the complete code example for the Bean.
//bean must appear in WebInf/classes/XPlatform package XPlatform; import java.net.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.rpc.*; public class getServiceBean { public String symbol = null; public String price = null; public void setSymbol(String s) { symbol = s; } public String getPrice() { String encodingStyleURI = Constants.NS_URI_SOAP_ENC; URL url = null; //set up URL to call try { url = new URL ("http://homer:8080/soap/servlet/rpcrouter"); } catch (MalformedURLException e){ System.out.println("Error:" + e); } //set up to the call to the Web Service Call call = new Call (); call.setTargetObjectURI ("urn:simple-stock-quote"); call.setMethodName ("getTestQuote"); call.setEncodingStyleURI(encodingStyleURI); Vector params = new Vector (); params.addElement (new Parameter("symbol", String.class, symbol, null)); call.setParams (params); Response resp; String returnValue = null; //try to call the Web Service, if successful return //the value try { resp = call.invoke ( url, "" ); if (resp.generatedFault ()) { Fault fault = resp.getFault (); System.out.println("fault: " + fault ); price = "-1"; } else { Parameter result = resp.getReturnValue (); price = result.getValue().toString(); } } catch (SOAPException e) { System.out.println("Error:" + e); } return(price); } }
Figure 7.11 shows the output of the JSP/Bean example
Figure 7.11: The output of the JSP/Bean example.
|