In this tutorial, we’ll walk through creating a REST API client in Java using the Swing library. This client will interact with a REST API server to manage product data. We'll cover CRUD (Create, Read, Update, Delete) operations, and focus on building a simple graphical interface to make these actions user-friendly.
Prerequisites
To follow this tutorial, it’s recommended that you review our previous article on building a REST API server with PHP, where we implemented basic CRUD endpoints for managing products and categories. Additionally, we previously created articles building a REST API Client in C# with Windows Form and building a REST API Client in Python with PyQt5, which can serve as a helpful comparison.
Project Overview
Our Java Swing client will perform these actions:
- Retrieve and display a list of products
- Add new products
- Update existing products
- Delete products
For this, we'll use Java's HttpURLConnection
for making HTTP requests and Swing components for the UI.
Setting Up the Java Project
- Create a New Java Project in your IDE of choice.
- Add any necessary imports for
HttpURLConnection
, JSON parsing (org.json), and Swing components.
Complete Code Implementation
Below is a basic setup for the Swing client, with each CRUD operation explained.
Main Java Swing Client Class
import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import org.json.JSONArray; import org.json.JSONObject; public class ProductAPIClient extends JFrame { private JTextField nameField, descriptionField; private JTextField priceField; private JButton createButton, fetchButton, updateButton, deleteButton; private JTable productTable; private DefaultTableModel tableModel; //private static final String API_BASE_URL = "http://localhost:8000/api/products"; private static final String API_BASE_URL = "https://bcssti.com/api-sample/products"; public ProductAPIClient() { setTitle("Product API Client"); setSize(600, 400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new FlowLayout()); nameField = new JTextField(10); descriptionField = new JTextField(15); priceField = new JTextField(5); createButton = new JButton("Create Product"); fetchButton = new JButton("Get All Products"); updateButton = new JButton("Update Product"); deleteButton = new JButton("Delete Product"); // Set up table model and JTable tableModel = new DefaultTableModel(new String[]{"ID", "Name", "Description", "Price"}, 0); productTable = new JTable(tableModel); productTable.setPreferredScrollableViewportSize(new Dimension(550, 200)); JScrollPane scrollPane = new JScrollPane(productTable); add(new JLabel("Name:")); add(nameField); add(new JLabel("Description:")); add(descriptionField); add(new JLabel("Price:")); add(priceField); add(createButton); add(fetchButton); add(updateButton); add(deleteButton); add(scrollPane); createButton.addActionListener(e -> createProduct(nameField.getText(), descriptionField.getText(), priceField.getText())); fetchButton.addActionListener(e -> getAllProducts()); updateButton.addActionListener(e -> updateProduct(nameField.getText(), descriptionField.getText(), priceField.getText())); deleteButton.addActionListener(e -> deleteProduct(nameField.getText())); } private void createProduct(String name, String description, String price) { try { JSONObject jsonInput = new JSONObject(); jsonInput.put("name", name); jsonInput.put("description", description); jsonInput.put("price", Double.parseDouble(price)); URL url = new URL(API_BASE_URL + "/"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Accept", "application/json"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Cache-Control", "no-cache"); conn.setDoOutput(true); try (OutputStream os = conn.getOutputStream()) { System.out.println(jsonInput.toString()); byte[] input = jsonInput.toString().getBytes("utf-8"); os.write(input, 0, input.length); os.flush(); } int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { JOptionPane.showMessageDialog(this, "Product created successfully."); this.getAllProducts(); } else { JOptionPane.showMessageDialog(this, "Failed to create product: " + responseCode); } conn.disconnect(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error: " + e.getMessage()); } } private void getAllProducts() { try { URL url = new URL(API_BASE_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Cache-Control", "no-cache"); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String inputLine; StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); conn.disconnect(); JSONArray products = new JSONArray(content.toString()); // Clear existing rows in the table model tableModel.setRowCount(0); // Populate the JTable with data for (int i = 0; i < products.length(); i++) { JSONObject product = products.getJSONObject(i); int id = product.getInt("id"); String name = product.getString("name"); String description = product.getString("description"); double price = product.getDouble("price"); tableModel.addRow(new Object[]{id, name, description, price}); } } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error: " + e.getMessage()); } } private void updateProduct(String name, String description, String price) { try { int productId = Integer.parseInt(JOptionPane.showInputDialog("Enter Product ID to Update")); JSONObject jsonInput = new JSONObject(); jsonInput.put("name", name); jsonInput.put("description", description); jsonInput.put("price", Double.parseDouble(price)); URL url = new URL(API_BASE_URL + "?id=" + productId); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("PUT"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Cache-Control", "no-cache"); conn.setDoOutput(true); try (OutputStream os = conn.getOutputStream()) { os.write(jsonInput.toString().getBytes()); os.flush(); } int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { JOptionPane.showMessageDialog(this, "Product updated successfully."); this.getAllProducts(); } else { JOptionPane.showMessageDialog(this, "Failed to update product: " + responseCode); } conn.disconnect(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error: " + e.getMessage()); } } private void deleteProduct(String name) { try { int productId = Integer.parseInt(JOptionPane.showInputDialog("Enter Product ID to Delete")); String urlPath = API_BASE_URL + "?id=" + productId; URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("DELETE"); conn.setRequestProperty("Cache-Control", "no-cache"); int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { JOptionPane.showMessageDialog(this, "Product deleted successfully."); this.getAllProducts(); } else { JOptionPane.showMessageDialog(this, "Failed to delete product: " + responseCode + "\n" + urlPath); } conn.disconnect(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "Error: " + e.getMessage()); } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { ProductAPIClient client = new ProductAPIClient(); client.setVisible(true); }); } }
Explanation of Key Sections
1. Setting Up HTTP Requests with HttpURLConnection
In the createProduct
method, we use HttpURLConnection
to set up a connection to our API:
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Cache-Control", "no-cache"); conn.setDoOutput(true);
Here we use Cache-Control: no-cache
to ensure that the request bypasses any local or proxy cache, so the client always gets the latest response directly from the server.
2. JSON Payload Construction and Transmission
Using org.json.JSONObject
, we create the JSON payload for our product:
JSONObject jsonInput = new JSONObject(); jsonInput.put("name", name); jsonInput.put("description", description); jsonInput.put("price", Double.parseDouble(price));
After preparing the JSON object, we convert it to a byte array and send it to the server using OutputStream
.
3. Handling Server Responses
We check the response code to confirm if the creation was successful:
int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { JOptionPane.showMessageDialog(this, "Product created successfully."); this.getAllProducts(); } else { JOptionPane.showMessageDialog(this, "Failed to create product: " + responseCode); }
Wrapping Up
In this article, we developed a basic Java client to interact with a REST API. This client enables CRUD operations on products and uses essential headers to manage data freshness and consistency. You can further enhance this client by:
- Adding error handling and input validation
- Creating a more advanced GUI layout
- Implementing additional API endpoints like categories
Additional Resources
- Server-side REST API tutorial from our previous article.
- C# REST API Client and Python REST API Client were built previously, showing another approach for interacting with the API with different language.
- A downloadable Postman collection for testing the API directly.
By following this guide, you’ll have a fully functional Java Swing client ready to manage product data in a RESTful environment