This document describes how to contribute to the core Javalin project, if you want to contribute to the Javalin website you should go to https://github.com/javalin/javalin.github.io.
Remember to include enough information if you're reporting a bug.
Creating an issue to ask a question is fine.
Every PR will be considered.
- Ask about the feature beforehand (or pick one of the open issues)
- If no issue exists, create an issue for the PR
- Try to write some tests for your change. There are a lot of examples in the
test
dir. - Format your code so it looks somewhat like the rest of the source (which is formatted using default settings in IntelliJ)
./mvnw test
(or mvnw.cmd test
for Windows)
./mvnw install
(or mvnw.cmd install
for Windows)
The following ASCII file structure diagram shows the most important packages and files, with comments.
io.javalin
├── apibuilder/ // Convenience methods for when declaring large APIs
├── core/ // Things that concern both HTTP and WebSockets
│ ├── security/ // AccessManager, Role interface, security utils
│ ├── util/ // Misc utils - if you don't know where to place something, this is the place...
│ └── validation/ // Validation for parameters
├── http/ // Everything related to http requests
│ ├── sse/ // Server-sent events
│ ├── staticfiles/ // Static file handling
│ ├── util/ // Misc utils for HTTP, mainly for Context
│ ├── Context.kt // Wrapper class for request/response, contains everything needed to fulfill a request
│ └── JavalinServlet.kt // Responsible for the request lifecycle (writes the response to the client)
├── plugin/ // All plugins (functionality that requires optional dependencies)
│ ├── json/ // Interfaces for JSON, as well as a Jackson based implementation
│ ├── metrics/ // Metric plugins
│ └── rendering/ // Interface for file rendering, and several template engine implementations
├── websocket/ // Everything related to WebSockets
│ ├── WsContext.kt // Wrapper class for WebSockets
│ ├── JavalinWsServlet.kt // Responsible for WebSocket upgrade, as well as switching between WebSocket and HTTP
│ └── WsConnection.kt // Keeps state of a WebSocket connection and handles incoming events
└── Javalin.java // Main public API, responsible for setting up and configuring the server
Any public API which takes a @FunctionalInterface
as a parameter has to be Java
to achieve the best interoperability between Java and Kotlin.
Every @FunctionalInterface
is also Java for the same reasons.
Almost all tests are written in Kotlin, but it's okay to contribute a Java test.
Almost all tests should be full integration tests. This means every test should
- Start a Javalin instance on a random port
- Attach a handler which does what you want to test
- Perform a HTTP request against that handler
- Verify what you want to test using the response value
- Stop the Javalin instance
This is a lot easier than it sounds. Here is an example test:
@Test
fun `session-cookie is http-only`() = TestUtil.test { app, http ->
app.get("/store-session") { ctx -> ctx.sessionAttribute("test", "tast") }
assertThat(http.get("/store-session").headers.getFirst("Set-Cookie").contains("HttpOnly"), `is`(true))
}
The TestUtil.test
function takes care of creating, starting and stopping a Javalin instance (on a random port),
and provides you with a http-client you can use to perform requests.
You can also give test
a Javalin instance:
TestUtil.test(Javalin.create().configure { ... }) { app, http ->
test
will assign the instance a random port and stop it after the test is done.
There's usually someone on gitter who can help you if you have any questions.