What Are RESTful Web Services?

RESTful web services are built to work best on  Web 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. In the REST architectural style, data and functionalities are considered resources and are accessed using Uniform Resource Identifiers (URIs), 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.

RESTful Web Services – Methods

Here are important points which need to be consider:

  • GET operations are read only and safe.
  • 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.
  • 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.

REST API vs direct DB calls in Desktop Application

When it comes to a large applications with huge database containing milions of records, you will soon realize that those operations( plain select, update, insert and delete) are simply not enough.

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.

The procedural problematic

Let´s 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’s say Java, it will always stay there, no matter which database engine you choose.

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.

Ideally, you should always have a mediator between the database and client which is implementing its own business rules. Providing 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.

How To Consume APEX REST Web Services in Swing?

There are many technologies to consume Rest Webservices in Java. We will use Retrofit in this case.

1-1 What is Retrofit?

Retrofit is a REST Client for Android and Java 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 the website.

1-2 Using Retrofit?

To work with Retrofit you need basically three classes.

  • Model class which is used to map the JSON data to
  • Interfaces which defines the possible HTTP operations
  • Retrofit.Builder class – Instance which uses the interface and the Builder API which allows defining the URL end point for the HTTP operation.

Every method of an interface represents one possible API call. It must have a HTTP annotation (GET, POST, PUT or DELETE) to specify the request type and the relative URL. The return value wraps the response in a Call object with the type of the expected result.

Example:

@GET("employees/")Call<EmployeesData.DataResponse> getEmployees();

1-3 Use Retrofit as Rest Client in Swing

What you’ll need

  •  JDK 1.7 or later
  •  Maven 3 (Gradle 3)  or later
  • Retrofit
  • Converter-Gson

I used Gradle for this Project.

Gradle Configuration

group 'pierre'

version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {

mavenCentral()

}

dependencies {

compile 'com.squareup.retrofit2:retrofit:2.3.0'

compile "com.squareup.retrofit2:converter-gson:2.3.0"

compile "org.projectlombok:lombok:1.16.16"

}

Project structure

├── src
│   └── main
│       ├── java
│       │       ├── application
│       │       │   ├── Main.java
│       │       ├── Modell
│       │       │   ├── Employee.java
│       │       │   └── EmployeesData.java
│       │       ├── Repository
│       │       │   ├── RestEndpoint.java
│       │       ├── Service
│       │       │   └── ServiceGenerator.java
│       │       ├── View
│       │       │   └── Ball.java
│       │       ├── Console.java
│       │       ├── Terminal.java
│       │       └── JFramesItems.java
└── Project

RestEndpoint

package Repository;
package Repository;
import java.util.List;
import modell.Employee;
import modell.EmployeesData;
import retrofit2.Call;
import retrofit2.http.*;
public interface RestEndpoint {
@GET("employees/") Call < EmployeesData.DataResponse > getEmployees();
@GET("employees/") Call < List < Employee >> getEmployeess();
@POST("employees/") Call < Void > addEmployee(@Body Employee employee);
@GET("employees/{empId}") Call < EmployeesData.DataResponse > GetEmployeeById(@Path("empId") long empId);
@PUT("employees/{empId}") Call < Void > editEmployee(@Body Employee employee, @Path("empId") long empId);
@DELETE("employees/{empId}") Call < Void > deleteEmployee(@Path("empId") long empId);
}

ServiceGenerator

package Service;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ServiceGenerator {

private static final String API_BASE_URL = "https://apex.oracle.com/pls/apex/pierrealli/hr/";

private static OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();

private static Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());

public static < S > S createService(Class < S > serviceClass) {
OkHttpClient httpClient = clientBuilder.build();
return retrofitBuilder.client(httpClient).build().create(serviceClass);
}
}

https://apex.oracle.com/pls/apex/pierrealli/hr/ is the API_BASE_URL  create in Oracle Apex.

Get All Data for the Webservices

public void fetchNext() {

 ServiceGenerator.createService(RestEndpoint.class).getEmployees().enqueue(new Callback < DataResponse > () {

  @Override

  public void onResponse(Call < DataResponse > call, Response < DataResponse > response) {

   if (response.isSuccessful()) {

    employees.addAll(response.body().getItems());

    Main.getMainInstance().updateConsole();

   }

  }

  @Override

  publicvoid onFailure(Call < DataResponse > call, Throwable t) {

  }

 });

}

Delete Employees By ID

private void deleteEmployee() {

if (empId.getText() == null || empId.getText().isEmpty()) {

Main.getMainInstance().setStatus("Specify employee id");

return;

}

ServiceGenerator.createService(RestEndpoint.class).deleteEmployee(Long.parseLong(empId.getText()))

.enqueue(new Callback < Void > () {

@Override

publicvoid onResponse(Call < Void > call, Response < Void > response) {

if (response.isSuccessful()) {

Main.getMainInstance().setStatus("Employee deleted");

} else {

Main.getMainInstance().setStatus("Failed to delete employee");

System.out.println(response.raw().toString());

}

}

@Override

publicvoid onFailure(Call < Void > call, Throwable t) {

Main.getMainInstance().setStatus("Retry!");

}

});

}

Source code

https://github.com/allipierre/Consume-Rest-Services-in-Swing-Application.git