Building a REST API Client in Java with Swing

 


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

  1. Create a New Java Project in your IDE of choice.
  2. 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);
}

This feedback informs the user of the result and makes troubleshooting easier.

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

By following this guide, you’ll have a fully functional Java Swing client ready to manage product data in a RESTful environment

Previous Post Next Post

نموذج الاتصال