Mapless logo


Schema-less persistence for Smalltalk with support for multiple backends.

RESTful APIs with Mapless and Teapot

Install Teapot

A RESTful API needs an HTTP so let’s install Teapot as it’s very comfortable to use in .

Pharo Playground

"Loads the HTTP application server in Phar.
If while loading you get a dialog asking for confirmation on Load/Merge/Cancel select Load."
Metacello new
  baseline: 'Teapot';
  repository: 'github://zeroflag/Teapot:v2.7.0/source';

"Load latest version of Mapless with its default backends (Memory and SQLite)"
Metacello new
  baseline: 'Mapless';
  repository: 'github://sebastianconcept/Mapless:v0.6.0/src';
Configure the server

Pharo Playground

"Configure Teapot defaults"
teapot := Teapot configure: {
		#port -> 9090.
		#debugMode -> true.
		#defaultOutput -> #html

"Add an exception handler to fail gracefully"
teapot exception: Error -> [ :ex :req |
  | content |
  content := (Smalltalk isHeadless and: [ Smalltalk isInteractiveGraphic ])
  ifTrue: [ 'Ouch: {1}' format: { ex messageText } ]
  ifFalse: [ 'Internal error' ].
  TeaResponse serverError body: content.

"Optionally add a ping route to use as health-check / availability check"
teapot GET: '/ping' -> 'pong'.  
Give structure to your API

Lets say we’re going to implement one endpoint for Tweet objects in a SimpleTwitter backend. With this /tweets endpoint, we’re going to be able to do CRUD operations following the RESTful system.

Pharo Playground

"Create an Mapless model, following the SimpleTwitter app, a Tweet class"
Mapless subclass: #Tweet
	instanceVariableNames: ''
	classVariableNames: ''
	package: 'SimpleTwitter-Mapless'
Setup routes

We need to implement the CRUD operations in their respective routes.

Pharo Playground

teapot POST: '/tweets' -> [ :req | 
  "to be done" 

Pharo Playground

teapot GET: '/tweets/<tweetId>' -> [ :req | 
  "Use as ID value that was given as part of the URI path to find a corresponding Tweet"
  found := repository findOne: Tweet atId: (req at: #tweetId).

  "Return a 404 if none was found"
  found ifNil:[ ^ TeaResponse notFound ].

  "Return the tweet found "
  { #author -> found author.
  #text -> found text } asDictionary
  output: #json.

Pharo Playground

teapot PUT: '/tweets/<tweetId>' -> [ :req | "to be done"  ].

Pharo Playground

teapot DELETE: '/tweets/<tweetId>' -> [ :req | "to be done" ].

Pharo Playground

"Start the HTTP server."
teapot start.

"Stop the HTTP server."
teapot stop.

Mapless source code in GitHub

Brought to you by Flowing

Since April 2014