Code Samples
Barebones App
Here we demonstrate building and running a single-file "barebones" 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.
This app lives in its own GitHub repository.
If you'd like an example of a production-ready system, see the Toy Store App.
Source Code
The entire application is contained in App.java, which is reproduced below.
public class App {
@GET("/")
public String index() {
return "Hello, world!";
}
@GET("/test-input")
public Response testInput(@QueryParameter Integer input) {
return Response.withStatusCode(200)
.headers(Map.of("Content-Type", Set.of("application/json; charset=UTF-8")))
// A real application would not construct JSON in this manner
.body(String.format("{\"input\": %d}", input))
.build();
}
public static void main(String[] args) throws Exception {
int port = 8080;
SokletConfig sokletConfig = SokletConfig.withServer(
Server.withPort(port).build()
).build();
// In an interactive console environment, it makes sense to stop on `Enter` keypress.
// In a Docker container, it makes sense to wait for JVM shutdown (e.g. SIGTERM)
boolean stopOnEnterKey = !"true".equals(System.getenv("RUNNING_IN_DOCKER"));
try (Soklet soklet = Soklet.withConfig(sokletConfig)) {
soklet.start();
System.out.printf("Soklet Barebones App started on port %d\n", port);
if (stopOnEnterKey) {
System.out.println("Press [enter] to exit");
soklet.awaitShutdown(ShutdownTrigger.ENTER_KEY);
} else {
soklet.awaitShutdown();
}
}
}
}
public class App {
@GET("/")
public String index() {
return "Hello, world!";
}
@GET("/test-input")
public Response testInput(@QueryParameter Integer input) {
return Response.withStatusCode(200)
.headers(Map.of("Content-Type", Set.of("application/json; charset=UTF-8")))
// A real application would not construct JSON in this manner
.body(String.format("{\"input\": %d}", input))
.build();
}
public static void main(String[] args) throws Exception {
int port = 8080;
SokletConfig sokletConfig = SokletConfig.withServer(
Server.withPort(port).build()
).build();
// In an interactive console environment, it makes sense to stop on `Enter` keypress.
// In a Docker container, it makes sense to wait for JVM shutdown (e.g. SIGTERM)
boolean stopOnEnterKey = !"true".equals(System.getenv("RUNNING_IN_DOCKER"));
try (Soklet soklet = Soklet.withConfig(sokletConfig)) {
soklet.start();
System.out.printf("Soklet Barebones App started on port %d\n", port);
if (stopOnEnterKey) {
System.out.println("Press [enter] to exit");
soklet.awaitShutdown(ShutdownTrigger.ENTER_KEY);
} else {
soklet.awaitShutdown();
}
}
}
}
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.
Without Docker
Requires JDK 17+ to be installed on your machine.
Build
javac -parameters -processor com.soklet.SokletProcessor -cp soklet-2.0.0.jar -d build src/com/soklet/example/App.java
javac -parameters -processor com.soklet.SokletProcessor -cp soklet-2.0.0.jar -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
With Docker
Requires Docker to be installed on your machine - no JDK needed.
The entire Dockerfile is reproduced below.
FROM amazoncorretto:25
EXPOSE 8080
ENV RUNNING_IN_DOCKER=true
# Copy in source and dependencies
RUN mkdir -p /app/src
COPY src /app/src
COPY soklet-2.0.0.jar /app
# Build the app
WORKDIR /app
RUN javac -parameters -processor com.soklet.SokletProcessor -cp soklet-2.0.0.jar -d build src/com/soklet/example/App.java
# Unprivileged user for runtime
USER 1000
CMD ["/bin/sh", "-c", "java -cp soklet-2.0.0.jar:build com/soklet/example/App"]
FROM amazoncorretto:25
EXPOSE 8080
ENV RUNNING_IN_DOCKER=true
# Copy in source and dependencies
RUN mkdir -p /app/src
COPY src /app/src
COPY soklet-2.0.0.jar /app
# Build the app
WORKDIR /app
RUN javac -parameters -processor com.soklet.SokletProcessor -cp soklet-2.0.0.jar -d build src/com/soklet/example/App.java
# Unprivileged user for runtime
USER 1000
CMD ["/bin/sh", "-c", "java -cp soklet-2.0.0.jar:build com/soklet/example/App"]
Build
docker build . --file Dockerfile --tag soklet/barebones-app
docker build . --file Dockerfile --tag soklet/barebones-app
Run
docker run -p 8080:8080 soklet/barebones-app
docker run -p 8080:8080 soklet/barebones-app
Testing
These tests assume you have the command-line tool curl installed.
Alternatively, you can open the URLs in your web browser.
Happy Path
Request
curl "http://localhost:8080/"
curl "http://localhost:8080/"
Response
Hello, world
Hello, world
Query Parameters
Request
curl --verbose "http://localhost:8080/test-input?input=123"
curl --verbose "http://localhost:8080/test-input?input=123"
Response
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test-input?input=123 HTTP/1.1
...
< HTTP/1.1 200 OK
< Content-Length: 14
< Content-Type: application/json; charset=UTF-8
< Date: Sun, 21 Mar 2024 16:19:01 GMT
<
* Connection #0 to host localhost left intact
{"input": 123}
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test-input?input=123 HTTP/1.1
...
< HTTP/1.1 200 OK
< Content-Length: 14
< Content-Type: application/json; charset=UTF-8
< Date: Sun, 21 Mar 2024 16:19:01 GMT
<
* Connection #0 to host localhost left intact
{"input": 123}
Bad Input
Request
curl --verbose "http://localhost:8080/test-input?input=abc"
curl --verbose "http://localhost:8080/test-input?input=abc"
Response
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test-input?input=abc HTTP/1.1
...
< 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
<
* Connection #0 to host localhost left intact
HTTP 400: Bad Request
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test-input?input=abc HTTP/1.1
...
< 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
<
* Connection #0 to host localhost left intact
HTTP 400: Bad Request

