Serving static resources in Javalin running as servlets

Javalin is a nice JVM-based microframework targetted at web APIs supporting Java and Kotlin as implementation language. Usually, it uses Jetty and runs standalone on the server or in a container.

However, those who want or need to deploy it to a servlet container/application server like Tomcat or Wildfly can do so by only changing a few lines of code and annotating at least one Url as a @WebServlet. Most of your application will continue to run unchanged.

But why do I say only “most of your application”?

Unfortunately, Javalin-jetty and Javalin-standalone do not provide complete feature parity. One important example is serving static resources, especially, if you do not want to only provide an API backend service but also serve resources like a single-page-application (SPA) or an OpenAPI-generated web interface.

Serving static resources in Javalin-jetty

Serving static files is straightforward and super-simple if you are using Javalin-jetty. Just configure the Javalin app using config.addStaticFiles() to specify some paths and file locations and your are done.

The OpenAPI-plugin for Javalin uses the above mechanism to serve it’s web interface, too.

Serving static resources in Javalin-standalone

Javalin-standalone, which is used for deployment to application servers, does not support serving static files as this is a jetty feature and standalone is built to run without jetty. So the short answer is: you can not!

The longer answer is, that you can implement a workaround by writing a servlet based on Javalin-standalone to serve files from the classpath for certain Url-paths yourself. See below a sample implementation in Kotlin using Javalin-standalone to accomplish the task:

package com.schneide.demo

import io.javalin.Javalin
import io.javalin.http.Context
import io.javalin.http.HttpCode
import java.net.URLConnection
import javax.servlet.annotation.WebServlet
import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

private const val DEFAULT_CONTENT_TYPE = "text/plain"

@WebServlet(urlPatterns = ["/*"], name = "Static resources endpoints")
class StaticResourcesEndpoints : HttpServlet() {
    private val wellknownTextContentTypes = mapOf(
        "js" to "text/javascript",
        "css" to "text/css"
    )

    private val servlet = Javalin.createStandalone()
        .get("/") { context ->
            serveResource(context, "/public", "index.html")
        }
        .get("/*") { context ->
            serveResource(context, "/public")
        }
        .javalinServlet()!!

    private fun serveResource(context: Context, prefix: String, fileName: String = "") {
        val filePath = context.path().replace(context.contextPath(), prefix) + fileName
        val resource = javaClass.getResourceAsStream(filePath)
        if (resource == null) {
            context.status(HttpCode.NOT_FOUND).result(filePath)
            return
        }
        var mimeType = URLConnection.guessContentTypeFromName(filePath)
        if (mimeType == null) {
            mimeType = guessContentTypeForWellKnownTextFiles(filePath)
        }
        context.contentType(mimeType)
        context.result(resource)
    }

    private fun guessContentTypeForWellKnownTextFiles(filePath: String): String {
        if (filePath.indexOf(".") == -1) {
            return DEFAULT_CONTENT_TYPE
        }
        val extension = filePath.substring(filePath.lastIndexOf('.') + 1)
        return wellknownTextContentTypes.getOrDefault(extension, DEFAULT_CONTENT_TYPE)
    }

    override fun service(req: HttpServletRequest?, resp: HttpServletResponse?) {
        servlet.service(req, resp)
    }
}

The code performs 3 major tasks:

  1. Register a Javalin-standalone app as a WebServlet for certain URLs
  2. Load static files bundled in the WAR-file from defined locations
  3. Guess the content-type of the files as good as possible for the response

Feel free to use and modify the code in your project if you find it useful. I will try to get this workaround into Javalin-standalone if I find the time to improve feature-parity between Javalin-jetty and Javalin-standalone. Until then I hopy you find the code useful.

Kotlin and null-safety

This week I installed the Android Studio 3.0 preview in preparation for the development of an Android tablet app. Android Studio is based on JetBrains’ IntelliJ IDE. Google recently announced that Android Studio will support Kotlin as an official programming language for Android starting with version 3.0. The language has been designed and developed by JetBrains since 2010.

Kotlin is a language for the Java ecosystem like Scala, Groovy or Clojure that targets both the JVM and Google’s Dalvik VM, which is used for Android. It’s a statically typed language and it has a similar feature set as Scala and C#. Compared to Java it adds things like operator overloading, short syntax for properties, type inference, extension functions, string templates and it supported lambda expressions since before Java 8. But it also fixes some of Java’s inconsistencies. For example, it provides a unified type system with the Any type at the top of the type hierarchy and without special raw types. Arrays in Kotlin are invariant, and it uses declaration-site variance instead of use-site variance (see my other blog post for an explanation of these terms: Declaration-site and use-site variance explained). However, in my opinion the most interesting of Kotlin’s features is null-safety.

Null-safety

In Kotlin all types are non-nullable by default. You can’t assign null to a variable declared as

var s: String = "hi";

If you really want to be able to assign null to a variable you have to declare it with a question mark after the type, for example

var s: String? = null;

However, if you want to access a member of nullable reference or call a method on it, you have to perform a null check before doing so. This is enforced by the compiler. 

if (s != null) {
    return s.toUpperCase();
}

The compiler keeps track of the null checks before accessing a member of a nullable reference. Without the check the code wouldn’t compile. Kotlin offers some additional operators to simplify these null checks, like the safe navigation operator ?. (also known from Groovy and C# 6.0) or the “Elvis” operator ?:

person?.address?.country?.name
s?.toUpperCase() ?: ""

With Kotlin’s null-safety feature NullPointerExceptions are a thing of the past.

Kotlin has a lot more to offer and we haven’t decided yet if we will use it for our new Android app project, but it’s definitely an option to consider.