{"id":2158,"date":"2017-04-09T13:27:40","date_gmt":"2017-04-09T13:27:40","guid":{"rendered":"http:\/\/blog.paranoidprofessor.com\/?p=2158"},"modified":"2017-04-28T18:52:27","modified_gmt":"2017-04-28T18:52:27","slug":"restful-services-in-java-client-and-server","status":"publish","type":"post","link":"https:\/\/blog.paranoidprofessor.com\/index.php\/2017\/04\/09\/restful-services-in-java-client-and-server\/","title":{"rendered":"Restful services in Java &#8211; client and server"},"content":{"rendered":"<p>My previous restful <a href=\"http:\/\/blog.paranoidprofessor.com\/index.php\/2017\/03\/30\/restful-services-in-java-simple-client-example\/\" target=\"_blank\">client example <\/a>and <a href=\"http:\/\/blog.paranoidprofessor.com\/index.php\/2017\/03\/23\/restful-services-in-java-simple-server-example\/\" target=\"_blank\">server example <\/a>were perfect, well, not exactly. \u00a0They worked but they pretty much assuming a perfect world. \u00a0That is to say that there is never a communication error or a server error.<\/p>\n<p>This small example will return one of the magazine objects. \u00a0Depending how you call it, it will return either the object directly or the xml that you can marshal into the object itself.<\/p>\n<pre>\/\/ example 2\/3 setup\r\nClientConfig config1 = new ClientConfig();\r\nClient client1       = ClientBuilder.newClient(config1);\r\nWebTarget target1    = client1.target(uribase);\r\n\t\t\r\n\/\/ example 3\r\nmagazine xmlobj = target1.path(\"\/Communicate\/hello\").request().accept(MediaType.APPLICATION_XML).get(magazine.class);\r\nshowMagazine(\"pure xml object\", xmlobj);\r\n<\/pre>\n<p>However, it should be pretty obvious in the previous simple server code that if for any reason the server cannot find the data it cannot really communicate that fact back to the client. \u00a0Well, it cannot if you are returning magazine objects or general strings.<\/p>\n<h2>New and better server<\/h2>\n<p>The solution is to return a response record. \u00a0This record will contain both the error code as well as our object. \u00a0The code is actually not too different from from the previous example but there are some\u00a0major differences.<\/p>\n<p>The first is that we are no longer returning either xml(string) nor magazine objects but rather we are\u00a0returning Response objects. \u00a0 \u00a0This allows us to set the status to one of the values that matches the result of the call.<\/p>\n<pre>Response.Status.OK<\/pre>\n<p>It is possible to use one of the predefined values such as Response.Status.OK but it is just as acceptable to put the actual value of 200.<\/p>\n<p>Here is a list of\u00a0the values that are defined for us to use.<\/p>\n<table class=\"w3-table-all\">\n<tbody>\n<tr>\n<th>Response codes<\/th>\n<th>Description<\/th>\n<\/tr>\n<tr>\n<td>OK<\/td>\n<td>200<\/td>\n<\/tr>\n<tr>\n<td>CREATED<\/td>\n<td>201<\/td>\n<\/tr>\n<tr>\n<td>ACCEPTED<\/td>\n<td>202<\/td>\n<\/tr>\n<tr>\n<td>NO_CONTENT<\/td>\n<td>204<\/td>\n<\/tr>\n<tr>\n<td>MOVED_PERMANENTLY<\/td>\n<td>301<\/td>\n<\/tr>\n<tr>\n<td>SEE_OTHER<\/td>\n<td>303<\/td>\n<\/tr>\n<tr>\n<td>NOT_MODIFIED<\/td>\n<td>304<\/td>\n<\/tr>\n<tr>\n<td>TEMPORARY_REDIRECT<\/td>\n<td>307<\/td>\n<\/tr>\n<tr>\n<td>BAD_REQUEST<\/td>\n<td>400<\/td>\n<\/tr>\n<tr>\n<td>UNAUTHORIZED<\/td>\n<td>401<\/td>\n<\/tr>\n<tr>\n<td>FORBIDDEN<\/td>\n<td>403<\/td>\n<\/tr>\n<tr>\n<td>NOT_FOUND<\/td>\n<td>404<\/td>\n<\/tr>\n<tr>\n<td>NOT_ACCEPTABLE<\/td>\n<td>406<\/td>\n<\/tr>\n<tr>\n<td>CONFLICT<\/td>\n<td>409<\/td>\n<\/tr>\n<tr>\n<td>GONE<\/td>\n<td>410<\/td>\n<\/tr>\n<tr>\n<td>PRECONDITION_FAILED<\/td>\n<td>412<\/td>\n<\/tr>\n<tr>\n<td>UNSUPPORTED_MEDIA_TYPE<\/td>\n<td>415<\/td>\n<\/tr>\n<tr>\n<td>INTERNAL_SERVER_ERROR<\/td>\n<td>500<\/td>\n<\/tr>\n<tr>\n<td>SERVICE_UNAVAILABLE<\/td>\n<td>503<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The code in this &#8220;server code&#8221; is not much larger than the original code.<\/p>\n<p>Another one of the changes is that the URI is returned as part of the response object. \u00a0This URI should point to the the data in the server. \u00a0This is especially interesting if a new object is created on your server. \u00a0The server then will return the URI to reference that object.<\/p>\n<p>The final difference is that we pass back our object as part of the Response object. \u00a0In the below code this is done as a simple string but it could just as easily be a your own Java object.<\/p>\n<pre>package com.acmesoft;\r\n\r\nimport java.net.URI;\r\nimport java.net.URISyntaxException;\r\n\r\nimport javax.ws.rs.Consumes;\r\nimport javax.ws.rs.GET;\r\nimport javax.ws.rs.POST;\r\nimport javax.ws.rs.Path;\r\nimport javax.ws.rs.PathParam;\r\nimport javax.ws.rs.Produces;\r\nimport javax.ws.rs.core.Context;\r\nimport javax.ws.rs.core.MediaType;\r\nimport javax.ws.rs.core.Response;\r\nimport javax.ws.rs.core.UriInfo;\r\n\r\n@Path(\"\/Communicate\")\r\npublic class HelloWorldEx {\r\n\r\n\t\/*  \r\n\t * http:\/\/192.168.178.70:8080\/SecondRestful\/Communicate\/mag\r\n\t *\/\t@GET\r\n\t@Path(\"\/mag\")\r\n\t@Produces( {MediaType.APPLICATION_XML})\r\n\tpublic Response sayHelloXml(@Context UriInfo ui) throws URISyntaxException\r\n\t{\r\n\t\tString retval =  \"\" +\r\n\t\t\t\t\"2016\" +\r\n\t\t\t\t\"6\" +\r\n\t\t\t\t\"Economist\" +\r\n\t\t\t\t\"9.99\" +\r\n\t\t\t\t\"\";\r\n\t\tString path = ui.getAbsolutePath().toString() ;\r\n\t\tURI uri = new URI(path);\r\n\r\n\t\treturn Response.created(uri).contentLocation(uri).status(Response.Status.OK).entity(retval).build();\r\n\t}\r\n\r\n\t\/*  \r\n\t * http:\/\/192.168.178.70:8080\/SecondRestful\/Communicate\/mag\r\n\t *\/\r\n\t@GET\r\n\t@Path(\"\/mag\")\r\n\t@Produces( {MediaType.APPLICATION_JSON})\r\n\tpublic Response sayHelloJSON(@Context UriInfo ui) throws URISyntaxException\r\n\t{\r\n\t\tString retval =  \"{ \\\"magazine\\\": {\\\"year\\\":2016,\\\"month\\\":6,\\\"title\\\":\\\"Economist\\\",\\\"price\\\":9.99} }\";\r\n\t\t\r\n\t\tString path = ui.getAbsolutePath().toString() ;\r\n\t\tURI uri = new URI(path);\r\n\r\n\t\treturn Response.created(uri).contentLocation(uri).status(Response.Status.OK).entity(retval).build();\r\n\t}\r\n\r\n\t\/*  \r\n\t * http:\/\/192.168.178.70:8080\/SecondRestful\/Communicate\/oucha_bunga\r\n\t *\/\r\n\t@Path(\"{c}\")\r\n\t@GET\r\n\t@Produces( {MediaType.APPLICATION_XML})\r\n\tpublic Response complexURI(@Context UriInfo ui, @PathParam(\"c\") String msg) throws URISyntaxException\r\n\t{\r\n\t\tString mymsg = \"Thinkin about \" + msg;\r\n\t\tString xmlStr = \"\" + mymsg + \"\";\r\n\r\n\t\t\/\/ this is a really clever way to get the URI but\r\n\t\t\/\/ if you pass in a string, it will throw an error.\r\n\t\t\/\/ and it all comes down to the URI that is added to the\r\n\t\t\/\/ response object (below)\r\n\t\tString path = ui.getAbsolutePath().toString() ;\r\n\t\tURI uri = new URI(path);\r\n\r\n\t\treturn Response.created(uri).contentLocation(uri).status(Response.Status.OK).entity(xmlStr).build();\r\n\t}\r\n}\r\n<\/pre>\n<p>The final method in this server example is is not actually called by my client but it is a clever example of a URI that can accept anything, in this case a string, and then that string can be used in some clever manner.<\/p>\n<h2>New Client<\/h2>\n<p>The new client changes is actually quite similar to the new server changes. \u00a0As a matter of fact, the client changes are actually almost transparent. There is just a few small changes to accommodate\u00a0the retrieving Response objects instead of strings or other java objects.<\/p>\n<p>Once the Response object has been retrieved simply call the status method to find out the status returned from the server. The range of success codes is 200-299.<\/p>\n<pre>\tif (response.getStatus() == 200)\r\n\t{\r\n\t\txmlAnswer = response.readEntity(String.class);\r\n\t\tSystem.out.println(xmlAnswer);\r\n\t\tmagazine converted = convertXmlToMag(xmlAnswer);\r\n\t\tshowMagazine(\"xml text data\", converted);\t\t\t\r\n\t}\r\n\tresponse.close();<\/pre>\n<p>If the call was successful then simply call the readEntity method on the Response object. \u00a0Simply pass in the class of the object that you are trying to read out. \u00a0The object is retrieved just like magic.<\/p>\n<p>In order to keep control on the system resources close the Response and the Client objects, failing to do so will cause your program to fail eventually due to resource issues.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.acmesoft;\r\n\r\nimport java.io.StringReader;\r\nimport java.net.URI;\r\n\r\nimport javax.ws.rs.client.Client;\r\nimport javax.ws.rs.client.ClientBuilder;\r\nimport javax.ws.rs.client.WebTarget;\r\nimport javax.ws.rs.core.MediaType;\r\nimport javax.ws.rs.core.Response;\r\nimport javax.ws.rs.core.UriBuilder;\r\nimport javax.xml.bind.JAXBContext;\r\nimport javax.xml.bind.JAXBException;\r\nimport javax.xml.bind.Unmarshaller;\r\n\r\nimport org.glassfish.jersey.client.ClientConfig;\r\n\r\npublic class TestClient \r\n{\r\n\tString uribase = &quot;http:\/\/192.168.178.70:8080\/SecondRestful&quot;;\r\n\r\n\tpublic void showMagazine(String desc, magazine value)\r\n\t{\r\n\t\tSystem.out.println(&quot;\\n&quot; + desc );\r\n\t\tSystem.out.println(&quot;year &quot;  + value.getYear());\r\n\t\tSystem.out.println(&quot;month &quot; + value.getMonth());\r\n\t\tSystem.out.println(&quot;price &quot; + value.getPrice());\r\n\t\tSystem.out.println(&quot;title &quot; + value.getTitle());\r\n\t}\r\n\t\r\n\tpublic magazine convertXmlToMag(String xmlstring)\r\n\t{\r\n\t\tmagazine converted = null;\r\n\t\tJAXBContext jc = null;\r\n\t\ttry {\r\n\t\t\tjc = JAXBContext.newInstance(magazine.class);\r\n\t\t\tUnmarshaller unmarshaller = jc.createUnmarshaller();\r\n\t\t\tStringReader reader = new StringReader(xmlstring);\r\n\t\t\tconverted = (magazine) unmarshaller.unmarshal(reader);\t\r\n\t\t}\r\n\t\tcatch (JAXBException ex)\r\n\t\t{\r\n\t\t\tex.printStackTrace();\r\n\t\t}\r\n\t\treturn converted;\r\n\t}\r\n\t\r\n\tpublic WebTarget restConnect(String targetUrl)\r\n\t{\r\n\t\tURI uri = UriBuilder.fromUri(targetUrl).build();\r\n\t\tClientConfig config = new ClientConfig();\r\n\t\tClient client = ClientBuilder.newClient(config);\r\n\t\tWebTarget target = client.target(uri);\r\n\t\treturn target;\r\n\t}\r\n\t\r\n\tpublic TestClient()\r\n\t{\r\n\t\tClientConfig config = new ClientConfig();\r\n\t\tClient client       = ClientBuilder.newClient(config);\r\n\t\tWebTarget target    = client.target(uribase);\r\n\r\n\t\tResponse response  = target.path(&quot;\/&quot;).path(&quot;Communicate&quot;).path(&quot;\/mag&quot;).request().accept(MediaType.APPLICATION_XML).get(Response.class);\r\n\t\tSystem.out.println(response.getStatus());\r\n\t\tString xmlAnswer = &quot;&quot;;\r\n\t\tif (response.getStatus() == 200)\r\n\t\t{\r\n\t\t\txmlAnswer = response.readEntity(String.class);\r\n\t\t\tSystem.out.println(xmlAnswer);\r\n\t\t\tmagazine converted = convertXmlToMag(xmlAnswer);\r\n\t\t\tshowMagazine(&quot;xml text data&quot;, converted);\t\t\t\r\n\t\t}\r\n\t\tresponse.close();\r\n\r\n\t\tresponse = target.path(&quot;\/Communicate\/mag&quot;).request().accept(MediaType.APPLICATION_XML).get(Response.class);\r\n\t\tif (response.getStatus() == 200)\r\n\t\t{\r\n\t\t\tmagazine xmlobj = response.readEntity(magazine.class);\r\n\t\t\tshowMagazine(&quot;pure xml object&quot;, xmlobj);\r\n\t\t}\r\n\t\tresponse.close();\r\n\t\tclient.close();\r\n\t}\r\n\t\r\n\tpublic static void main(String[] args) \r\n\t{\r\n\t\tnew TestClient();\r\n\t}\r\n}\r\n<\/pre>\n<p>The output is not terribly interesting, it is just a few print statements in order to prove that the client can retrieve the data.<\/p>\n<pre><span style=\"font-size: 12px; white-space: normal;\">\u00a0<\/span>200\r\n&lt;Magazine&gt;&lt;Year&gt;2016&lt;\/Year&gt;&lt;Month&gt;6&lt;\/Month&gt;&lt;Title&gt;Economist&lt;\/Title&gt;&lt;Price&gt;9.99&lt;\/Price&gt;&lt;\/Magazine&gt;\r\n\r\nxml text data\r\nyear 2016\r\nmonth 6\r\nprice 9.99\r\ntitle Economist\r\n\r\npure xml object\r\nyear 2016\r\nmonth 6\r\nprice 9.99\r\ntitle Economist<\/pre>\n<p>With the ability to verify the return status of the restful server calls it is possible to create much more interesting services than displayed here.<\/p>\n<p>I have attempted to create more than your typical &#8220;foo&#8221; &#8220;bar&#8221; type example program. My final blog on restful services will be a fairly complete service that could be used to provide price data supplied by several &#8220;banks&#8221; on various exchanges.<\/p>\n<p>The data is actually pseudo randomly generated and retrieved and displayed by web browser using java script to fetch, extract and display the data from a JSON formatted string.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My previous restful client example and server example were perfect, well, not exactly. \u00a0They worked but they pretty much assuming a perfect world. \u00a0That is to say that there is never a communication error or a server error. This small &hellip; <a href=\"https:\/\/blog.paranoidprofessor.com\/index.php\/2017\/04\/09\/restful-services-in-java-client-and-server\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[20,3],"tags":[12,36,88],"_links":{"self":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/2158"}],"collection":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/comments?post=2158"}],"version-history":[{"count":17,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/2158\/revisions"}],"predecessor-version":[{"id":2288,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/posts\/2158\/revisions\/2288"}],"wp:attachment":[{"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/media?parent=2158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/categories?post=2158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.paranoidprofessor.com\/index.php\/wp-json\/wp\/v2\/tags?post=2158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}