Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
echo '====================================================='
echo 'Running pre-commit checks (Spotless, Checkstyle)...'
echo '====================================================='
if ! mvn spotless:check checkstyle:check; then
echo '====================================================='
echo '❌ PRE-COMMIT FAILED: Code quality checks did not pass.'
echo 'Please fix the errors above or run "mvn spotless:apply" to format.'
echo '====================================================='
exit 1
fi
echo '✅ All checks passed! Proceeding with commit.'
exit 0
82 changes: 82 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Manual Deployment

on:
workflow_dispatch: # Allows manual triggering from GitHub UI

jobs:
# Job 1: Tooling System & Testing
validate-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Set up JDK 17
uses: actions/setup-java@v6
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Validate & Test (Format, Lint, Test)
run: mvn spotless:check checkstyle:check test

# Job 2: Build the Deployment Artifact
build-artifact:
needs: validate-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Set up JDK 17
uses: actions/setup-java@v6
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build Fat JAR
run: mvn clean package -DskipTests
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: deployment-jar
path: target/basic-web-server-1.0-SNAPSHOT.jar

# Job 3: Actual Deployment to Target Server
deploy:
needs: build-artifact
runs-on: ubuntu-latest
steps:
- name: Download Artifact
uses: actions/download-artifact@v4
with:
name: deployment-jar

- name: Copy Artifact to VM via SCP
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_PORT || '22' }}
source: "basic-web-server-1.0-SNAPSHOT.jar"
target: "/opt/basic-web-server/"

- name: Restart Service via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
port: ${{ secrets.SERVER_PORT || '22' }}
script: |
echo "Deployment starting on remote VM..."
cd /opt/basic-web-server

# If you are using a systemd service (recommended professional approach):
# sudo systemctl restart basic-web-server

# Or if you are using a raw shell script to restart:
echo "Stopping old server instance..."
pkill -f 'basic-web-server-1.0-SNAPSHOT.jar' || true

echo "Starting new server instance in background..."
nohup java -jar basic-web-server-1.0-SNAPSHOT.jar > server.log 2>&1 &

echo "Deployment completed successfully!"
26 changes: 26 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: PR Check

on:
pull_request:
branches: [ main ]

jobs:
validate-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Set up JDK 17
uses: actions/setup-java@v6
with:
java-version: '17'
distribution: 'temurin'
cache: maven

- name: Formatter Check (Spotless)
run: mvn spotless:check

- name: Linter Check (Checkstyle)
run: mvn checkstyle:check

- name: Type Check & Test (Compile + JUnit)
run: mvn clean test
48 changes: 46 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
bin/
.vscode/
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar

# IDEs
.idea/
*.iml
*.iws
.classpath
.project
.settings/
.vscode/
bin/
178 changes: 129 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
# Basic Java Web Server Project
# Basic Java Web Server REST API

<img src="docs/img/java-img.jpg" width="100%">

This is a basic web server project built with **native Java**, utilizing only the Java standard library without any external frameworks. It demonstrates fundamental concepts such as routing, handling different HTTP methods, and processing URL parameters and query strings. The goal of this project is to serve as a reference for anyone interested in understanding how a web service can be implemented using just Java.
This is a basic web server project originally built with native Java, now refactored into a **professional RESTful JSON API**. It demonstrates fundamental backend concepts such as handling HTTP methods, thread pools for concurrency, routing, and processing JSON payloads. The goal of this project is to serve as an educational reference for building a modern web service in Java from scratch.

## Features

- **Basic Routing**: Set up routes for different endpoints.
- **Route with Parameters**: Handle dynamic routes with URL parameters.
- **Query Parameters**: Extract and process query strings from the URL.
- **HTTP Methods**: Support for common HTTP methods: `GET`, `POST`, `PATCH`, `DELETE`.
- **REST API (JSON)**: Fully responds and consumes `application/json` using Google's Gson library.
- **Concurrency**: Built-in `ThreadPoolExecutor` for handling multiple HTTP requests simultaneously.
- **Maven Architecture**: Standardized project structure and dependency management.
- **Dev Tooling**: Code automatically formatted via **Spotless** (Google Java Format) and linted via **Checkstyle**.
- **CI/CD Ready**: Includes GitHub Actions for PR checks (Format/Lint/Test) and multi-stage manual deployment pipelines using SCP/SSH.

## Getting Started

### Prerequisites

Ensure you have **Java Development Kit (JDK)** installed on your machine.

- [Download JDK](https://www.oracle.com/java/technologies/downloads/) (or the version you prefer)
Ensure you have **Java Development Kit (JDK) 17+** and **Apache Maven** installed on your machine.

### Installation

Expand All @@ -32,64 +31,145 @@ Ensure you have **Java Development Kit (JDK)** installed on your machine.

### Running the Server

1. Compile Java program first:
```bash
javac -d bin src/Main.java src/controller/*.java src/model/*.java src/utils/*.java
```
2. Run compiled program
```bash
java -cp bin Main
```
Using Maven, you can compile and start the server immediately:
```bash
mvn clean compile exec:java -Dexec.mainClass="com.server.Main"
```
The server will be running at `http://localhost:8000`

The server will be running at http://localhost:8000
### Building the Executable JAR
If you want to build a deployment-ready Fat JAR:
```bash
mvn clean package -DskipTests
java -jar target/basic-web-server-1.0-SNAPSHOT.jar
```

## Tooling & Testing

## Endpoints
Here are the key endpoints that you can interact with:
Run the automated tests:
```bash
mvn test
```

Format the codebase and check for linting errors:
```bash
mvn spotless:apply checkstyle:check
```
GET / : Returns a simple welcome message and provide simple form to handle request input
GET /users : Fetch all users
GET /users/:id : Fetch a data by their ID
POST /users : Add a new user
PATCH /users/:id : Update user information
DELETE /users/:id : Delete a user by their ID
GET /search?name=&job= : Retrieves data based on user input from a search form, filtering results by name and job

### Pre-commit Hooks
This project strictly enforces code quality using Git pre-commit hooks (Spotless and Checkstyle).
After cloning the repository, you **must** configure Git to use the local hooks directory:
```bash
git config core.hooksPath .githooks
```
Every time you commit, it will automatically verify formatting and linting. If it fails, the commit will be aborted.

## Query Parameters
Example: /search?name=John&job=data+analyst
Query parameters can be extracted and used in request processing.
## Endpoints
Here are the key REST endpoints you can interact with. All endpoints strictly consume and return `application/json`.

### 1. API Health Check
- **`GET /`**
- **Response (200 OK):**
```json
{
"status": "UP",
"message": "Welcome to Basic Web Server API",
"totalUsers": 8
}
```

## HTTP Methods
The service supports the following HTTP methods:
### 2. Fetch All Users
- **`GET /users`**
- **Response (200 OK):**
```json
[
{ "name": "Alex", "job": "Data Analyst" },
{ "name": "Budi", "job": "Frontend Web Developer" }
]
```

```
GET: Retrieve data.
POST: Submit new data.
PATCH: Update partial existing data.
DELETE: Remove data.
```
### 3. Fetch User by ID
- **`GET /users/:id`** *(e.g. `/users/1`)*
- **Response (200 OK):**
```json
{
"name": "Alex",
"job": "Data Analyst"
}
```

### 4. Create New User
- **`POST /users`**
- **Request Body:**
```json
{
"name": "John Doe",
"job": "Backend Engineer"
}
```
- **Response (201 Created):**
```json
{
"status": "success",
"message": "User added successfully"
}
```

### 5. Update User Information
- **`PATCH /users/:id`** *(e.g. `/users/1`)*
- **Request Body:**
```json
{
"job": "Senior Data Analyst"
}
```
- **Response (200 OK):**
```json
{
"status": "success",
"message": "Data updated successfully"
}
```

### 6. Delete a User
- **`DELETE /users/:id`** *(e.g. `/users/1`)*
- **Response (200 OK):**
```json
{
"status": "success",
"message": "Data deleted successfully"
}
```

### 7. Search Users
- **`GET /search?name=&job=`** *(e.g. `/search?job=Data Analyst`)*
- **Response (200 OK):**
```json
[
{ "name": "Alex", "job": "Data Analyst" },
{ "name": "Dono", "job": "Data Analyst" }
]
```

## Code Structure
The project is simple and has the following structure:
The project uses the standard Maven structure:

```bash
/root
├───bin # compiled Java file
│ ├─── /controller
│ ├─── /model
│ └─── /utils
├───lib
├───.github/workflows # CI/CD Pipelines
├───pom.xml # Build config and dependencies
└───src
├─── /controller # A handler for any request
├─── /model # A temporary data user blueprint
├─── /utils # Some helper function
└─── Main.java # Main server logic
├───main/java/com/server
│ ├─── /controller # HTTP route handlers
│ ├─── /model # Data structures and tracking
│ ├─── /utils # Parsers and HTTP helpers
│ └─── Main.java # Server initialization and Thread Pool
└───test/java/com/server
└─── /model # JUnit 5 test cases
```

## License
This project is licensed under the MIT License.

## Acknowledgments
This project is intended to help others learn the basics of building a web service with Java native ☕.
This project is intended to help others learn the basics of building a robust REST API with Java ☕.
Loading
Loading