A lightweight Java web microframework that enables developers to build REST services using lambda functions, extract query parameters, and serve static files β all powered by raw Java sockets with zero external dependencies.
Server starting with registered routes and configuration details
Interactive web page served from the static files directory
GET /App/hello?name=Pedro returning a personalized greeting
GET /App/pi returning the value of Math.PI
GET /App/greeting?name=Pedro returning an HTML greeting page
GET /App/time returning the current time server
All 101 unit tests passing with BUILD SUCCESS
| Feature | Description |
|---|---|
| π§ Lambda REST Services | Define GET endpoints with get("/path", (req, resp) -> "response") |
| π Query Parameter Extraction | Access query values with req.getValues("name") |
| π Static File Serving | Configure static directory with staticfiles("/webroot") |
| β‘ Zero Dependencies | Built with pure Java sockets β no Spring, no Jetty, no external libs |
| π§ͺ Fully Tested | 101 unit tests covering all framework components |
| π Multi-format Static Files | Serves .html, .css, .js, .png, .jpg, .gif, .svg, .ico, .json |
These instructions will give you a copy of the project up and running on your local machine for development and testing purposes.
Requirements for running the project:
| Requirement | Description |
|---|---|
| Java 17+ | JDK for compiling and running |
| Maven 3.9+ | Build automation tool |
| Git | Version control |
A step-by-step guide to get the development environment running:
-
Clone the repository
git clone https://github.com/AnderssonProgramming/lambda-rest-microframework.git cd lambda-rest-microframework -
Build the project
mvn clean compile
-
Run the tests
mvn test -
Start the server
mvn exec:java
-
Open your browser and test
URL Description http://localhost:8080/index.html Static HTML page with interactive demo http://localhost:8080/App/hello?name=Pedro REST greeting service http://localhost:8080/App/pi REST service returning PI http://localhost:8080/App/greeting?name=World HTML greeting page http://localhost:8080/App/time Server time service http://localhost:8080/App/echo?msg=test&from=user Echo query parameters
This project enhances a basic Java HTTP server into a fully functional web microframework that supports REST service development through lambda functions. The framework is inspired by lightweight frameworks like Spark Java, providing a minimal but powerful API for building web applications.
A microframework provides the essential tools for web development without the overhead of full-featured frameworks:
π Request β π Router β β‘ Lambda Handler β π¦ Response
β
π Static Files
- Routing β Maps URL paths to handler functions
- Request Parsing β Extracts HTTP method, path, query parameters, and headers
- Static File Serving β Delivers HTML, CSS, JS, and images from a configured directory
- Response Generation β Builds proper HTTP responses with status codes and content types
| Component | Technology | Why? |
|---|---|---|
| Language | Java 17 | Modern features, lambda support, strong typing |
| Networking | Raw Sockets (java.net) | Deep understanding of HTTP protocol |
| Build | Maven | Industry-standard Java build tool |
| Testing | JUnit 4 | Reliable, widely-adopted test framework |
| Dependencies | None (runtime) | Minimal footprint, educational value |
By studying this project, you will understand:
- β How HTTP protocol works at the socket level
- β How to parse HTTP requests (method, URI, query parameters, headers)
- β How to implement a routing system with lambda functions
- β How to serve static files with proper MIME type detection
- β How to apply clean code principles and design patterns (Singleton, Functional Interface)
- β The architecture of web frameworks and distributed applications
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP Client (Browser) β
βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β HTTP Request
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MicroServer (Socket Listener) β
β Listens on port 8080 for connections β
βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β Parse Request
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Request Parser β
β Extracts: method, path, query params, headers β
βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β Route Decision
βΌ
βββββββββββββ΄ββββββββββββ
β β
βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββββββ
β /App/* prefix β β Static File Request β
β REST Router β β (*.html, *.css, ...) β
β β β β
β RouteHandler β β StaticFileHandler β
β finds matching β β reads from classpathβ
β lambda handler β β /webroot directory β
ββββββββββ¬ββββββββββ ββββββββββββ¬ββββββββββββ
β β
βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββββββ
β RestHandler β β File Bytes + β
β (req, resp) -> β β MIME Content-Type β
β Lambda executes β β Detection β
ββββββββββ¬ββββββββββ ββββββββββββ¬ββββββββββββ
β β
βββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP Response Builder β
β Status line + Headers + Body β Output Stream β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Client sends an HTTP request to
localhost:8080 - MicroServer accepts the socket connection and reads the raw HTTP request
- Request Parser extracts the method, URI, query string, and headers
- Router decides:
- If path starts with
/App/β delegate to RouteHandler (REST) - Otherwise β delegate to StaticFileHandler (static files)
- If path starts with
- Handler produces the response body
- Response Builder sends proper HTTP response with headers back to client
lambda-rest-microframework/
βββ π README.md # Project documentation
βββ π LICENSE # MIT License
βββ π pom.xml # Maven build configuration
βββ π .gitignore # Git ignore rules
βββ π images/ # Screenshots for README
βββ π src/
β βββ π main/
β β βββ π java/co/edu/escuelaing/microframework/
β β β βββ π· RestHandler.java # @FunctionalInterface for lambda handlers
β β β βββ π· Request.java # HTTP request wrapper with getValues()
β β β βββ π· Response.java # HTTP response with fluent API
β β β βββ π· RouteHandler.java # Route registration and lookup
β β β βββ π· StaticFileHandler.java # Static file serving + MIME detection
β β β βββ π· MicroServer.java # Main server: get(), staticfiles(), start()
β β β βββ π demo/
β β β βββ π· WebApplication.java # Example application
β β βββ π resources/
β β βββ π webroot/ # Static web files
β β βββ π index.html # Main page with API demo
β β βββ π style.css # Dark theme stylesheet
β β βββ π app.js # Client-side API caller
β βββ π test/
β βββ π java/co/edu/escuelaing/microframework/
β βββ π§ͺ RequestTest.java # 22 tests
β βββ π§ͺ ResponseTest.java # 17 tests
β βββ π§ͺ RouteHandlerTest.java # 18 tests
β βββ π§ͺ StaticFileHandlerTest.java # 32 tests
β βββ π§ͺ MicroServerTest.java # 12 tests
The @FunctionalInterface that enables lambda-based REST service definition:
@FunctionalInterface
public interface RestHandler {
String handle(Request request, Response response);
}This is the core abstraction that allows developers to write:
get("/hello", (req, resp) -> "Hello " + req.getValues("name"));Wraps the raw HTTP request and provides clean access to query parameters:
// Inside a handler, access query parameters easily:
get("/search", (req, resp) -> {
String query = req.getValues("q"); // Extract "q" parameter
String page = req.getValues("page"); // Extract "page" parameter
return "Searching for: " + query + " (page " + page + ")";
});
// URL: /App/search?q=java&page=1Key method: req.getValues(String key) β Returns the query parameter value or empty string if not present.
The Request.parseQueryString() method handles URL-encoded query strings:
name=Pedro&age=25β{name: "Pedro", age: "25"}greeting=Hello+Worldβ{greeting: "Hello World"}email=user%40example.comβ{email: "user@example.com"}
Provides a fluent API for response configuration:
Response response = new Response()
.setStatusCode(200)
.setContentType("application/json")
.setBody("{\"message\": \"OK\"}");Manages the mapping between URL paths and lambda handlers:
RouteHandler router = new RouteHandler();
router.addGetRoute("/hello", (req, resp) -> "Hello!");
router.addGetRoute("/pi", (req, resp) -> String.valueOf(Math.PI));
RestHandler handler = router.findHandler("GET", "/hello");
// handler.handle(req, resp) β "Hello!"Features path normalization: /hello, hello, and /hello/ all map to the same route.
Serves files from a configurable directory with automatic MIME type detection:
StaticFileHandler handler = new StaticFileHandler("/webroot");
byte[] fileBytes = handler.getFileBytes("/index.html");
String mimeType = StaticFileHandler.getContentType("style.css"); // "text/css"Supported MIME types:
| Extension | MIME Type |
|---|---|
.html, .htm |
text/html |
.css |
text/css |
.js |
application/javascript |
.json |
application/json |
.png |
image/png |
.jpg, .jpeg |
image/jpeg |
.gif |
image/gif |
.svg |
image/svg+xml |
.ico |
image/x-icon |
The main server class providing the public API:
public static void main(String[] args) {
// 1. Configure static file location
staticfiles("/webroot");
// 2. Define REST services with lambda functions
get("/hello", (req, resp) -> "Hello " + req.getValues("name"));
get("/pi", (req, resp) -> String.valueOf(Math.PI));
// 3. Start the server
start(); // Listens on port 8080
}REST Prefix: All REST services are accessed under the /App prefix:
get("/hello", ...)β accessible athttp://localhost:8080/App/helloget("/pi", ...)β accessible athttp://localhost:8080/App/pi
Static Files: Served from the root:
http://localhost:8080/index.htmlβ reads from/webroot/index.htmlhttp://localhost:8080/style.cssβ reads from/webroot/style.css
The project includes 101 unit tests covering all framework components:
| Test Class | Tests | Coverage Areas |
|---|---|---|
RequestTest |
22 | Query params, URL decoding, constructors, immutability |
ResponseTest |
17 | Status codes, fluent API, defaults, headers |
RouteHandlerTest |
18 | Route registration, lookup, path normalization, lambdas |
StaticFileHandlerTest |
32 | MIME types, file detection, folder config |
MicroServerTest |
12 | Singleton, route registration, static config |
mvn testExpected output:
[INFO] Tests run: 101, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
// Test: query parameter extraction
@Test
public void testGetValuesReturnsCorrectValue() {
Request req = new Request("GET", "/hello",
Map.of("name", "Pedro"), null, "");
assertEquals("Pedro", req.getValues("name"));
}
// Test: lambda handler with computation
@Test
public void testLambdaWithComputation() {
routeHandler.addGetRoute("/pi", (req, resp) -> String.valueOf(Math.PI));
RestHandler handler = routeHandler.findHandler("GET", "/pi");
assertEquals(String.valueOf(Math.PI), handler.handle(null, null));
}
// Test: MIME type detection
@Test
public void testContentTypeCss() {
assertEquals("text/css", StaticFileHandler.getContentType("style.css"));
}import static co.edu.escuelaing.microframework.MicroServer.*;
public class MyApp {
public static void main(String[] args) {
// Set static files directory
staticfiles("/webroot");
// Simple greeting endpoint
get("/hello", (req, resp) -> "Hello " + req.getValues("name"));
// Mathematical computation
get("/pi", (req, resp) -> String.valueOf(Math.PI));
// Multi-line handler with logic
get("/greeting", (req, resp) -> {
String name = req.getValues("name");
if (name.isEmpty()) name = "World";
return "<h1>Hello, " + name + "!</h1>";
});
// Start server
start();
}
}Available URLs after starting:
http://localhost:8080/index.htmlβ Static web pagehttp://localhost:8080/App/hello?name=Pedroβ Returns "Hello Pedro"http://localhost:8080/App/piβ Returns "3.141592653589793"http://localhost:8080/App/greeting?name=Pedroβ Returns HTML greeting
| Technology | Purpose |
|---|---|
| Java 17 | Programming language with lambda support |
| Maven | Build automation and dependency management |
| JUnit 4 | Unit testing framework |
| Java Sockets (java.net) | HTTP server implementation |
| Pattern | Where | Purpose |
|---|---|---|
| Singleton | MicroServer |
Single server instance with global access |
| Functional Interface | RestHandler |
Lambda-based REST handler definition |
| Strategy | RouteHandler |
Pluggable route-to-handler mapping |
| Builder (Fluent) | Response |
Chainable response configuration |
- Java Networking Tutorial
- Java ServerSocket Documentation
- HTTP/1.1 Protocol (RFC 2616)
- Java Functional Interfaces
- Maven Getting Started Guide
- Andersson David SΓ‘nchez MΓ©ndez β Developer β AnderssonProgramming
This project is licensed under the MIT License β see the LICENSE file for details.
- Escuela Colombiana de IngenierΓa Julio Garavito β Academic institution
- Prof. Luis Daniel Benavides Navarro β Course material on networking and web services
- Spark Java framework β Inspiration for the lambda-based API design
- Java documentation team β Comprehensive networking tutorials