This tutorial was updated by Kendrick Wilson in 2017 to:
- Resolve issues with classloader
- Documented new installation process for groovy
- Update Spark version
- Add slf4j logging
Background
I just bought a Raspberry Pi to have some fun. First with code, and hopefully with hardware later.
After setting it up (with the Raspian OS, a Linux distro for the Pi), making sure it could connect to the internet and that I could ssh into it from my laptop, the first thing I wanted to do was to get it to run a webserver.
I recently attended a Java meetup (in fact, the very first one in Stockholm) where one of the speakers demoed the Spark micro-framework, and it really caught my attention. Starting up a webserver and providing a simple REST API (or just plain HTML) with Spark is as easy as it gets, but is it also that easy on the Pi?
Well, if you want to use Java, you would need to first get the required jars, then compile all sources before you can run anything. It’s not fun to manually download jars, place the files in the right places so that you can give Java and javac the right classpath and so on, specially in an environment where an IDE is not a viable option… There should be a better way. And of course, there is!
Getting groovy with it
I have previously written about how easy it is to set up a webserver using Groovy, so I was already inclined to use Groovy for this project… you see, using @Grab, all your dependencies will be downloaded automatically. No need to install Maven or Gradle! All you need, besides the JDK (which already comes installed in the Raspian image), is to have Groovy installed.
Now, you may ask, just how easy is it to install Groovy in the Raspberry Pi?
Well, here’s what you need to type in the terminal to get the job done:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install groovy
Note: here, we use sdkman to get Groovy. See http://sdkman.io
You can check that you have groovy installed by running:
groovy -version
Which should print something like:
Groovy Version: 2.4.10 JVM: 1.8.0 Vendor: Oracle Corporation OS: Linux
Setting up Spark
The environment is set up now, and all you have to do is write some code. And that’s the fun part! The code required to get started with Spark is ridiculously simple:
@Grab(group = 'com.sparkjava', module = 'spark-core', version = '2.5.5')
@GrabExclude('javax.servlet:javax.servlet-api')
@Grab(group = 'org.slf4j', module = 'slf4j-simple', version = '1.7.21')
import static spark.Spark.*
get '/hello', { req, res -> 'Hello from your groovy Sparkberry Pi!' }
Save this code in a file called Server.groovy.
Download servlet api to avoid classloader issues.
curl http://central.maven.org/maven2/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar -o javax.servlet-api-3.1.0.jar
groovy -cp javax.servlet-api-3.1.0.jar Server.groovy
Once you see some output from the application (which does take a little while in the Pi, unfortunately), hit the following URL with your browser (replace the IP address with your Raspberry Pi’s IP):
http://192.168.1.18:4567/hello
Notice that, even though Spark was written with Java 8 closures in mind, with the latest versions of Groovy, Groovy closures will also work just fine.
If you want to serve static files from a sub-directory (here “/public”), you just have to add this line:
staticFileLocation "public"
Building HTML
If you fancy serving some dynamic HTML as well, you can write plain Groovy code using the MarkupBuilder class.
Create another file in the same directory as Server.groovy called Page.groovy:
import groovy.xml.MarkupBuilder as Builder
static String createPage(Map queryParams) {
def writer = new StringWriter()
new Builder(writer).html {
h2 'A Dynamic Webpage!'
div(id: 'query-params') {
if (!queryParams) li 'No query parameters given'
else ul {
for (key in queryParams.keySet()) {
li "Query param: $key -> ${queryParams[key]}"
}
}
}
p "Current date: ${new Date()}"
}
writer.toString()
}
Now, your complete Server.groovy file should look like this:
@Grab(group = 'com.sparkjava', module = 'spark-core', version = '2.5.5')
@GrabExclude('javax.servlet:javax.servlet-api')
@Grab(group = 'org.slf4j', module = 'slf4j-simple', version = '1.7.21')
import static spark.Spark.*
println "Configuring server..."
staticFileLocation "public"
get '/hello', { req, res -> 'Hello from Groovy!' }
get '/page', { req, res -> Page.createPage(req.queryMap().toMap()) }
Now just run it! Let Groovy know there’s more than one Groovy file in the current directory by adding the classpath option as follows:
groovy -cp javax.servlet-api-3.1.0.jar:. Server.groovy
And that’s it. You’ve got a hassle-free webserver running on your Raspberry Pi in just a few minutes!