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">

<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> </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
- Execute
./gradlew bootRunfrom the project root - Open
http://localhost:8080/index.htmlin a browser - Enter search criteria and click the search button
- Results display in the table below the search form