Fork me on GitHub

Getting started

1: Create a new maven project and add the dependency to your POM.xml:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.5.3</version>
</dependency>
Not familiar with Maven? Click here for more detailed instructions.

Other dependency managers:

Gradle : compile "com.sparkjava:spark-core:2.5.3" //add to build.gradle
   Ivy : <dependency org="com.sparkjava" name="spark-core" rev="2.5.3" conf="build" /> //ivy.xml
   SBT : libraryDependencies += "com.sparkjava" % "spark-core" % "2.5.3" //build.sbt

2: Start coding:

import static spark.Spark.*;

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

3: Run and view:

http://localhost:4567/hello

To see more console output from Spark (debug info, etc), you have to add a logger to your project.

Stopping the Server

By calling the stop() method the server is stopped and all routes are cleared.

stop();

Routes

The main building block of a Spark application is a set of routes. A route is made up of three simple pieces:

Routes are matched in the order they are defined. The first route that matches the request is invoked.

get("/", (request, response) -> {
    // Show something
});

post("/", (request, response) -> {
    // Create something
});

put("/", (request, response) -> {
    // Update something
});

delete("/", (request, response) -> {
    // Annihilate something
});

options("/", (request, response) -> {
    // Appease something
});

Route patterns can include named parameters, accessible via the params method on the request object:

// matches "GET /hello/foo" and "GET /hello/bar"
// request.params(":name") is 'foo' or 'bar'
get("/hello/:name", (request, response) -> {
    return "Hello: " + request.params(":name");
});

Route patterns can also include splat (or wildcard) parameters. These parameters can be accessed by using the splat method on the request object:

// matches "GET /say/hello/to/world"
// request.splat()[0] is 'hello' and request.splat()[1] 'world'
get("/say/*/to/*", (request, response) -> {
    return "Number of splat parameters: " + request.splat().length;
});

Route overview

In Spark 2.4 we added an experimental feature, the Route Overview:
RouteOverview.enableRouteOverview(); // overview available at /debug/routeoverview/
RouteOverview.enableRouteOverview("/my/overview/path"); // available at specified path

Note: This feature has a lot of reflection magic, it might not work perfectly with some JDK versions.

Request

Request information and functionality is provided by the request parameter:

request.attributes();             // the attributes list
request.attribute("foo");         // value of foo attribute
request.attribute("A", "V");      // sets value of attribute A to V
request.body();                   // request body sent by the client
request.bodyAsBytes();            // request body as bytes
request.contentLength();          // length of request body
request.contentType();            // content type of request.body
request.contextPath();            // the context path, e.g. "/hello"
request.cookies();                // request cookies sent by the client
request.headers();                // the HTTP header list
request.headers("BAR");           // value of BAR header
request.host();                   // the host, e.g. "example.com"
request.ip();                     // client IP address
request.params("foo");            // value of foo path parameter
request.params();                 // map with all parameters
request.pathInfo();               // the path info
request.port();                   // the server port
request.protocol();               // the protocol, e.g. HTTP/1.1
request.queryMap();               // the query map
request.queryMap("foo");          // query map for a certain parameter
request.queryParams();            // the query param list
request.queryParams("FOO");       // value of FOO query param
request.queryParamsValues("FOO")  // all values of FOO query param
request.raw();                    // raw request handed in by Jetty
request.requestMethod();          // The HTTP method (GET, ..etc)
request.scheme();                 // "http"
request.servletPath();            // the servlet path, e.g. /result.jsp
request.session();                // session management
request.splat();                  // splat (*) parameters
request.uri();                    // the uri, e.g. "http://example.com/foo"
request.url();                    // the url. e.g. "http://example.com/foo"
request.userAgent();              // user agent

Response

Response information and functionality is provided by the response parameter:

response.body();               // get response content
response.body("Hello");        // sets content to Hello
response.header("FOO", "bar"); // sets header FOO with value bar
response.raw();                // raw response handed in by Jetty
response.redirect("/example"); // browser redirect to /example
response.status();             // get the response status
response.status(401);          // set status code to 401
response.type();               // get the content type
response.type("text/xml");     // set content type to text/xml

Query Maps

Query maps allows you to group parameters to a map by their prefix. This allows you to group two parameters like user[name] and user[age] to a user map.

request.queryMap().get("user", "name").value();
request.queryMap().get("user").get("name").value();
request.queryMap("user").get("age").integerValue();
request.queryMap("user").toMap();

Cookies

request.cookies();                         // get map of all request cookies
request.cookie("foo");                     // access request cookie by name
response.cookie("foo", "bar");             // set cookie with a value
response.cookie("foo", "bar", 3600);       // set cookie with a max-age
response.cookie("foo", "bar", 3600, true); // secure cookie
response.removeCookie("foo");              // remove cookie

Sessions

Every request has access to the session created on the server side, provided with the following methods:

request.session(true)                      // create and return session
request.session().attribute("user")        // Get session attribute 'user'
request.session().attribute("user", "foo") // Set session attribute 'user'
request.session().removeAttribute("user")  // Remove session attribute 'user'
request.session().attributes()             // Get all session attributes
request.session().id()                     // Get session id
request.session().isNew()                  // Check if session is new
request.session().raw()                    // Return servlet object

Halting

To immediately stop a request within a filter or route use:

halt();

You can also specify the status when halting:

halt(401);

Or the body:

halt("This is the body");

...or both:

halt(401, "Go away!");

Filters

Before-filters are evaluated before each request, and can read the request and read/modify the response.
To stop execution, use halt:

before((request, response) -> {
    boolean authenticated;
    // ... check if authenticated
    if (!authenticated) {
        halt(401, "You are not welcome here");
    }
});

After-filters are evaluated after each request, and can read the request and read/modify the response:

after((request, response) -> {
    response.header("foo", "set by after filter");
});

Filters optionally take a pattern, causing them to be evaluated only if the request path matches that pattern:

before("/protected/*", (request, response) -> {
    // ... check if authenticated
    halt(401, "Go Away!");
});

Redirects

You can trigger a browser redirect with the redirect method on the Response:

response.redirect("/bar");

You can also trigger a browser redirect with specific HTTP 3XX status code:

response.redirect("/bar", 301); // moved permanently

Redirect API

There is also a convenience API for redirects which can be used directly without the Response:

// redirect a GET to "/fromPath" to "/toPath"
redirect.get("/fromPath", "/toPath");

// redirect a POST to "/fromPath" to "/toPath", with status 303
redirect.post("/fromPath", "/toPath", Redirect.Status.SEE_OTHER);

// redirect any request to "/fromPath" to "/toPath" with status 301
redirect.any("/fromPath", "/toPath", Redirect.Status.MOVED_PERMANENTLY);

Remember to import it statically instead of prefixing it as Spark.redirect

Exception Mapping

To handle exceptions of a configured type for all routes and filters:

get("/throwexception", (request, response) -> {
    throw new YourCustomException();
});

exception(YourCustomException.class, (exception, request, response) -> {
    // Handle the exception here
});

Static Files

You can assign a folder in the classpath serving static files with the staticFileLocation method. Note that the public directory name is not included in the URL.
A file /public/css/style.css is made available as http://{host}:{port}/css/style.css

staticFiles.location("/public"); // Static files

You can also assign an external folder (a folder not in the classpath) to serve static files by using the externalStaticFileLocation method.

staticFiles.externalLocation(System.getProperty("java.io.tmpdir"));

Cache/Expire time

You can specify the expire time (in seconds). By default there is no caching.

staticFiles.expireTime(600); // ten minutes

Setting custom headers

staticFiles.header("Key-1", "Value-1");
staticFiles.header("Key-1", "New-Value-1"); // Using the same key will overwrite value
staticFiles.header("Key-2", "Value-2");
staticFiles.header("Key-3", "Value-3");

ResponseTransformer

Mapped routes that transforms the output from the handle method. This is done by extending the ResponseTransformer and pass this to the mapping method. Example Of a route transforming output to JSON using Gson:

import com.google.gson.Gson;

public class JsonTransformer implements ResponseTransformer {

    private Gson gson = new Gson();

    @Override
    public String render(Object model) {
        return gson.toJson(model);
    }

}

and how it is used (MyMessage is a bean with one member 'message'):

get("/hello", "application/json", (request, response) -> {
    return new MyMessage("Hello World");
}, new JsonTransformer());

You can also use Java 8 method references, since ResponseTransformer is an interface with one method:

Gson gson = new Gson();
get("/hello", (request, response) -> new MyMessage("Hello World"), gson::toJson);

Views and Templates

A TemplateViewRoute is built up by a path (for url-matching) and the template engine holding the implementation of the 'render' method. Instead of returning the result of calling toString() as body the TemplateViewRoute returns the result of calling render method.

The primary purpose of this kind of Route is to provide a way to create generic and reusable components for rendering output using a Template Engine.

Velocity

Renders objects to HTML using the Velocity template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-velocity</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Freemarker

Renders objects to HTML using the Freemarker template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-freemarker</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Mustache

Renders objects to HTML using the Mustache template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-mustache</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Handlebars

Renders objects to HTML using the Handlebars template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-handlebars</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Jade

Renders objects to HTML using the Jade template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-jade</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Thymeleaf

Renders objects to HTML using the Thymeleaf template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-thymeleaf</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Jetbrick

Renders objects to HTML using the Jetbrick template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-jetbrick</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Pebble

Renders objects to HTML using the Pebble template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-pebble</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Water

Renders objects to HTML using the Water template engine.

Maven dependency:

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-template-water</artifactId>
    <version>2.3</version>
</dependency>

Source and example on GitHub

Embedded web server

Standalone Spark runs on an embedded Jetty web server.


Port

By default, Spark runs on port 4567. If you want to set another port use port. This has to be done before using routes and filters:

port(9090); // Spark will run on port 9090

Secure (HTTPS/SSL)

You can set the connection to be secure via the secure method. This has to be done before any route mapping:

secure(keystoreFilePath, keystorePassword, truststoreFilePath, truststorePassword);

If you need more help, check out the FAQ.

ThreadPool

You can set the maximum number of threads easily:

int maxThreads = 8;
threadPool(maxThreads);

You can also configure the minimum numbers of threads, and the idle timeout:

int maxThreads = 8;
int minThreads = 2;
int timeOutMillis = 30000;
threadPool(maxThreads, minThreads, timeOutMillis);

Waiting for Initialization

You can use the method awaitInitialization() to check if the server is ready to handle requests. This is usually done in a separate thread, for example to run a health check module after your server has started.
The method causes the current thread to wait until the embedded Jetty server has been initialized. Initialization is triggered by defining routes and/or filters. Hence, if you're using just one thread don't put this before you define your routes and/or filters.

awaitInitialization(); // Wait for server to be initialized

WebSockets

WebSockets provide a protocol full-duplex communication channel over a single TCP connection, meaning you can send message back and forth over the same connection.

WebSockets only works with the embedded Jetty server, and must be defined before regular HTTP routes. To create a WebSocket route, you need to provide a path and a handler class:

webSocket("/echo", EchoWebSocket.class);
init(); // Needed if you don't define any HTTP routes after your WebSocket routes
import org.eclipse.jetty.websocket.api.*;
import org.eclipse.jetty.websocket.api.annotations.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;

@WebSocket
public class EchoWebSocket {

    // Store sessions if you want to, for example, broadcast a message to all users
    private static final Queue<Session> sessions = new ConcurrentLinkedQueue<>();

    @OnWebSocketConnect
    public void connected(Session session) {
        sessions.add(session);
    }

    @OnWebSocketClose
    public void closed(Session session, int statusCode, String reason) {
        sessions.remove(session);
    }

    @OnWebSocketMessage
    public void message(Session session, String message) throws IOException {
        System.out.println("Got: " + message);   // Print message
        session.getRemote().sendString(message); // and send it back
    }

}

Other web server

To run Spark on a web server (instead of the embedded jetty server), an implementation of the interface spark.servlet.SparkApplication is needed. You have to initialize the routes in the init() method, and the following filter has to be configured in your web.xml:

<filter>
    <filter-name>SparkFilter</filter-name>
    <filter-class>spark.servlet.SparkFilter</filter-class>
    <init-param>
        <param-name>applicationClass</param-name>
        <param-value>com.company.YourApplication</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>SparkFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

GZIP

GZIP is done automatically if it's in both the request and the response headers. This usually only means that you have to set it in your response headers.

If you want to GZIP a single response, you can add it manually to your route:

get("/some-path", (request, response) -> {
    // code for your get
    response.header("Content-Encoding", "gzip");
});

If you want to GZIP everything, you can use an after-filter

after((request, response) -> {
    response.header("Content-Encoding", "gzip");
});

Javadoc

After getting the source from GitHub run:

mvn javadoc:javadoc

The result is put in /target/site/apidocs

Examples and FAQ

Examples can be found on the project's page on GitHub.

How do I upload something?

Note: This applies to the standard configuration of Spark. If you're using Spark with some other webserver, this might not apply to you.

To upload a file you need a form and a post handler. First, create a form with the correct enctype, and an input field with the type "file" and a name of your choice (here "upoaded_file"):

<form method='post' enctype='multipart/form-data'>
    <input type='file' name='uploaded_file'>
    <button>Upload picture</button>"
</form>"

For Spark to be able to extract the uploaded file, you have to set a specific request attribute, which allows to use the getPart method on the raw request:

post("/yourUploadPath", (request, response) -> {
    request.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp"));
    try (InputStream is = request.raw().getPart("uploaded_file").getInputStream()) {
        // Use the input stream to create a file
    }
    return "File uploaded";
});

The Java-IO-stuff is left out as it's not Spark-specific, but you can see a fully working example here.

How do I enable SSL/HTTPS?

Enabling HTTPS/SSL requires you to have a keystore file, which you can generate using the Java keytool (→ oracle docs). Once you have the keystore file, just point to its location and include its password.

String keyStoreLocation = "deploy/keystore.jks";
String keyStorePassword = "password";
secure(keyStoreLocation, keyStorePassword, null, null);

Check out the fully working example on GitHub if you need more guidance.

How do I enable logging?

You might have seen this message when starting Spark:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

To enable logging, just add the following dependency to your project:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.21</version>
</dependency>

How do I enable automatic refresh of static files?

If you use staticFiles.location(...), meaning you keep your static files in the classpath, static resources are copied to a target folder when you build your application. This means you have to make/build your project in order to refresh static files. A workaround for this is to tell Spark to read static files from the absolute path to the src-directory. If you do this you will see changes instantly when you refresh, but if you build a jar file it will only work on your computer (because of the absolute path). So, only use this during development.

if (localhost) {
    String projectDir = System.getProperty("user.dir");
    String staticDir = "/src/main/resources/public";
    staticFiles.externalLocation(projectDir + staticDir);
} else {
    staticFiles.location("/public");
}