Java Rest API with sqlite and simple web frontend

This commit is contained in:
arul 2025-06-25 03:05:49 +05:30
commit 10011418f5
19 changed files with 670 additions and 0 deletions

0
README.md Normal file
View File

49
pom.xml Normal file
View File

@ -0,0 +1,49 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>java-project</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>java-project</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>5.6.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

BIN
purchase.db Normal file

Binary file not shown.

View File

@ -0,0 +1,72 @@
CURL COMMAND TUTORIAL
---
### 1.
```bash
curl http://localhost:7070/total
```
* **What it does:**
Sends an HTTP GET request to your APIs `/total` endpoint.
* **Purpose:**
Fetches the total profit so far from your server.
* **Response you got:**
```json
{"totalProfit":12000.0}
```
This means the total sum of all purchased products recorded so far is ₹12,000.
---
### 2.
```bash
curl http://localhost:7070/turl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
```
* **What you tried to do:**
Looks like you tried to send a POST request to `/purchase` to add a new product "Camera Drone" priced at 12000.
* **Why its wrong / problematic:**
The syntax is incorrect and malformed. You are mixing a GET request to `/turl` with `-X POST http://localhost:7070/purchase`, which doesnt make sense for `curl`.
The command has extra URL (`http://localhost:7070/purchase`) placed incorrectly after `-X POST`, which should only be followed by the HTTP method, not another URL.
* **Correct form:**
```bash
curl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
```
* This correctly sends a POST request to `/purchase` endpoint with a JSON body specifying the product and price.
---
### Summary of key curl options used:
* `curl [URL]` — by default, sends a GET request to the URL.
* `-X POST` — explicitly sets HTTP method to POST (used to send data).
* `-H "Content-Type: application/json"` — adds HTTP header specifying the request body is JSON.
* `-d '{"product":"Camera Drone","price":12000}'` — the JSON data to send in the body of the POST request.
---
If you want to test adding a new purchase and then check total, this sequence is correct:
```bash
curl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
curl http://localhost:7070/total
```
This will record the new product and then return the updated total profit.
---
If you want, I can help you build some shell scripts or alias commands to make testing easier! Just say the word.

View File

@ -0,0 +1,114 @@
package com.test;
//Custom Classes Imported below
import com.test.PurchaseDAO;
// Import necessary classes
import java.util.Map;
import java.util.HashMap;
import java.util.Scanner;
import io.javalin.Javalin;
import io.javalin.http.Context;
import io.javalin.plugin.bundled.CorsPluginConfig;
public class App {
// Create a Constructor object to hold user and product info
Constructor construct = new Constructor("Arul", 24, "India, TN");
// Counter to track number of products purchased
int productIndex = 0;
// Map to store product name as key and price as value
Map<String, Double> purchasedProductDetails = new HashMap<>();
// Scanner object to read input from console
Scanner scanner = new Scanner(System.in);
PurchaseDAO db = new PurchaseDAO(); // Initializing DB
// Method to record a purchase
public void recordPurchase(String product, double price) {
productIndex++; // Increment product count
construct.setProductName(product); // Set product name
construct.setProductPrice(price); // Set product price
construct.setTotalProductsPurchased(productIndex); // Update total
makeList(); // Add to local Map
db.insertPurchase(product, price); // Save to DB
}
// Read user input from console (for CLI use)
public void printAndRead() {
System.out.println("[+] Enter the Product " + productIndex + " Name:");
String productName = scanner.nextLine();
System.out.println("[+] Enter price of the Product");
Double productPrice = scanner.nextDouble();
scanner.nextLine(); // Consume newline
recordPurchase(productName, productPrice);
}
// Add product and price to Map
public void makeList() {
purchasedProductDetails.put(construct.getProductName(), construct.getProductPrice());
}
// Calculate total from DB and print
public void calculateTotalProfit() {
double sum = db.getTotalProfit(); // From DB
System.out.println("Total profit: ₹" + sum);
}
// 🟢 Start API server
public void startApi() {
Javalin app = Javalin.create(config -> {
// Enable CORS for frontend origin
config.plugins.enableCors(cors -> {
cors.add(CorsPluginConfig::anyHost); // Or use allowHost("http://localhost:8080")
});
}).start(7070);
// Set JSON response type
app.before(ctx -> ctx.contentType("application/json"));
// 🔸 POST /purchase Record purchase
app.post("/purchase", ctx -> {
Map<String, Object> data = ctx.bodyAsClass(Map.class);
String product = data.get("product").toString();
double price = Double.parseDouble(data.get("price").toString());
recordPurchase(product, price);
ctx.status(200).result("Recorded: " + product + " for ₹" + price);
});
// 🔹 GET /total Return total profit
app.get("/total", ctx -> {
double sum = db.getTotalProfit();
ctx.json(Map.of(
"totalProfit", sum,
"customerName", construct.name,
"customerAge", construct.age,
"customerRegion", construct.region
));
});
}
// 🚀 Main Method
public static void main(String[] args) {
App app = new App();
app.startApi(); // Start server
// Optional CLI (not needed for frontend, just for manual entry)
int flag = 0;
while (flag != 1) {
System.out.println("Proceed Adding Products? (Y/N)");
String userInput = app.scanner.nextLine();
if (userInput.equalsIgnoreCase("Y")) {
app.printAndRead();
} else {
app.calculateTotalProfit();
flag = 1;
app.scanner.close();
}
}
}
}

View File

@ -0,0 +1,62 @@
package com.test;
public class Constructor {
// User info fields
String name;
int age;
String region;
// Product-related fields (private for encapsulation)
private String purchaseProduct;
private double productPrice;
private double profitOfTheDay;
private int totalProductsPurchased;
// Constructor to initialize user details
public Constructor(String name, int age, String region) {
this.age = age;
this.name = name;
this.region = region;
}
// Getter for product name
public String getProductName() {
return purchaseProduct;
}
// Getter for product price
public double getProductPrice() {
return productPrice;
}
// Getter for profit of the day (not used yet in App)
public double getProfitOfTheDay() {
return profitOfTheDay;
}
// Setter for product name
public void setProductName(String purchaseProduct) {
this.purchaseProduct = purchaseProduct;
}
// Setter for product price
public void setProductPrice(double productPrice) {
this.productPrice = productPrice;
}
// Setter for profit of the day
public void setProfitOfTheDay(double profitOfTheDay) {
this.profitOfTheDay = profitOfTheDay;
}
// Setter for total products purchased
public void setTotalProductsPurchased(int totalProductsPurchased) {
this.totalProductsPurchased = totalProductsPurchased;
}
// Getter for total products purchased
public int getTotalProductsPurchased() {
return totalProductsPurchased;
}
}

View File

@ -0,0 +1,57 @@
package com.test;
import java.sql.*;
public class PurchaseDAO {
private static final String DB_URL = "jdbc:sqlite:purchase.db";
public PurchaseDAO(){
try(Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement())
{
String sql = "CREATE TABLE IF NOT EXISTS purchases ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "product TEXT NOT NULL,"
+ "price REAL NOT NULL);";
stmt.execute(sql);
}
catch(SQLException e){
e.printStackTrace();
}
}
public void insertPurchase(String product, double price){
String sql = "INSERT INTO purchases (product, price) VALUES (?,?)";
try (Connection conn = DriverManager.getConnection(DB_URL);
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setString(1, product);
pstmt.setDouble(2, price);
pstmt.executeUpdate();
}
catch(SQLException e){
e.printStackTrace();
}
}
public double getTotalProfit(){
double total = 0;
String sql = "SELECT SUM(price) FROM purchases";
try(Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement();
ResultSet res = stmt.executeQuery(sql)){
if(res.next()){
total = res.getDouble(1);
}
}
catch(SQLException e){
e.printStackTrace();
}
return total;
}
}

View File

@ -0,0 +1,54 @@
// Wait until the DOM (HTML page) is fully loaded
document.addEventListener("DOMContentLoaded", function () {
// Grab form elements and buttons
const form = document.getElementById("purchaseForm");
const resultDiv = document.getElementById("result");
const totalBtn = document.getElementById("totalBtn");
// 🟩 Handle form submission (Add new Purchase)
form.addEventListener("submit", function (event) {
event.preventDefault(); // Prevent page refresh
// Get product and price values from form
const product = document.getElementById("product").value;
const price = parseFloat(document.getElementById("price").value);
const data = { product: product, price: price };
// Send POST request to /purchase endpoint
fetch("http://localhost:7070/purchase", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(function (response) {
return response.text(); // Expecting plain text response
})
.then(function (data) {
resultDiv.innerText = data; // Show server response
form.reset(); // Clear form inputs
})
.catch(function (error) {
resultDiv.innerText = "Error: " + error; // Show error if any
});
});
// 🟦 Handle "Show Total Profit" button click (GET from /total)
totalBtn.addEventListener("click", function () {
fetch("http://localhost:7070/total")
.then((response) => response.json()) // Expect JSON response
.then((data) => {
// Format and display returned data
const output = `
Name: ${data.customerName}
Age: ${data.customerAge}
Region: ${data.customerRegion}
Total Profit: ${data.totalProfit}
`;
resultDiv.innerText = output;
})
.catch((error) => {
resultDiv.innerText = "Error: " + error; // Display fetch error
});
});
});

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Purchase Tracker</title>
<!-- Link CSS -->
<link rel="stylesheet" href="styles.css" />
<!-- Link JS (corrected attribute typo: 'data-jslicence' to 'data-jslicense') -->
<script src="app.js" defer data-jslicense="MIT"></script>
</head>
<body>
<div class="container">
<h1>Product Purchase Tracker</h1>
<!-- Purchase form -->
<form id="purchaseForm">
<label for="product">Product Name:</label>
<input type="text" id="product" name="product" required />
<label for="price">Price (₹):</label>
<input type="number" id="price" name="price" step="0.01" required />
<button type="submit">Add Purchase</button>
</form>
<!-- Button to fetch total -->
<button id="totalBtn">Show Total Profit</button>
<!-- Result will be shown here -->
<div id="result"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,28 @@
body {
font-family: sans-serif;
background-color: #f4f4f4;
padding: 20px;
}
.container {
max-width: 500px;
margin: auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* optional visual polish */
}
input,
button {
display: block;
width: 100%;
margin-top: 10px;
padding: 8px;
font-size: 1rem;
}
#result {
margin-top: 20px;
white-space: pre-wrap; /* keep newlines and wrap long lines */
}

View File

@ -0,0 +1,72 @@
CURL COMMAND TUTORIAL
---
### 1.
```bash
curl http://localhost:7070/total
```
* **What it does:**
Sends an HTTP GET request to your APIs `/total` endpoint.
* **Purpose:**
Fetches the total profit so far from your server.
* **Response you got:**
```json
{"totalProfit":12000.0}
```
This means the total sum of all purchased products recorded so far is ₹12,000.
---
### 2.
```bash
curl http://localhost:7070/turl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
```
* **What you tried to do:**
Looks like you tried to send a POST request to `/purchase` to add a new product "Camera Drone" priced at 12000.
* **Why its wrong / problematic:**
The syntax is incorrect and malformed. You are mixing a GET request to `/turl` with `-X POST http://localhost:7070/purchase`, which doesnt make sense for `curl`.
The command has extra URL (`http://localhost:7070/purchase`) placed incorrectly after `-X POST`, which should only be followed by the HTTP method, not another URL.
* **Correct form:**
```bash
curl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
```
* This correctly sends a POST request to `/purchase` endpoint with a JSON body specifying the product and price.
---
### Summary of key curl options used:
* `curl [URL]` — by default, sends a GET request to the URL.
* `-X POST` — explicitly sets HTTP method to POST (used to send data).
* `-H "Content-Type: application/json"` — adds HTTP header specifying the request body is JSON.
* `-d '{"product":"Camera Drone","price":12000}'` — the JSON data to send in the body of the POST request.
---
If you want to test adding a new purchase and then check total, this sequence is correct:
```bash
curl -X POST http://localhost:7070/purchase -H "Content-Type: application/json" -d '{"product":"Camera Drone","price":12000}'
curl http://localhost:7070/total
```
This will record the new product and then return the updated total profit.
---
If you want, I can help you build some shell scripts or alias commands to make testing easier! Just say the word.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,54 @@
// Wait until the DOM (HTML page) is fully loaded
document.addEventListener("DOMContentLoaded", function () {
// Grab form elements and buttons
const form = document.getElementById("purchaseForm");
const resultDiv = document.getElementById("result");
const totalBtn = document.getElementById("totalBtn");
// 🟩 Handle form submission (Add new Purchase)
form.addEventListener("submit", function (event) {
event.preventDefault(); // Prevent page refresh
// Get product and price values from form
const product = document.getElementById("product").value;
const price = parseFloat(document.getElementById("price").value);
const data = { product: product, price: price };
// Send POST request to /purchase endpoint
fetch("http://localhost:7070/purchase", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(function (response) {
return response.text(); // Expecting plain text response
})
.then(function (data) {
resultDiv.innerText = data; // Show server response
form.reset(); // Clear form inputs
})
.catch(function (error) {
resultDiv.innerText = "Error: " + error; // Show error if any
});
});
// 🟦 Handle "Show Total Profit" button click (GET from /total)
totalBtn.addEventListener("click", function () {
fetch("http://localhost:7070/total")
.then((response) => response.json()) // Expect JSON response
.then((data) => {
// Format and display returned data
const output = `
Name: ${data.customerName}
Age: ${data.customerAge}
Region: ${data.customerRegion}
Total Profit: ${data.totalProfit}
`;
resultDiv.innerText = output;
})
.catch((error) => {
resultDiv.innerText = "Error: " + error; // Display fetch error
});
});
});

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Purchase Tracker</title>
<!-- Link CSS -->
<link rel="stylesheet" href="styles.css" />
<!-- Link JS (corrected attribute typo: 'data-jslicence' to 'data-jslicense') -->
<script src="app.js" defer data-jslicense="MIT"></script>
</head>
<body>
<div class="container">
<h1>Product Purchase Tracker</h1>
<!-- Purchase form -->
<form id="purchaseForm">
<label for="product">Product Name:</label>
<input type="text" id="product" name="product" required />
<label for="price">Price (₹):</label>
<input type="number" id="price" name="price" step="0.01" required />
<button type="submit">Add Purchase</button>
</form>
<!-- Button to fetch total -->
<button id="totalBtn">Show Total Profit</button>
<!-- Result will be shown here -->
<div id="result"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,28 @@
body {
font-family: sans-serif;
background-color: #f4f4f4;
padding: 20px;
}
.container {
max-width: 500px;
margin: auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* optional visual polish */
}
input,
button {
display: block;
width: 100%;
margin-top: 10px;
padding: 8px;
font-size: 1rem;
}
#result {
margin-top: 20px;
white-space: pre-wrap; /* keep newlines and wrap long lines */
}

View File

@ -0,0 +1,3 @@
com/test/PurchaseDAO.class
com/test/App.class
com/test/Constructor.class

View File

@ -0,0 +1,3 @@
/home/arul/apiServerProject/java-project/src/main/java/com/test/App.java
/home/arul/apiServerProject/java-project/src/main/java/com/test/Constructor.java
/home/arul/apiServerProject/java-project/src/main/java/com/test/PurchaseDAO.java