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
<?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
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.
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).
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
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); } }
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.
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; } } }
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.
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.
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.
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.
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.
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.
0 Response to "Belajar Java Swing - Cara Membuat Rest API Client Menggunakan Retrofit"
Posting Komentar