Overview
Why Soklet?
The Java web ecosystem is missing a server solution that is dependency-free but offers support for Virtual Threads, Server-Sent Events, hooks for dependency injection, and annotation-based request handling. Soklet aims to fill this void.
Soklet provides the basic plumbing to build "transactional" REST APIs that exchange small amounts of data with clients. It does not make technology choices on your behalf (but an example of how to build a full-featured API is available). It does not natively support Reactive Programming or similar methodologies. It does give you the foundation to build your system, your way.
Soklet is commercially-friendly Open Source Software, proudly powering production systems since 2015.
Design Goals
- Main focus: routing HTTP/1.1 requests to Java methods
- Near-instant startup
- Zero dependencies
- Immutability/thread-safety
- Small, comprehensible codebase
- Support for automated unit and integration testing
- Emphasis on configurability
- Thorough, high-quality documentation
- Support for Server-Sent Events
- Servlet integration for legacy code
Design Non-Goals
- SSL/TLS (your load balancer should provide TLS termination)
- Traditional HTTP streaming
- WebSockets
- Dictate which technologies to use (Guice vs. Dagger, Gson vs. Jackson, etc.)
- "Batteries included" authentication and authorization
Installation
Soklet is a single JAR, available on Maven Central.
JDK 17+ is required (or JDK 21+ for Server-Sent Events).
Maven
<dependency>
<groupId>com.soklet</groupId>
<artifactId>soklet</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.soklet</groupId>
<artifactId>soklet</artifactId>
<version>2.0.0</version>
</dependency>
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation 'com.soklet:soklet:2.0.0'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.soklet:soklet:2.0.0'
}
Direct Download
If you don't use Maven or Gradle, you can drop soklet-2.0.0.jar directly into your project. No other dependencies are required.
Example Usage
Here we demonstrate building and running a single-file Soklet application with nothing but the soklet-2.0.0.jar and the JDK. There are no other libraries or frameworks, no Servlet container, no Maven build process - no special setup is required.
While a real production system will have more moving parts, this demonstrates that you can build server software without ceremony or dependencies.
Source Code
package com.soklet.example;
public class App {
// Canonical example
@GET("/")
public String index() {
return "Hello, world!";
}
// Echoes back the path parameter, which must be a LocalDate
@GET("/echo/{date}")
public LocalDate echo(@PathParameter LocalDate date) {
return date;
}
// Formats request body locale for display and customizes the response.
// Example: fr-CA ⇒ francês (Canadá)
@POST("/language")
public Response languageFor(@RequestBody Locale locale) {
Locale systemLocale = Locale.forLanguageTag("pt-BR");
String contentLanguage = systemLocale.toLanguageTag();
return Response.withStatusCode(200)
.body(locale.getDisplayName(systemLocale))
.headers(Map.of("Content-Language", Set.of(contentLanguage)))
.cookies(Set.of(
ResponseCookie.withName("lastRequest")
.value(Instant.now().toString())
.httpOnly(true)
.secure(true)
.maxAge(Duration.ofMinutes(5))
.sameSite(SameSite.LAX)
.build()
))
.build();
}
// Start the server and listen on :8080
public static void main(String[] args) throws Exception {
// Use out-of-the-box defaults
SokletConfig config = SokletConfig.withServer(
Server.withPort(8080).build()
).build();
try (Soklet soklet = Soklet.withConfig(config)) {
soklet.start();
System.out.println("Soklet started, press [enter] to exit");
soklet.awaitShutdown(ShutdownTrigger.ENTER_KEY);
}
}
}
package com.soklet.example;
public class App {
// Canonical example
@GET("/")
public String index() {
return "Hello, world!";
}
// Echoes back the path parameter, which must be a LocalDate
@GET("/echo/{date}")
public LocalDate echo(@PathParameter LocalDate date) {
return date;
}
// Formats request body locale for display and customizes the response.
// Example: fr-CA ⇒ francês (Canadá)
@POST("/language")
public Response languageFor(@RequestBody Locale locale) {
Locale systemLocale = Locale.forLanguageTag("pt-BR");
String contentLanguage = systemLocale.toLanguageTag();
return Response.withStatusCode(200)
.body(locale.getDisplayName(systemLocale))
.headers(Map.of("Content-Language", Set.of(contentLanguage)))
.cookies(Set.of(
ResponseCookie.withName("lastRequest")
.value(Instant.now().toString())
.httpOnly(true)
.secure(true)
.maxAge(Duration.ofMinutes(5))
.sameSite(SameSite.LAX)
.build()
))
.build();
}
// Start the server and listen on :8080
public static void main(String[] args) throws Exception {
// Use out-of-the-box defaults
SokletConfig config = SokletConfig.withServer(
Server.withPort(8080).build()
).build();
try (Soklet soklet = Soklet.withConfig(config)) {
soklet.start();
System.out.println("Soklet started, press [enter] to exit");
soklet.awaitShutdown(ShutdownTrigger.ENTER_KEY);
}
}
}
Want a better understanding of Soklet's capabilities? Start with Request Handling.
Want a minimum-viable "hello world" app you can easily clone and run? Check out the Barebones App.
Want to see how a real-world Soklet app looks? The Toy Store App covers topics like JSON marshaling, dependency injection, authentication/authorization, talking to a database, error handling, internationalization, and more.
Building and Running
You'll need to provide javac with these flags:
-parameters-processor com.soklet.SokletProcessor
JDK 17+ is required.
If you need a JDK, Amazon provides Corretto - a free-to-use-commercially, production-ready distribution of OpenJDK that includes long-term support. Official Corretto Docker Images are also available.
It's recommended to use JDK 21+ to take advantage of Virtual Threads.
Where's Maven? Where's Gradle?
The examples below use javac to build and java to run. Soklet systems can be structurally as simple as a "hello world" app.
Of course, most systems use a build tool to manage dependencies and execution. The Toy Store App shows how a Maven pom.xml can be configured for Soklet.
Build
% javac -parameters -cp soklet-2.0.0.jar -processor com.soklet.SokletProcessor -d build src/com/soklet/example/App.java
% javac -parameters -cp soklet-2.0.0.jar -processor com.soklet.SokletProcessor -d build src/com/soklet/example/App.java
Run
% java -cp soklet-2.0.0.jar:build com/soklet/example/App
% java -cp soklet-2.0.0.jar:build com/soklet/example/App
Test
# Hello, world
% curl -i 'http://localhost:8080/'
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
Hello, world!
# Hello, world
% curl -i 'http://localhost:8080/'
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
Hello, world!
# Acceptable path parameter
% curl -i 'http://localhost:8080/echo/2024-12-31'
HTTP/1.1 200 OK
Content-Length: 10
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
2024-12-31
# Acceptable path parameter
% curl -i 'http://localhost:8080/echo/2024-12-31'
HTTP/1.1 200 OK
Content-Length: 10
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
2024-12-31
# Illegal path parameter
% curl -i 'http://localhost:8080/echo/abc'
HTTP/1.1 400 Bad Request
Content-Length: 21
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
HTTP 400: Bad Request
# Illegal path parameter
% curl -i 'http://localhost:8080/echo/abc'
HTTP/1.1 400 Bad Request
Content-Length: 21
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
HTTP 400: Bad Request
# Language request body
% curl -i -X POST 'http://localhost:8080/language' -d 'fr-CA'
HTTP/1.1 200 OK
Content-Language: pt-BR
Content-Length: 18
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
Set-Cookie: lastRequest=2024-04-21T16:19:01.115336Z; Max-Age=300; Secure; HttpOnly; SameSite=Lax
francês (Canadá)
# Language request body
% curl -i -X POST 'http://localhost:8080/language' -d 'fr-CA'
HTTP/1.1 200 OK
Content-Language: pt-BR
Content-Length: 18
Content-Type: text/plain; charset=UTF-8
Date: Sun, 21 Mar 2024 16:19:01 GMT
Set-Cookie: lastRequest=2024-04-21T16:19:01.115336Z; Max-Age=300; Secure; HttpOnly; SameSite=Lax
francês (Canadá)
Credits
Soklet stands on the shoulders of giants. Internally, it embeds code from the following OSS projects, all of which have licenses that are suitable for commercial use:
- Microhttp by Elliot Barlas - MIT License
- Selenium - Apache 2.0 License
- Apache Commons FileUpload - Apache 2.0 License
- The Spring Framework - Apache 2.0 License



