How to create a BedSheet Extension for SkySpark 3.0

BedSheet is a great Fantom framework for web applications. It provides not only an IoC container but also a rich Middleware mechanism for routing and manipulating HTTP content. But given I wrote BedSheet, I guess I'm also quite biased!
Anyway, BedSheet is built on top of Fantom's Wisp, one of the cornerstones of SkySpark. So just for fun I thought I'd build a SkySpark web extension that integrates with a BedSheet application - and it turned out to be quite easy.
Following is a SkySpark web Ext that delegates all web requests to BedSheet.
using skyarcd::Ext
using skyarcd::ExtMeta
using concurrent::AtomicRef
using afIoc
using afBedSheet::MiddlewarePipeline
using web::Weblet
@ExtMeta { name = "bedsheet" }
const class BedSheetExt : Ext, Weblet {
private const AtomicRef registryRef := AtomicRef(null)
private Registry registry {
get { registryRef.val }
set { registryRef.val = it }
}
private const AtomicRef pipelineRef := AtomicRef(null)
private MiddlewarePipeline pipeline {
get { pipelineRef.val }
set { pipelineRef.val = it }
}
override Void onStart() {
this.registry = RegistryBuilder().addModulesFromPod("afBedSheet").addModule(AppModule#).build
this.pipeline = registry.activeScope.serviceById(MiddlewarePipeline#.qname)
}
override Void onService() {
registry.activeScope.createChild("request") {
// this is the actual call to BedSheet!
pipeline.service
}
}
override Void onStop() {
registry.shutdown
}
}
The actual BedSheet application I used is just the Quick Start example from the BedSheet documentation.
using afIoc
using afBedSheet
const class AppModule {
@Contribute { serviceType=Routes# }
Void contributeRoutes(Configuration conf) {
conf.add(Route(`/`, Text.fromHtml("<html><body>Welcome to BedSheet!</body></html>")))
conf.add(Route(`/hello/**`, HelloPage#hello))
}
}
class HelloPage {
Text hello(Str name, Int iq := 666) {
return Text.fromPlain("Hello! I'm $name and I have an IQ of $iq!")
}
}
And for completeness, here is my build.fan
using build
class Build : BuildPod {
new make() {
podName = "afBedSheetExt"
summary = "My Awesome BedSheetExt Project"
version = Version("1.0")
index = [
"skyarc.ext": "afBedSheetExt::BedSheetExt"
]
depends = [
// ---- Core Fantom ----
"sys 1.0.69 - 1.0",
"web 1.0.69 - 1.0",
"concurrent 1.0.69 - 1.0",
// ---- Sky Spark ----
"skyarcd 3.0.6 - 3.0",
// ---- BedSheet ----
"afIoc 3.0.4 - 3.0",
"afBedSheet 1.5.2 - 1.5",
]
srcDirs = [`fan/`]
resDirs = [`locale/`]
}
}
It was then a simple case of building the pod, adding it to SkySpark and enabling the ext in an example project.
I then used the following URLS to test the BedSheet application:
C:\> curl http://localhost:8080/api/example/ext/bedsheet/ <html><body>Welcome to BedSheet!</body></html> C:\> curl http://localhost:8080/api/example/ext/bedsheet/hello/Traci/69 Hello! I'm Traci and I have an IQ of 69! C:\> curl http://localhost:8080/api/example/ext/bedsheet/hello/Luci Hello! I'm Luci and I have an IQ of 666!
And I could see the usual re-assuring Alien-Factory logo in the SkySpark console window.
Note that BedSheet has it's own pod dependencies which also need copying to SkySpark's /lib/fan/ dir:
But how you may maintain and distribute these with your SkySpark application is an entirely different problem!
Edits
- 29 April 2017 - Posted article on Alien-Factory.
- 18 October 2016 - Original article posted on SkyFoundry Forum.