Building a Simple Spring Boot Web Application with Frontend Integration

Project Configuration

Gradle Build Setup

plugins {
    id 'java'
    id 'org.springframework.boot'
    id 'io.spring.dependency-management'
}

group = 'com.example'
version = '1.0.0'

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('bootJar') {
    archiveFileName = 'app.jar'
}

Application Properties

The default configuration works for most scenarios. The auto-configuration handles view resolution and static resource serving automatically.

# Application port (default is 8080)
server.port=8080

# View resolution configuration (if needed)
# spring.mvc.view.prefix=/templates/
# spring.mvc.view.suffix=.html

Backend Implementation

REST Controller

package com.example.controller;

import com.example.model.Product;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/api")
public class ProductController {

    @PostMapping("/search")
    @ResponseBody
    public List<Product> searchProducts(
            @RequestParam String productCode,
            @RequestParam String sortField) {
        
        List<Product> results = new ArrayList<>();
        Product item = new Product();
        item.setProductCode("PRD-001");
        item.setProductName("Sample Product");
        results.add(item);
        
        return results;
    }
}

Domain Model

package com.example.model;

public class Product {
    
    private String productCode;
    private String productName;

    public String getProductCode() {
        return productCode;
    }

    public void setProductCode(String productCode) {
        this.productCode = productCode;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }
}

Application Entry Point

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }
}

Frontend Implementation

HTML Page


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Product Search</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f5f5f5;
        }
        .search-panel {
            background: white;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .form-row {
            display: flex;
            gap: 15px;
            align-items: flex-end;
        }
        .form-group {
            display: flex;
            flex-direction: column;
        }
        .form-group label {
            margin-bottom: 5px;
            font-weight: 500;
        }
        .form-group input, .form-group select {
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        .btn-search {
            padding: 8px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        .btn-search:hover {
            background-color: #45a049;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            background: white;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        th, td {
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #eee;
        }
        th {
            background-color: #4CAF50;
            color: white;
        }
        tr:hover {
            background-color: #f9f9f9;
        }
        .header-image {
            max-width: 200px;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <div class="search-panel">
        ![Header](/assets/header.jpg)
        <form id="searchForm">
            <div class="form-row">
                <div class="form-group">
                    <label for="productCode">Product Code</label>
                    <input type="text" id="productCode" name="productCode" maxlength="50">
                </div>
                <div class="form-group">
                    <label for="sortField">Sort By</label>
                    <select id="sortField" name="sortField">
                        <option value="code">Product Code</option>
                        <option value="name">Product Name</option>
                    </select>
                </div>
                <div class="form-group">
                    <label>&nbsp;</label>
                    <button type="button" id="btnSearch" class="btn-search">Search</button>
                </div>
            </div>
        </form>
    </div>

    <div class="results-container">
        | Product Code | Product Name |
|---|---|
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="/js/app.js"></script>
</body>
</html>

JavaScript Handler

(function() {
    'use strict';

    function initSearchHandler() {
        var searchBtn = document.getElementById('btnSearch');
        var resultsBody = document.getElementById('resultsBody');

        searchBtn.addEventListener('click', function() {
            var productCode = document.getElementById('productCode').value;
            var sortField = document.getElementById('sortField').value;

            fetchProductData(productCode, sortField, resultsBody);
        });
    }

    function fetchProductData(productCode, sortField, container) {
        var requestData = {
            productCode: productCode,
            sortField: sortField
        };

        fetch('/api/search', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(requestData)
        })
        .then(function(response) {
            return response.json();
        })
        .then(function(data) {
            renderResults(data, container);
        })
        .catch(function(error) {
            console.error('Search failed:', error);
            alert('An error occurred while searching. Please try again.');
        });
    }

    function renderResults(products, container) {
        var html = '';

        if (products && products.length > 0) {
            products.forEach(function(item) {
                html += '<tr>';
                html += '<td>' + escapeHtml(item.productCode) + '</td>';
                html += '<td>' + escapeHtml(item.productName) + '</td>';
                html += '</tr>';
            });
        } else {
            html = '<tr><td colspan="2">No results found</td></tr>';
        }

        container.innerHTML = html;
    }

    function escapeHtml(text) {
        var div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    document.addEventListener('DOMContentLoaded', initSearchHandler);
})();

Project Structure

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           ├── WebApplication.java
│   │           ├── controller/
│   │           │   └── ProductController.java
│   │           └── model/
│   │               └── Product.java
│   └── resources/
│       ├── static/
│       │   ├── index.html
│       │   └── js/
│       │       └── app.js
│       └── application.properties
└── build.gradle

Running the Application

  1. Execute ./gradlew bootRun from the project root
  2. Open http://localhost:8080/index.html in a browser
  3. Enter search criteria and click the search button
  4. Results display in the table below the search form

Tags: spring-boot Gradle java web-development frontend

Posted on Sun, 07 Jun 2026 16:15:55 +0000 by speps