Belajar Java Swing - Cara Membuat Rest API Client Menggunakan Retrofit - Java Community

Belajar Java Swing - Cara Membuat Rest API Client Menggunakan Retrofit

Pada tutorial saya sebelumnya, saya telah membuat Rest API Server menggunakan Spring Boot. Untuk tutorial-nya bisa kalian lihat disini, pada tutorial tersebut untuk melakukan testing-nya saya masih menggunakan software Postman. Sedangkan pada tutorial sekarang saya akan memberikan contoh bagaimana cara membuat Rest API Client menggunakan Retrofit. Retrofit merupakan library Rest Client yang sering digunakan dalam mengembangkan aplikasi Android dan Java dari squareup.

Persiapan Membuat Rest API Client

Rest API Server : Silahkan kalian ikuti tutorial cara membuat Rest API Server menggunakan Spring Boot agar mempermudah kalian dalam mengikuti tutorial saat ini.

Membuat Sebuah Project

Setelah kalian membuat Rest API Server, tahapan berikutnya adalah membuat sebuah Project Maven. Untuk editor yang saya gunakan saat membuat tutorial ini, saya menggunakan Netbeans 12.5 dengan menggunakan GrallVM Java 11 (bisa diganti dengan menggunakan JDK 11 atau OpenJDK 11).

Menambahkan Dependencies

Tambahkan 4(Empat) buah dependency retrofit, converter-gson, gson dan projectlombok ke file pom.xml

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.community</groupId>
    <artifactId>BelajarRetrofit</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>retrofit</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.retrofit2</groupId>
            <artifactId>converter-gson</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>
</project>

Membuat Class Produk

CODE
package com.community.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class Produk {
    private long id;
    private String kodeProduk;
    private String namaProduk;
}

Membuat Class ResponseData

ResponseData merupakan Generic Class Generic yang akan kita gunakan untuk mengambil response API.

CODE
package com.community.request;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ResponseData<T> {
    private int status;
    private String pesan;
    private T data; 
}

Membuat Interface ProdukRestClient

Interface ProdukRestClient Untuk mendefinikasi Rest Client apa saja yang akan panggil, untuk kali ini kita akan membuat contoh CRUD (Create, Read, Update, Delete).

CODE
package com.community.api;

import com.community.request.Produk;
import com.community.request.ResponseData;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;

public interface ProdukRestClient {
    
    @GET("master-produk/list")
    public Call<ResponseData<List<Produk>>> getListProduk();

    @GET("master-produk/{id}")
    public Call<ResponseData<Produk>> getProdukByID(@Path("id") long id);

    @POST("master-produk/create")
    public Call<ResponseData<Produk>> createProduk(@Body Produk produk);
    
    @PUT("master-produk/update/{id}")
    public Call<ResponseData<Produk>> updateProduk(@Path("id") long id, @Body Produk produk);
    
    @DELETE("master-produk/delete/{id}")
    public Call<ResponseData<Produk>> deleteProduk(@Path("id") long id);
}

Membuat Class ApiService

CODE
package com.community.api;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiService {
    private static final String BASE_URL = "http://localhost/belajar-spring/";
    private static Retrofit retrofit;

    public static ProdukRestClient endPoint(){
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

        return retrofit.create(ProdukRestClient.class);
    }
}
Catatan

Pada contoh tutorial cara membuat Rest API Server menggunakan Spring Boot, saya menggunakan port:80 dan context-path=/belajar-spring. Silahkan sesuaikan dengan port dan context-path yang kalian gunakan. Jika kalian menggunakan port dan context-path yang sama, kalian dapat mengabaikan ini.

Membuat Class ProdukModel

Class ProdukModel digunakan untuk pengganti DefaultTableModel yang biasanya saya gunakan dalam membuat JTable.

CODE
package com.community.view.model;

import com.community.api.ApiService;
import com.community.request.Produk;
import com.community.request.ResponseData;
import java.util.List;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.ERROR;
import javax.swing.table.AbstractTableModel;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class ProdukModel extends AbstractTableModel {

    private List<Produk> listProduk;
    
    private final String header[] = new String[]{
        "Kode Produk", "Nama Produk"
    };

    public ProdukModel() {
        getListProduk();
    }

    private void getListProduk() {
        Call<ResponseData<List<Produk>>> call = ApiService.endPoint().getListProduk();
        call.enqueue(new Callback<ResponseData<List<Produk>>>() {
            @Override
            public void onResponse(Call<ResponseData<List<Produk>>> call, Response<ResponseData<List<Produk>>> response) {
                if (response.isSuccessful()) {
                    listProduk = response.body().getData();
                }
            }

            @Override
            public void onFailure(Call<ResponseData<List<Produk>>> call, Throwable thrwbl) {
                JOptionPane.showMessageDialog(null, "Gagal Mengambil Data Produk", "Error", ERROR);
            }

        });
    }

    public Produk getDataProduk(int row) {
        return listProduk.get(row);
    }

    public void addRow(Produk produk) {
        listProduk.add(produk);
    }

    public void removeRow(Produk produk) {
        listProduk.remove(produk);
    }

    public void reloadData() {
        if (!listProduk.isEmpty()) {
            listProduk.clear();
        }
    }

    @Override
    public int getRowCount() {
        if (!listProduk.isEmpty()) {
            return listProduk.size();
        } else {
            return 0;
        }
    }

    @Override
    public int getColumnCount() {
        return header.length;
    }

    @Override
    public String getColumnName(int column) {
        return header[column];
    }

    @Override
    public Object getValueAt(int row, int column) {
        switch (column) {
            case 0:
                return listProduk.get(row).getKodeProduk();
            case 1:
                return listProduk.get(row).getNamaProduk();
            default:
                return null;
        }
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return String.class;
            case 1:
                return String.class;
            default:
                return null;
        }
    }
}
Catatan

Method private void getListProduk() berfungsi untuk memanggil data produk dengan menggunakan call.enqueue(...) atau disebut juga sebagai asynchronous. Jika berhasil terhubung dengan Rest API Server akan masuk ke method public void onResponse dan jika sukses akan melakukan eksekusi baris listProduk = response.body().getData();

Membuat Class ViewProduk

Digunakan untuk membuat tampilan yang akan menampung data Produk kedalam JTable.

Cara Membuat Rest API Client Menggunakan Retrofit
CODE
package com.community.view;

import com.community.controller.ViewProdukController;
import com.community.view.model.ProdukModel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class ViewProduk extends JFrame implements ActionListener {

    private final ViewProdukController controller;
    private JTable tabel;
    private ProdukModel model;
    private JButton tambah, edit, hapus, batal;

    public ViewProduk() {
        controller = new ViewProdukController(this);
        initGUI();
    }

    private void initGUI() {
        setTitle("Rest Client Retrofit");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setSize(700, 500);
        setLocationRelativeTo(null);

        JPanel panelBtn = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));

        tambah = new JButton("Tambah");
        tambah.setPreferredSize(new Dimension(120, 30));
        tambah.addActionListener(this);
        panelBtn.add(tambah);

        edit = new JButton("Edit");
        edit.setPreferredSize(new Dimension(120, 30));
        edit.addActionListener(this);
        panelBtn.add(edit);

        hapus = new JButton("Hapus");
        hapus.setPreferredSize(new Dimension(120, 30));
        hapus.addActionListener(this);
        panelBtn.add(hapus);

        batal = new JButton("Batal");
        batal.setPreferredSize(new Dimension(120, 30));
        batal.addActionListener(this);
        panelBtn.add(batal);

        getContentPane().add(panelBtn, BorderLayout.NORTH);

        model = new ProdukModel();

        tabel = new JTable(model);
        getContentPane().add(new JScrollPane(tabel));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == tambah) {
            controller.tambahData();
        } else if (e.getSource() == edit) {
            int row = tabel.getSelectedRow();
            controller.updateData(row);
        } else if (e.getSource() == hapus) {
            int row = tabel.getSelectedRow();
            controller.deleteData(row);
        }
    }

    public ProdukModel getModel() {
        return model;
    }

}

Membuat Class ViewProdukController

Membuat Controller untuk melakukan respon atau aksi pada ViewProduk seperti tambah, edit dan hapus data produk.

CODE
package com.community.controller;

import com.community.api.ApiService;
import com.community.request.Produk;
import com.community.request.ResponseData;
import com.community.view.DialogProduk;
import com.community.view.ViewProduk;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.ERROR;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class ViewProdukController {

    private final ViewProduk view;

    public ViewProdukController(ViewProduk view) {
        this.view = view;
    }

    public void tambahData() {
        DialogProduk dialog = new DialogProduk(view, Produk.builder().build());
        dialog.setVisible(true);
    }

    public void updateData(int row) {
        Produk produk = view.getModel().getDataProduk(row);
        DialogProduk dialog = new DialogProduk(view, produk);
        dialog.setVisible(true);
    }

    public void deleteData(int row) {
        Produk produk = view.getModel().getDataProduk(row);

        Call<ResponseData<Produk>> call = ApiService.endPoint().deleteProduk(produk.getId());
        call.enqueue(new Callback<ResponseData<Produk>>() {
            @Override
            public void onResponse(Call<ResponseData<Produk>> call, Response<ResponseData<Produk>> response) {
                if (response.isSuccessful()) {
                    view.getModel().removeRow(produk);
                    view.getModel().fireTableDataChanged();
                    JOptionPane.showMessageDialog(null, "Data Produk Berhasil di Hapus", "Sukses", INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(null, "Data Produk Gagal di Hapus", "Error", ERROR);
                }
            }

            @Override
            public void onFailure(Call<ResponseData<Produk>> call, Throwable thrwbl) {
                JOptionPane.showMessageDialog(null, "Tidak Dapat Terhubung Ke Server", "Error", ERROR);
            }

        });
    }
    
}

Membuat Class DialogProduk

Membuat tampilan dialog yang berfungsi untuk menambahkan atau mengedit data produk.

Cara Membuat Rest API Client Menggunakan Retrofit
CODE
package com.community.view;

import com.community.controller.DialogProdukController;
import com.community.request.Produk;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class DialogProduk extends JDialog implements ActionListener{
    
    private final ViewProduk view;
    private final Produk produk;
    private final DialogProdukController controller;
    private JTextField fieldKodeProduk, fieldNamaProduk;
    private JButton simpan, batal;
    
    public DialogProduk(ViewProduk view, Produk produk){
        this.view = view;
        this.produk = produk;
        controller = new DialogProdukController(this);
        initGUI();
        controller.getData();
    }

    private void initGUI() {
        setTitle("Form Produk");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setSize(300, 300);
        setResizable(false);
        setModal(true);
        setLocationRelativeTo(null);
        
        JPanel panelForm = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
        
        JLabel labelKodeProduk = new JLabel("Kode Produk");
        labelKodeProduk.setPreferredSize(new Dimension(120, 30));
        panelForm.add(labelKodeProduk);
        
        fieldKodeProduk = new JTextField();
        fieldKodeProduk.setPreferredSize(new Dimension(250, 30));
        panelForm.add(fieldKodeProduk);
        
        JLabel labelNamaProduk = new JLabel("Nama Produk");
        labelNamaProduk.setPreferredSize(new Dimension(120, 30));
        panelForm.add(labelNamaProduk);
        
        fieldNamaProduk = new JTextField();
        fieldNamaProduk.setPreferredSize(new Dimension(250, 30));
        panelForm.add(fieldNamaProduk);
        
        getContentPane().add(panelForm);
        
        JPanel panelBtn = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));

        simpan = new JButton("Simpan");
        simpan.setPreferredSize(new Dimension(120, 30));
        simpan.addActionListener(this);
        panelBtn.add(simpan);

        batal = new JButton("Batal");
        batal.setPreferredSize(new Dimension(120, 30));
        batal.addActionListener(this);
        panelBtn.add(batal);
        
        getContentPane().add(panelBtn, BorderLayout.SOUTH);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==simpan){
            controller.tambahData();
        } else if(e.getSource()==batal){
            this.dispose();
        }
    }

    public ViewProduk getView() {
        return view;
    }

    public Produk getProduk() {
        return produk;
    }

    public JTextField getFieldKodeProduk() {
        return fieldKodeProduk;
    }

    public JTextField getFieldNamaProduk() {
        return fieldNamaProduk;
    }
    
}

Membuat Class DialogProdukController

Membuat Controller untuk melakukan respon atau aksi simpan data produk pada DialogProduk.

CODE
package com.community.controller;

import com.community.api.ApiService;
import com.community.request.Produk;
import com.community.request.ResponseData;
import com.community.view.DialogProduk;
import static java.awt.image.ImageObserver.ERROR;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class DialogProdukController {

    private final DialogProduk dialog;

    public DialogProdukController(DialogProduk dialog) {
        this.dialog = dialog;
    }
    
    public void getData(){
        dialog.getFieldKodeProduk().setText(dialog.getProduk().getKodeProduk());
        dialog.getFieldNamaProduk().setText(dialog.getProduk().getNamaProduk());
    }

    public void tambahData() {
        if (validasi()) {
            if (dialog.getProduk().getId() > 0) {
                updateData(dialog.getProduk().getId());
            } else {
                simpanData();
            }
            dialog.dispose();
        }
    }

    private boolean validasi() {
        boolean result = true;

        if (dialog.getFieldKodeProduk().getText().trim().equals("")
                || dialog.getFieldNamaProduk().getText().trim().equals("")) {
            result = false;
        }

        if (!result) {
            JOptionPane.showMessageDialog(null, "Kode dan Nama Produk Tidak Boleh Kosong", "Perhatian", WARNING_MESSAGE);
        }

        return result;
    }

    private void simpanData() {
        Call<ResponseData<Produk>> call = ApiService.endPoint()
                .createProduk(Produk.builder()
                        .kodeProduk(dialog.getFieldKodeProduk().getText())
                        .namaProduk(dialog.getFieldNamaProduk().getText())
                        .build());
        call.enqueue(new Callback<ResponseData<Produk>>() {
            @Override
            public void onResponse(Call<ResponseData<Produk>> call, Response<ResponseData<Produk>> response) {
                if (response.isSuccessful()) {
                    dialog.getView().getModel().addRow(response.body().getData());
                    dialog.getView().getModel().fireTableDataChanged();

                    JOptionPane.showMessageDialog(null, "Data Produk Berhasil di Simpan", "Sukses", INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(null, "Data Produk Gagal di Simpan", "Error", ERROR);
                }
            }

            @Override
            public void onFailure(Call<ResponseData<Produk>> call, Throwable thrwbl) {
                JOptionPane.showMessageDialog(null, "Tidak Dapat Terhubung Ke Server", "Error", ERROR);
            }

        });
    }

    public void updateData(long idProduk) {
        Call<ResponseData<Produk>> call = ApiService.endPoint()
                .updateProduk(idProduk, Produk.builder()
                        .kodeProduk(dialog.getFieldKodeProduk().getText())
                        .namaProduk(dialog.getFieldNamaProduk().getText())
                        .build());

        call.enqueue(new Callback<ResponseData<Produk>>() {
            @Override
            public void onResponse(Call<ResponseData<Produk>> call, Response<ResponseData<Produk>> response) {
                if (response.isSuccessful()) {
                    dialog.getView().getModel().removeRow(dialog.getProduk());
                    dialog.getView().getModel().addRow(response.body().getData());
                    dialog.getView().getModel().fireTableDataChanged();
                    JOptionPane.showMessageDialog(null, "Data Produk Berhasil di Update", "Sukses", INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(null, "Data Produk Gagal di Update", "Error", ERROR);
                }
            }

            @Override
            public void onFailure(Call<ResponseData<Produk>> call, Throwable thrwbl) {
                JOptionPane.showMessageDialog(null, "Tidak Dapat Terhubung Ke Server", "Error", ERROR);
            }

        });
    }
}

Membuat Class AppMain

AppMain merupakan Main Class atau Class utama yang akan dieksekusi pertama kali saat aplikasi dijalankan, dan pada AppMain saya menggunakan NimbusLookAndFeel.

CODE
package com.community.app;

import com.community.view.ViewProduk;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;

public class AppMain {
    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(new NimbusLookAndFeel());
        ViewProduk view = new ViewProduk();
        view.setVisible(true);
    }
}

Untuk Source Code Cara Membuat Rest API Client Menggunakan Retrofit, kalian dapat lihat disini

Sekian tutorial bagaimana cara membuat Rest Client API menggunakan Retrofit. Semoga bermanfaat.

Subscribe to receive free email updates:

0 Response to "Belajar Java Swing - Cara Membuat Rest API Client Menggunakan Retrofit"

Posting Komentar