{"id":1445,"date":"2017-07-16T15:30:05","date_gmt":"2017-07-16T13:30:05","guid":{"rendered":"http:\/\/www.pitss.org\/blog\/?p=1445"},"modified":"2018-01-10T12:48:35","modified_gmt":"2018-01-10T11:48:35","slug":"consume-apex-restful-web-services-in-java-swing","status":"publish","type":"post","link":"https:\/\/pitss.org\/de\/consume-apex-restful-web-services-in-java-swing\/","title":{"rendered":"Consume APEX RESTful Web Services in Java Swing?"},"content":{"rendered":"<h2>What Are RESTful Web Services?<\/h2>\n<p><b>RESTful web services<\/b> are built to work best on \u00a0Web and Desktop Application. Representational State Transfer (REST) is an architectural style which specify constraints, such as uniform interface. if apply to a web service, desirable properties, such as performance, scalability and modifiability will be induce. this will enable services to work best on a web or desktop application.\u00a0In the REST architectural style, data and functionalities are considered resources and are accessed using <b>Uniform Resource Identifiers (URIs)<\/b>, typically links on the Web. The resources are acted upon by using a set of simple, well-define operations. The REST architectural style constrains an architecture to a client\/server architecture and is designed to use a stateless communication protocol (HTTP). In the REST architecture style, clients and servers exchange representations of resources by using a standardized interface and protocol.<\/p>\n<h2>RESTful Web Services &#8211; Methods<\/h2>\n<p>Here are important points which need to be consider:<\/p>\n<ul class=\"list\">\n<li>GET operations are read only and safe.<\/li>\n<li>PUT and DELETE operations are idempotent. It means that their result will always be the same no matter how many times these operations are invoked.<\/li>\n<li>PUT and POST operation are nearly same with the difference lying only in the result where PUT operation is idempotent and POST operation can cause different result.<\/li>\n<\/ul>\n<h2>REST API vs direct DB calls in Desktop Application<\/h2>\n<p>When it comes to a large applications with huge database containing milions of records, you will soon realize\u00a0that those operations( plain select, update, insert and delete) are simply not enough.<\/p>\n<p>So you start thinking in a different way. You create procedures and triggers to take care of more complicated stuff directly in the database and this is not very good. Databases offer great performance when performing CRUD operations.<\/p>\n<h2>The procedural problematic<\/h2>\n<p>Let\u00b4s imagine that you have to switch to a database which does not support the concept of procedures. What will you do? You are forced to move the procedures to your code base instead, where you can be pretty sure that once you program it in let&#8217;s say Java, it will always stay there, no matter which database engine you choose.<\/p>\n<p>Not to mention, your procedures are usually part of your business logic and it is not a good idea to have your business logic splatered across your codebase and database.<\/p>\n<p>Ideally, you should always have a mediator between the database and client which is implementing its own business rules.\u00a0Providing direct access to database is not a good idea because a direct access to the DB tables is granting the user full data manipulation rights wich is not appropriate for security reasons.<\/p>\n<h2>How To Consume APEX REST Web Services in Swing?<\/h2>\n<p>There are many technologies to consume Rest Webservices in Java. We will use <strong>Retrofit<\/strong> in this case.<\/p>\n<h2>1-1 What is Retrofit?<\/h2>\n<p>Retrofit is a REST Client for Android and <a href=\"https:\/\/pitss.org\/de\/top-java-frameworks-2018\/\">Java<\/a> by Square. It makes it relatively easy to retrieve and upload JSON (or other structured data) via a REST based webservice. In Retrofit you can configure which converter will be use for the data serialisation. Typically for JSON you use GSon but you can also add custom converters to process XML and other protocols. Retrofit uses the OkHttp library for HTTP requests. For more information please see\u00a0<a href=\"http:\/\/square.github.io\/retrofit\/\">the website<\/a>.<\/p>\n<h2>1-2 Using Retrofit?<\/h2>\n<div class=\"paragraph\">\n<p>To work with Retrofit you need basically three classes.<\/p>\n<\/div>\n<div class=\"ulist\">\n<ul>\n<li>Model class which is used to map the JSON data to<\/li>\n<li>Interfaces which defines the possible HTTP operations<\/li>\n<li>Retrofit.Builder class &#8211; Instance which uses the interface and the Builder API which allows defining the URL end point for the HTTP operation.<\/li>\n<\/ul>\n<p>Every method of an interface represents one possible API call. It must have a HTTP annotation (<code>GET<\/code>, <code>POST<\/code>, PUT or DELETE) to specify the request type and the relative URL. The return value wraps the response in a <em>Call<\/em> object with the type of the expected result.<\/p>\n<p>Example:<\/p>\n<pre style=\"background: #fafafa; font-size: 1.1rem;\">@GET(\"employees\/\")Call&lt;EmployeesData.DataResponse&gt; getEmployees();<\/pre>\n<\/div>\n<h2>1-3 Use Retrofit as Rest Client in Swing<\/h2>\n<h3 id=\"whatyoullneed\">What you&#8217;ll need<\/h3>\n<ul>\n<li>\u00a0JDK 1.7 or later<\/li>\n<li>\u00a0Maven 3 (Gradle 3) \u00a0or later<\/li>\n<li>Retrofit<\/li>\n<li>Converter-Gson<\/li>\n<\/ul>\n<p>I used Gradle for this Project.<\/p>\n<h3 id=\"stack\">Gradle Configuration<\/h3>\n<pre><code>group 'pierre'\r\n\r\nversion '1.0-SNAPSHOT'\r\n\r\napply plugin: 'java'\r\n\r\nsourceCompatibility = 1.8\r\n\r\nrepositories {\r\n\r\nmavenCentral()\r\n\r\n}\r\n\r\ndependencies {\r\n\r\ncompile 'com.squareup.retrofit2:retrofit:2.3.0'\r\n\r\ncompile \"com.squareup.retrofit2:converter-gson:2.3.0\"\r\n\r\ncompile \"org.projectlombok:lombok:1.16.16\"\r\n\r\n}\r\n<\/code><\/pre>\n<h3 id=\"projectstructure\">Project structure<\/h3>\n<pre><code>\u251c\u2500\u2500 src\r\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 main\r\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 application\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u251c\u2500\u2500 Main.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 Modell\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u251c\u2500\u2500 Employee.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u2514\u2500\u2500 EmployeesData.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 Repository\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u251c\u2500\u2500 RestEndpoint.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 Service\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u2514\u2500\u2500 ServiceGenerator.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 View\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2502\u00a0\u00a0 \u2514\u2500\u2500 Ball.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 Console.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u251c\u2500\u2500 Terminal.java\r\n\u2502\u00a0\u00a0     \u2502\u00a0\u00a0     \u2514\u2500\u2500 JFramesItems.java\r\n\u2514\u2500\u2500 Project<\/code><\/pre>\n<h2>RestEndpoint<\/h2>\n<pre><code>package Repository;\r\npackage Repository;\r\nimport java.util.List;\r\nimport modell.Employee;\r\nimport modell.EmployeesData;\r\nimport retrofit2.Call;\r\nimport retrofit2.http.*;\r\npublic interface RestEndpoint {\r\n@GET(\"employees\/\") Call &lt; EmployeesData.DataResponse &gt; getEmployees();\r\n@GET(\"employees\/\") Call &lt; List &lt; Employee &gt;&gt; getEmployeess();\r\n@POST(\"employees\/\") Call &lt; Void &gt; addEmployee(@Body Employee employee);\r\n@GET(\"employees\/{empId}\") Call &lt; EmployeesData.DataResponse &gt; GetEmployeeById(@Path(\"empId\") long empId);\r\n@PUT(\"employees\/{empId}\") Call &lt; Void &gt; editEmployee(@Body Employee employee, @Path(\"empId\") long empId);\r\n@DELETE(\"employees\/{empId}\") Call &lt; Void &gt; deleteEmployee(@Path(\"empId\") long empId);\r\n}\r\n<\/code><\/pre>\n<h2>ServiceGenerator<\/h2>\n<pre><code>package Service;\r\nimport okhttp3.OkHttpClient;\r\nimport retrofit2.Retrofit;\r\nimport retrofit2.converter.gson.GsonConverterFactory;\r\n\r\npublic class ServiceGenerator {\r\n\r\nprivate static final String API_BASE_URL = \"https:\/\/apex.oracle.com\/pls\/apex\/pierrealli\/hr\/\";\r\n\r\nprivate static OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();\r\n\r\nprivate static Retrofit.Builder retrofitBuilder = new Retrofit.Builder()\r\n.baseUrl(API_BASE_URL)\r\n.addConverterFactory(GsonConverterFactory.create());\r\n\r\npublic static &lt; S &gt; S createService(Class &lt; S &gt; serviceClass) {\r\nOkHttpClient httpClient = clientBuilder.build();\r\nreturn retrofitBuilder.client(httpClient).build().create(serviceClass);\r\n}\r\n}\r\n<\/code><\/pre>\n<p>https:\/\/apex.oracle.com\/pls\/apex\/pierrealli\/hr\/ is the <code>API_BASE_URL<\/code>\u00a0 create in Oracle Apex.<\/p>\n<h2>Get All Data for the Webservices<\/h2>\n<pre><code>public void fetchNext() {\r\n\r\n ServiceGenerator.createService(RestEndpoint.class).getEmployees().enqueue(new Callback &lt; DataResponse &gt; () {\r\n\r\n  @Override\r\n\r\n  public void onResponse(Call &lt; DataResponse &gt; call, Response &lt; DataResponse &gt; response) {\r\n\r\n   if (response.isSuccessful()) {\r\n\r\n    employees.addAll(response.body().getItems());\r\n\r\n    Main.getMainInstance().updateConsole();\r\n\r\n   }\r\n\r\n  }\r\n\r\n  @Override\r\n\r\n  publicvoid onFailure(Call &lt; DataResponse &gt; call, Throwable t) {\r\n\r\n  }\r\n\r\n });\r\n\r\n}\r\n<\/code><\/pre>\n<h2>Delete Employees By ID<\/h2>\n<pre><code>private void deleteEmployee() {\r\n\r\nif (empId.getText() == null || empId.getText().isEmpty()) {\r\n\r\nMain.getMainInstance().setStatus(\"Specify employee id\");\r\n\r\nreturn;\r\n\r\n}\r\n\r\nServiceGenerator.createService(RestEndpoint.class).deleteEmployee(Long.parseLong(empId.getText()))\r\n\r\n.enqueue(new Callback &lt; Void &gt; () {\r\n\r\n@Override\r\n\r\npublicvoid onResponse(Call &lt; Void &gt; call, Response &lt; Void &gt; response) {\r\n\r\nif (response.isSuccessful()) {\r\n\r\nMain.getMainInstance().setStatus(\"Employee deleted\");\r\n\r\n} else {\r\n\r\nMain.getMainInstance().setStatus(\"Failed to delete employee\");\r\n\r\nSystem.out.println(response.raw().toString());\r\n\r\n}\r\n\r\n}\r\n\r\n@Override\r\n\r\npublicvoid onFailure(Call &lt; Void &gt; call, Throwable t) {\r\n\r\nMain.getMainInstance().setStatus(\"Retry!\");\r\n\r\n}\r\n\r\n});\r\n\r\n}\r\n<\/code><\/pre>\n<h2>Source code<\/h2>\n<pre><code>https:\/\/github.com\/allipierre\/Consume-Rest-Services-in-Swing-Application.git\r\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>What Are RESTful Web Services? RESTful web services are built to work best on \u00a0Web and Desktop Application. Representational State Transfer (REST) is an architectural style which specify constraints, such as uniform interface. if apply to a web service, desirable properties, such as performance, scalability and modifiability will be induce. this will enable services to [&hellip;]<\/p>\n","protected":false},"author":46,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[85,86,87,81,91,92],"tags":[64,88,89,90],"class_list":["post-1445","post","type-post","status-publish","format-standard","hentry","category-java","category-jdk-7","category-jre-7","category-tech-blog","category-web-service","category-webservice","tag-apex","tag-rest-webservices","tag-retrofit","tag-swing"],"_links":{"self":[{"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/posts\/1445","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/users\/46"}],"replies":[{"embeddable":true,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/comments?post=1445"}],"version-history":[{"count":5,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/posts\/1445\/revisions"}],"predecessor-version":[{"id":18857,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/posts\/1445\/revisions\/18857"}],"wp:attachment":[{"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/media?parent=1445"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/categories?post=1445"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pitss.org\/de\/wp-json\/wp\/v2\/tags?post=1445"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}