4 JVM Web Frameworks
-
Upload
joe-kutner -
Category
Internet
-
view
370 -
download
0
Transcript of 4 JVM Web Frameworks
![Page 1: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/1.jpg)
@codefinger#Devoxx #YourTagHere
4 JVMWeb Frameworks
in 40 minutes
![Page 2: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/2.jpg)
@codefinger#Devoxx #YourTagHere
in 50 minutes
4 JVMWeb Frameworks4 JVMWeb Frameworks
with 10 minutes for questions
![Page 3: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/3.jpg)
@codefinger#Devoxx #YourTagHere
in 50 minutes
4 JVMWeb Frameworks4 JVMWeb Frameworks
with 10 minutes for questions±5 minutes
![Page 4: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/4.jpg)
@YourTwitterHandle#Devoxx #YourTag
Joe Kutner@codefinger
JVM Platform Owner
![Page 5: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/5.jpg)
@YourTwitterHandle#Devoxx #YourTag
![Page 6: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/6.jpg)
@YourTwitterHandle#Devoxx #YourTag
Alternative JVM languages
![Page 7: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/7.jpg)
Scala Groovy
JRuby Clojure
![Page 8: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/8.jpg)
What is a even a web framework??
![Page 9: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/9.jpg)
2015
2000
Model
View
Controller
![Page 10: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/10.jpg)
Model
View
Controller
2015
2000
MongoDB Redis Active
MQ
AJAX
WebSocket
CSS
Events AsyncIORESTSOAP
Auth
Logs
![Page 11: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/11.jpg)
Full Stack (big circle)MRAAWC
EARSALM
MicroMRA
AWC
EARS
ALM (little circle)
NanoQ
(no circle)
![Page 12: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/12.jpg)
Full Stack
Micro
Nano
![Page 13: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/13.jpg)
Templating
Server
Docs
Stack
Tooling
Language Scala/Java
Play
Netty
A-
activator/sbt
Persistence Slick
Testing ScalaTest
Full
Groovy/Java
Groovy
Netty
B+
Gradle
—
—
Micro
JRuby
ERB
Torquebox
A+
Rake
ActiveRecord
Minitest
Full
Clojure
Hiccup
Immutant
B+
Lein
Yesql
clojure.test
Nano?
![Page 14: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/14.jpg)
Full Stack Reactive Opinionated
![Page 15: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/15.jpg)
Client Server Database
Block wait
Async IO
![Page 16: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/16.jpg)
Client Server Database
Async wait
Async IO
![Page 17: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/17.jpg)
Client Server PostgreSQL MongoDB
Async IO
![Page 18: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/18.jpg)
Client Server PostgreSQL MongoDB
Client Server PostgreSQL MongoDB
Client Server PostgreSQL MongoDB
Async IO
![Page 19: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/19.jpg)
Demo Time
![Page 20: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/20.jpg)
Tooling
![Page 21: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/21.jpg)
Templating
@(customer: Customer, orders: List[Order])
<h1>Welcome @customer.name!</h1>
<ul> @for(order <- orders) { <li>@order.title</li> } </ul>
val content = views.html.Hello.index(c, o)
![Page 22: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/22.jpg)
HikariCP
Database
![Page 23: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/23.jpg)
Database Functional Relational Mapping
coffees.filter(_.price < 10.0)
![Page 24: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/24.jpg)
val crossJoin = for { (c, s) <- coffees join suppliers } yield (c.name, s.name)
Database
select x2."COF_NAME", x3."SUP_NAME" from "COFFEES" x2 inner join "SUPPLIERS" x3
compiles to…
Functional Relational Mapping
![Page 25: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/25.jpg)
val fullOuterJoin = for { (c, s) <- coffees joinFull suppliers on (_.supID === _.id) } yield (c.map(_.name), s.map(_.name))
Database
select x2."COF_NAME", x3."SUP_NAME" from "COFFEES" x2 full outer join "SUPPLIERS" x3 on x2."SUP_ID" = x3."SUP_ID"
compiles to…
Functional Relational Mapping
![Page 26: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/26.jpg)
Database Evolutions
conf/ ├─ evolutions │ └── default │ ├── 1.sql │ └── 2.sql
# --- !Ups
create table "people" ( "id" serial not null primary key, "name" varchar not null, "age" int not null );
# --- !Downs
drop table "people" if exists;
![Page 27: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/27.jpg)
Streaming HTTP
def index = Action { val s = getDataStream val d: Enumerator[Array[Byte]] = Enumerator.fromStream(s) Ok.chunked(d) }
![Page 28: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/28.jpg)
Websockets (with Actors)
class MyWebSocketActor(out: ActorRef) extends Actor { def receive = { case msg: String => out ! ("I received your message: " + msg) } }
WebSocket.acceptWithActor[String, String] { request => out => MyWebSocketActor.props(out) }
![Page 29: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/29.jpg)
ScalaTest
class StackSpec extends PlaySpec {
"A Stack" must { "pop values in last-in-first-out order" in { val stack = new Stack[Int] stack.push(1) stack.push(2) stack.pop() mustBe 2 stack.pop() mustBe 1 } "throw NoSuchElementException if an empty stack is popped" in { val emptyStack = new Stack[Int] a [NoSuchElementException] must be thrownBy { emptyStack.pop() } } } }
Testing
$ activator ~test
![Page 30: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/30.jpg)
Pros
Great for…
• Traditional web apps with lots of IO• Getting something up and running fast• High Powered apps, which is often mutually exclusive
with getting started fast.
![Page 31: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/31.jpg)
Cons
Not so great if…
• You don’t like heavy-handed tools• You like backward compatibility
![Page 32: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/32.jpg)
Templating
Server
Docs
Stack
Tooling
Language Scala/Java
Play
Netty
A-
activator/sbt
Persistence Slick
Testing ScalaTest
Full
Groovy/Java
Groovy
Netty
B+
Gradle
—
—
Micro
JRuby
ERB
Torquebox
A+
Rake
ActiveRecord
Minitest
Full
Clojure
Hiccup
Immutant
B+
Lein
Yesql
clojure.test
Nano
![Page 33: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/33.jpg)
Microframework Asynchronous Unopinionated
![Page 34: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/34.jpg)
![Page 35: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/35.jpg)
Async IO
Client Server Database
Async wait
![Page 36: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/36.jpg)
Demo
Templating
Time
![Page 37: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/37.jpg)
Database
?
![Page 38: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/38.jpg)
Testing
?
![Page 39: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/39.jpg)
Spring Hysterix
Integrations!
Pac4j
DropwizardRxJava
![Page 40: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/40.jpg)
ratpack { bindings { module DropwizardMetricsModule }
handlers { all { MetricsRegistry -> mr mr.counter(“request-count”).inc() next() } get { // ... } } }
Metrics Dropwizard
![Page 41: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/41.jpg)
ratpack { bindings { modules HystrixModule }
handlers { get(“users”) { new HysterixObservableCommand<User>(... //... } } }
}
Fault Tolerance Hystrix
Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.
![Page 42: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/42.jpg)
ratpack {
handlers { get { httpClient.get(“http://host”.toURI()) { s -> s .headers { h -> h.set(HttpHeaderNames.ACCEPT, “application/json”) } }.then { resp -> render(resp) } } }
}
Non-blocking HTTP Client
![Page 43: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/43.jpg)
Templating
Server
Docs
Stack
Tooling
Language Scala/Java
Play
Netty
A-
activator/sbt
Persistence Slick
Testing ScalaTest
Full
Groovy/Java
Groovy
Netty
B+
Gradle
—
—
Micro
JRuby
ERB
Torquebox
A+
Rake
ActiveRecord
Minitest
Full
Clojure
Hiccup
Immutant
B+
Lein
Yesql
clojure.test
Nano
![Page 44: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/44.jpg)
vs.
StrengthsNetty Netty
Full-Stack Microservices
Traditional Web-app API, Circuit Breaker
Weaknesses
Monolith New(ish)
Async IO Async IO
Backward Compatibility Docs
![Page 45: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/45.jpg)
Demo
@codefinger#Devoxx #LameSlideTemplate
![Page 46: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/46.jpg)
@codefinger#Devoxx #YourTagHere
in 50 minutes
4 JVMWeb Frameworks4 JVMWeb Frameworks
with 10 minutes for questions±5 minutes
with a few minutes for intermission
![Page 47: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/47.jpg)
why java?
![Page 48: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/48.jpg)
Full Stack Convention Opinionated
![Page 49: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/49.jpg)
Full Stack
![Page 50: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/50.jpg)
Synchronous IO
Client Server Database
Block wait
![Page 51: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/51.jpg)
Demo Time
![Page 52: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/52.jpg)
Tooling
$ rails new
$ rails generate
$ rails asset:precompile
$ rails server
$ rake routes
![Page 53: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/53.jpg)
Templating ERB
<% @books.each do |book| %> <tr> <td><%= book.title %></td> <td><%= book.content %></td> <td><%= link_to "Show", book %></td> <td><%= link_to "Edit", edit_book_path(book) %></td> </tr><% end %>
![Page 54: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/54.jpg)
Database ActiveRecord
class Person < ActiveRecord::Baseend
class CreatePerson < ActiveRecord::Migration def change create_table :persons do |t| t.string :name t.references :bodyguard t.integer :age t.timestamps null: false end endend
![Page 55: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/55.jpg)
Torquebox
![Page 56: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/56.jpg)
Torquebox
![Page 57: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/57.jpg)
Templating
Server
Docs
Stack
Tooling
Language Scala/Java
Play
Netty
A-
activator/sbt
Persistence Slick
Testing ScalaTest
Full
Groovy/Java
Groovy
Netty
B+
Gradle
—
—
Micro
JRuby
ERB
Torquebox
A+
Rake
ActiveRecord
Minitest
Full
Clojure
Hiccup
Immutant
B+
Lein
Yesql
clojure.test
Nano
![Page 58: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/58.jpg)
vs.
StrengthsNetty Torquebox
Full-Stack Full-Stack
Traditional Web App Traditional Web App
Weaknesses
Complex (Scala) Opinionated
Async IO
Flexible
Mature
Approachable (Ruby)
Async IO
![Page 59: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/59.jpg)
Nano Modular (Un)opinionated
![Page 60: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/60.jpg)
Libraries
![Page 61: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/61.jpg)
F****work is a dirty word
Fordevelopers…
![Page 62: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/62.jpg)
Demo Time
![Page 63: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/63.jpg)
REPL Driven Development
![Page 64: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/64.jpg)
![Page 65: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/65.jpg)
Templating
Hiccup Selmer
(html [:ul (for [x (range 1 4)] [:li x])])
<ul>{% for item in items %}<li> {{item}} </li>{% endfor %}</ul>
![Page 66: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/66.jpg)
ClojureScript
var zero = 0; if (zero) { console.log("Nope!");} else { console.log("Zero is false!");}
(def zero 0) (if zero (println "Zero is not false!"))
Javascript ClojureScript
![Page 67: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/67.jpg)
Database
(with-transaction [t-conn conn] (create-user! {:id "foo" :first_name "Sam" :last_name "Smith"}) (get-user {:id "foo"}))
Yesql
--name: create-user!-- creates a new user recordINSERT INTO users(id, first_name, last_name)VALUES (:id, :first_name, :last_name)
![Page 68: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/68.jpg)
Server
Immutant
caching
messaging
scheduling
transactions
logging
websockets
![Page 69: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/69.jpg)
Websockets
(defn reverser "An example WebSocket app" [request] (async/as-channel request {:on-open (fn [channel] (async/send! channel "Ready to reverse!")) :on-message (fn [channel m] (async/send! channel (apply str (reverse m)))) :on-close (fn [channel {:keys [code reason]}] (println "close code:" code "reason:" reason))}))
![Page 70: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/70.jpg)
Templating
Server
Docs
Stack
Tooling
Language Scala/Java
Play
Netty
A-
activator/sbt
Persistence Slick
Testing ScalaTest
Full
Groovy/Java
Groovy
Netty
B+
Gradle
—
—
Micro
JRuby
ERB
Torquebox
A+
Rake
ActiveRecord
Minitest
Full
Clojure
Hiccup
Immutant
B+
Lein
Yesql
clojure.test
Nano
![Page 71: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/71.jpg)
vs.
StrengthsNetty Immutant
Microservices Client-Side Web App
API, Circuit Breaker Traditional Web App
Weaknesses
Async IO
Async IO
ModularModular
Functional
Functional
![Page 72: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/72.jpg)
There is one thing all of these frameworks
have in common
NO WAR FILES
![Page 73: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/73.jpg)
modern JVM web development uses alternative languages
![Page 74: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/74.jpg)
![Page 75: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/75.jpg)
pick one
![Page 76: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/76.jpg)
Scala Groovy
JRuby Clojure
![Page 77: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/77.jpg)
$ lazybones create ratpack my-app
$ activator new my-app
$ rails new my-app
$ lein new luminous my-app
![Page 78: 4 JVM Web Frameworks](https://reader031.fdocuments.net/reader031/viewer/2022030302/587c978c1a28abfa5e8b65bd/html5/thumbnails/78.jpg)
@codefinger#Devoxx #YourTagHere
Joe Kutner@codefinger
JVM Platform Owner
thank you!