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