Web services in Java SE, Part 3: Creating RESTful Web services

Learn how to create RESTful-based Web services

1 2 3 Page 3
Page 3 of 3

You can omit --add-modules java.xml.ws when compiling under Java 8 or earlier.

Assuming successful compilation, run this application as follows:

java --add-modules java.xml.ws Library

Again, you can omit --add-modules java.xml.ws when compiling under Java 8 or earlier.

The Library Web service should run continuously and you should observe no output.

Defining a library client

Now that you understand how the Library Web service is implemented, you need a client to try it out. Listing 4 presents the source code to an application that shows how a client can access Library via the java.net.HttpURLConnection class.

Listing 4. A client for accessing the Library Web service

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;
import java.net.URL;

public class LibraryClient
{
   final static String LIBURI = "http://localhost:9902/library";

   public static void main(String[] args) throws Exception
   {
      String book1 = "<?xml version=\"1.0\"?>" +
                     "<book isbn=\"0201548550\" pubyear=\"1992\">" +
                     "  <title>" +
                     "    Advanced C++" +
                     "  </title>" +
                     "  <author>" +
                     "    James O. Coplien" +
                     "  </author>" +
                     "  <publisher>" +
                     "    Addison Wesley" +
                     "  </publisher>" +
                     "</book>";
      doPost(book1);
      String book2 = "<?xml version=\"1.0\"?>" +
                     "<book isbn=\"9781430210450\" pubyear=\"2008\">" +
                     "  <title>" +
                     "    Beginning Groovy and Grails" +
                     "  </title>" +
                     "  <author>" +
                     "    Christopher M. Judd" +
                     "  </author>" +
                     "  <author>" +
                     "    Joseph Faisal Nusairat" +
                     "  </author>" +
                     "  <author>" +
                     "    James Shingler" +
                     "  </author>" +
                     "  <publisher>" +
                     "    Apress" +
                     "  </publisher>" +
                     "</book>";
      doPost(book2);
      doGet(null);
      doGet("0201548550");
      doGet("9781430210450");
      String book1u = "<?xml version=\"1.0\"?>" +
                      "<book isbn=\"0201548550\" pubyear=\"1992\">" +
                      "  <title>" +
                      "    Advanced C++" +
                      "  </title>" +
                      "  <author>" +
                      "    James O. Coplien" +
                      "  </author>" +
                      "  <publisher>" +
                      "    Addison Wesley" +
                      "  </publisher>" +
                      "</book>";
      doPut(book1u);
      doGet("0201548550");
      doDelete("0201548550");
      doGet(null);
   }

   static void doDelete(String isbn) throws Exception
   {
      URL url = new URL(LIBURI + ((isbn != null) ? "?isbn=" + isbn : ""));
      HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
      httpurlc.setRequestMethod("DELETE");
      httpurlc.setDoInput(true);
      InputStreamReader isr;
      isr = new InputStreamReader(httpurlc.getInputStream());
      BufferedReader br = new BufferedReader(isr);
      StringBuilder xml = new StringBuilder();
      String line;
      while ((line = br.readLine()) != null)
         xml.append(line);
      System.out.println(xml);
      System.out.println();
   }

   static void doGet(String isbn) throws Exception
   {
      URL url = new URL(LIBURI + ((isbn != null) ? "?isbn=" + isbn : ""));
      HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
      httpurlc.setRequestMethod("GET");
      httpurlc.setDoInput(true);
      InputStreamReader isr;
      isr = new InputStreamReader(httpurlc.getInputStream());
      BufferedReader br = new BufferedReader(isr);
      StringBuilder xml = new StringBuilder();
      String line;
      while ((line = br.readLine()) != null)
         xml.append(line);
      System.out.println(xml);
      System.out.println();
   }

   static void doPost(String xml) throws Exception
   {
      URL url = new URL(LIBURI);
      HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
      httpurlc.setRequestMethod("POST");
      httpurlc.setDoOutput(true);
      httpurlc.setDoInput(true);
      httpurlc.setRequestProperty("Content-Type", "text/xml");
      OutputStream os = httpurlc.getOutputStream();
      OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
      osw.write(xml);
      osw.close();
      if (httpurlc.getResponseCode() == 200)
      {
         InputStreamReader isr;
         isr = new InputStreamReader(httpurlc.getInputStream());
         BufferedReader br = new BufferedReader(isr);
         StringBuilder sb = new StringBuilder();
         String line;
         while ((line = br.readLine()) != null)
            sb.append(line);
         System.out.println(sb.toString());
      }
      else
         System.err.println("cannot insert book: " + httpurlc.getResponseCode());
      System.out.println();
   }

   static void doPut(String xml) throws Exception
   {
      URL url = new URL(LIBURI);
      HttpURLConnection httpurlc = (HttpURLConnection) url.openConnection();
      httpurlc.setRequestMethod("PUT");
      httpurlc.setDoOutput(true);
      httpurlc.setDoInput(true);
      httpurlc.setRequestProperty("Content-Type", "text/xml");
      OutputStream os = httpurlc.getOutputStream();
      OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
      osw.write(xml);
      osw.close();
      if (httpurlc.getResponseCode() == 200)
      {
         InputStreamReader isr;
         isr = new InputStreamReader(httpurlc.getInputStream());
         BufferedReader br = new BufferedReader(isr);
         StringBuilder sb = new StringBuilder();
         String line;
         while ((line = br.readLine()) != null)
            sb.append(line);
         System.out.println(sb.toString());
      }
      else
         System.err.println("cannot update book: " + httpurlc.getResponseCode());
      System.out.println();
   }
}

LibraryClient is partitioned into a main() method and four do-prefixed methods for performing DELETE, GET, POST, and PUT operations. main() invokes each "do" method to make a request and output a response.

A "do" method first instantiates the java.net.URL class; doDelete() and doGet() attach query strings to their URI arguments when these methods are called with nonnull isbn arguments. The method then invokes URL's URLConnection openConnection() method to return a communications link between the application and URL instance as an instance of a concrete subclass of the abstract java.net.URLConnection class. This concrete subclass is HttpConnection because of the http:// prefix in the argument passed to URL's constructor.

HttpURLConnection's void setRequestMethod(String method) is then called to specify the HTTP verb, which must appear in uppercase with no whitespace. Depending on the "do" method, either void setDoInput(boolean doinput) is called with a true argument, or void setDoInput(boolean doinput) and void setDoOutput(boolean dooutput) are called with true arguments, to signify that an input stream or input and output streams are required to communicate with the Web service.

Each of doPost() and doPut() is required to set the Content-Type request header to text/xml, which it accomplishes by passing this header and MIME type to the void setRequestProperty(String key, String value) method. Forgetting to set the content type to text/xml causes the JAX-WS infrastructure to respond with an internal error response code (500).

doDelete() and doGet() read the XML from the connection's input stream and output this XML content to the standard output stream. Behind the scenes, the JAX-WS infrastructure makes the string of characters encapsulated in the StringReader instance, which is encapsulated in the StreamSource instance returned from invoke(), available on the input stream.

doPost() and doPut() access the connection's output stream and output their XML content to the stream. Behind the scenes, JAX-WS makes this content available to invoke() as an instance of a class that implements the Source interface. Assuming that the Web service responds with a success code (200), each method reads the XML reply from the connection's input stream and outputs this content to the standard output stream.

Building and running the library client

It's easy to build and run the Library client. Copy Listing 4 to a LibraryClient.java file that is stored in the current directory. Next, compile this source code as follows:

javac LibraryClient.java

Assuming successful compilation, and assuming that the Library Web service is running, run this application as follows:

java LibraryClient

You should observe the following output (slightly reformatted for clarity):

<?xml version="1.0" ?><response>book inserted</response>

<?xml version="1.0" ?><response>book inserted</response>

<?xml version="1.0" ?><isbns><isbn>9781430210450</isbn><isbn>0201548550</isbn></isbns>

<?xml version="1.0" ?><book isbn="0201548550" pubyear="1992"><title>Advanced C++</title>
   <author>James O. Coplien</author><publisher>Addison Wesley</publisher></book>

<?xml version="1.0" ?><book isbn="9781430210450" pubyear="2008"><title>Beginning Groovy and Grails</title>
   <author>Christopher M. Judd</author><author>Joseph Faisal Nusairat</author>
   <author>James Shingler</author><publisher>Apress</publisher></book>

<?xml version="1.0" ?><response>book updated</response>

<?xml version="1.0" ?><book isbn="0201548550" pubyear="1992"><title>Advanced C++</title>
   <author>James O. Coplien</author><publisher>Addison Wesley</publisher></book>

<?xml version="1.0" ?><response>book deleted</response>

<?xml version="1.0" ?><isbns><isbn>9781430210450</isbn></isbns>

Run LibraryClient a second time and you should observe that the second <response>book inserted</response> message has been replaced with cannot insert book: 400. This message is output because the library map already contains an entry whose key identifies ISBN 9781430210450.

Conclusion

This article and the first article in this four-part series on Java SE Web services referred to Java's SAAJ API. Part 4 wraps up this series by introducing you to SAAJ and a few other advanced Java SE Web services topics.

download
Get the source code for this post's applications. Created by Jeff Friesen for JavaWorld

The following software was used to develop the post's code:

  • 64-bit JDK 9ea+181

The post's code was tested on the following platform(s):

  • JVM on 64-bit Windows 10
1 2 3 Page 3
Page 3 of 3