Scalatra-Scalate 2. The Storm

Robert Crowther Apr 2022

PrevNext

In this guide, I take some unusual stances. I assume you can code, and will look up what you don’t know. I assume you know nothing about these languages (in truth, I know little). I assume you know little about the software—I don’t, but wanted to do a job. Then, I act and talk abruptly. This I know—Scala is not Java, but the support is, and outsiders in the world of Java must act violent and fast—otherwise they are dead. One result of this is that this guide is a non‐stop deluge of information and opinion. You will need it.

What is Scalatra? What is Sinatra?

Scalatra is a clone (not identical) of Sinatra. Sinatra is code written in Ruby. Sinatra is a web‐server with a genius interface. What do I mean, ‘genius’? Works like this… you say to the API what web requests you want to catch, catch them, do something with them, then return some configured material. No database, no templates, no controllers, no folder layouts, no configuration, no classes, usually no permissions. Here’s pseudo‐code for what you might do in a Sinatra clone,

import usefulCodebasesForReadingRequestsAndCreatingResponses
...

# web request arrives here...
WebRequestHandler {

# catch the root request
def get("/") {
  # respond with this text to the request
  return "HomePage!"
}

# Catch a request with a two digit number after it e.g. '/art/33',
# then call the captured number 'id'. Uses regex.
def get("/art/id:re(/d/d?)") {
  var id = params('is')

  # We could do something with the 'id', such as get information,
  # or reform a shape based on the number etc.
  # but for this test I return that number as a string
  return str(id)
}

The form of the code depends on the language.

Sinatra, and it’s clones, are refreshing to use. In the complexity of web apps, it’s easy to forget that the front action of a server is to capture a request then respond. But then, you may ask, what use this? Fair enough. You will never construct ‘a website’ using a Sinatra‐clone—a ‘website’ needs data to work from, so a database. It needs to form pages from database data, so needs templates. It needs to route urls via a system, sometimes automatic. And it needs hunks of protection, and utility code, and webforms.

But where Sinatra‐clones kick in is when we talk about a web‐based utility. Any kind of action where we need to respond to a URL, not with pages of HTML dragged from a database, but snippets of information. For example, JSON data. Getting JSON data and carving it up is a small coding exercise, but you need then to deliver the data as a reply to a request. Or maybe you’re delivering images, and tired of reconfiguring heavyweight servers? Don’t—route requests to a Sinatra‐clone, then handle the requests with a nice, maintainable API. So the API is refreshing, obvious and, in some circumstances, there is a time to use Sinatra or a clone. Which is why Sinatra has been rewritten in different computer languages but, that said, not so many languages can manage this trick.

Base of this post

I use Linux. And a Debian variant (doesn’t matter which). The Sinatra‐clone is called ‘Scalatra’. It is written in the language Scala. Scala runs on the Java Virtual Machine. After that, it’s nothing like Java. At all. The issue is that Scala may not be Java, but uses many of the tools. And Java tools are a horror show. Much of the time, Scala will protect us. But not all.

Get Scala

That means having a JVM. There are two ways to go about this. The official way is official and best and guaranteed to work. Download and install an Oracle JVM. I’m not doing that, for too many reasons to list here. I’m going with my operating system’s builtin OpenJDK variant. I have reasons for belief it will work (apologies for disabling your self‐empowerment, but don’t ask me how I know, Java‐world is like this).

After that, we need Scala. Well, I know something about this, too—we won’t need it. The tools we are about to install will put it there for us (don’t ask me how I know, Java‐world is like this).

Install SBT

This is where the Java‐nightmare crawls in. The Scalatra install instructions include near a thousand paths to get the thing up and running. None of them apply to this guide. Bottom line is, get SBT running.

SBT is associated with Scala, though not exclusively. SBT stands for Simple Build Tool. It isn’t. That said, SBT runs in a different world to other Java build tools, so maybe the coders have a point. The SBT instructions have evolved from the days when the writers insulted their users, but they’re still a battle. Ignore the oh‐so‐professional FUD on the SBT installation page, and run the distribution instructions for installing a Debian package. Then wait a long time (Java‐world is like this).

Download and build a Scalatra

More gnomic Java. First, choose a directory to place the project in. Navigate there. Issue this command,

 sbt new scalatra/scalatra.g8

Don’t ask what it is or means. This will create a new deluge of Java‐informacy—you may even have time for a brew. If you own only a fifteen‐core computer.

This command will not finish. After your brew, you will find your terminal stalled, asking for an ‘organization’. You may feel pleased that Java thinks you are an organisation, but you are not, so you must pretend you are. The Scalatra instructions, with admirable calm, suggest ‘com.github.username’. That’s not the end of this, the download code will ask maybe seven other questions. Thankfully, the code also offers reasonable defaults. The one question I would take care with is the ‘name’ of the project. Make it short, distinctive, lower‐case, preferably one word. You’ll be using it. More deluge. then you hopefully reach a commandline prompt.

Ok, a little download. Nothing to worry about. Now you need SBT to build from what you downloaded. Run this,

sbt

More deluge. Does it ever stop? Time for coffee.

What have we here?

What we have now is a folder, organised by SBT. This contains a version of Scala (said you didn’t need to worry about that). It also contains the Scalatra code, all other necessary code, and a basic configuration, And a webserver called Jetty. If this has not happened, or SBT would not run true, abandon tutorial now. Don’t ask questions. Don’t try to understand. Don’t think StackOverflow will save you. Get out and work with your trauma.

It worked for me, so if it worked for you, you can confirm,

$ sbt
> ~jetty:start

The tithe is to start a continuous development environment, where the server restarts on code changes. Heavily recommended. Then try looking at,

http://localhost:8080.

It should return,

Hi there!

Never in the field of human endeavour has so much been installed by so many for so few. Ah,, but now you got the power. No ordinary API, Scalatra. No common development server, Jetty.

Java web server conventions

Or, Java‐mind‐warp. Inside these generated folders, someplace, is configuration for what is being returned when we tried the URL. It’s at,

/pathToTheProject/ProjectName/src/main/scala/PathMadeFromPArtsOfTheOrganisationURL/yourName/app/naameGivenForServlet.scala

This is your key file, where you declare, Sinatra‐like, where routes will point to and what they return. Go find. If this position seems insane, people do insane things for reasons. You need to work with it. The scattered directory placements form a common structure used by many Java servers. The Servlet idea is so that directories of code can be switched in and out of servers, while retaining strong security. Still, it’s intimidating.

The directory structure

To help, I’ll list a few of the most important places in this mass. First, the top level,

├── build.sbt
├── project
├── src
└── target

‘project’ is for SBT to structure the build in. You won’t go near it—use the ‘build.sbt’ file on the top level. ‘src’ is for source code, that’s where code will go. ‘target’ is where SBT builds code to. Again, you’ll not have much to do there, though you may root in it now and then, see what is happening.

Under the top level are insanely deep nests of directories. These follow the Java convention of naming directory structures after a URL e.g.

── src
│   ├── main
│   │   ├── resources
│   │   │   └── logback.xml
│   │   ├── scala
│   │   │   ├── com
│   │   │   │   └── yourName
│   │   │   │       └── app

Let’s repeat about this file, where build‐configuration info can be added,

/pathToTheProject/ProjectName/build.sbt

Lines added here tell SBT to auto‐download code libraries. So mention where SBT places library files—‐you’ll find a stash of JAR files here,

/pathToTheProject/ProjectName/target/webapp/WEB-INF/lib

And go look at,

/pathToTheProject/ProjectName/src/main/webapp/WEB-INF/web.xml

This is the ‘web.xml’ file. It points URLs at code and resources. Hopefully it is preconfigured, so you will never need to go near it. Finally, this important path in the ‘src’. ‘Webapp’ is where gear that the server needs will be located. It will be repeated in ‘target’.

├── src
│   ├── main
│   │   ├── resources
│   │   │   └── logback.xml
│   │   ├── scala
│   │   │   ├── com
│   │   │   │   └── rcrowther
│   │   │   │       └── app
│   │   │   │           └── ScalatraServelet.scala
│   │   │   └── ScalatraBootstrap.scala
│   │   └── webapp
│   │       └── WEB-INF

When an app is compressed and sent to a server, the server will look at directories from ‘webapp’ down.

Oh, there’s more—if you want a look, Scalatra itself has a guide to project structure . But let’s leave that there.

Looking at the Sinatra‐like call

Briefly. Scala, the language has the ability to make what it calls DSL. For you and me, that means Scala can write code that, when used, pretends to be part of the language. It’s not as hot as a language that can do this in full, like a basic LISP, but most languages can’t do this at all. The reason I’m telling you this is because the Scala code you will use can seem impossible. Here’s what was installed for me as a starter in the ‘Servlet.scala’ file (go up a section),

package com.magicbus.app

import org.scalatra._

class BluntServlet extends ScalatraServlet {

  get("/") {
    views.html.hello()
  }

}

Take it on face value. Or wonder how Scala knows to execute the methods inside the class (aside, the order of checks is bottom up. So put the easiest URL matches at the top, not the bottom). Wonder how this code has no need for a mark to define what a method is—no ‘def’ or ‘procedure’? That word, the method name ‘get’—is that the HTML method? Yes. And is that a Ruby‐like affair that there is no ‘return’ in the method, is Scala a last‐item‐in‐the‐method‐is‐the‐return convention? Yes.

This can get odder,

package com.rcrowther.app

import org.scalatra._

class ScalatraServlet extends ScalatraServlet {

  get("/") {
    views.html.hello()
  }

  get("/params-test") {
    println( multiParams("splat"))

    <html>
    <head><title>Test</title></head>
    <body>
    <h1>Params Test</h1>
    <dl>
      <dt>Found parameters:</dt>
      <dd>{multiParams}</dd>
    </dl>
    </body>
    </html>
  }
}

Two methods with the same name and parameter type? Clue, they’re not really ‘methods’, more configuration of an executable sequence. Printing with no conversion? Yes, all Scala data has a print method builtin (‘println’ is short for ‘printLine’). Where did ‘multiparams’ appear from with no declaration? It’s declared, allocated and passed in from the base code that scans the outer brackets. Yes, ‘multiparams’ contains parameters from the URL. How can HTML/XML be in code with no wrap‐marks or escapes? Because in Scala XML is a recognised type. Give it a go with,

http://127.0.0.1:8080/params-test?language=punjabi&shop=sweets&city=lahori

And watch those multiparams print! If you ask questions such as these, rather than following along, you may want to scan down the latest Scalatra Guides.

End of Part Two

If you’ve followed the above, or tried, the result is something else. I give a stream of warnings about what can go wrong. I warn you, this can can go wrong often. I warn you that when it goes bad, I can’t help you. I warn you to get out. I tell you how and where to run. I tell you this because to Java I am an outsider. I have been there enough to know what happens in Java to outsiders. Y’godda move.

But if you get there, it’s amazing, yes? The code above? Defies gravity. Now we wade thorns, Part Three awaits.