[HN Gopher] Javalin - a simple web framework for Java and Kotlin
___________________________________________________________________
Javalin - a simple web framework for Java and Kotlin
Author : saikatsg
Score : 133 points
Date : 2024-02-11 12:55 UTC (10 hours ago)
(HTM) web link (javalin.io)
(TXT) w3m dump (javalin.io)
| dkpk wrote:
| I read about the Spark framework on another thread. Looks very
| similar. https://news.ycombinator.com/item?id=39331126
| yCombLinks wrote:
| It's basically a fork and spark dev was abandoned
| TeaVMFan wrote:
| This looks useful for server-side web apps. For using Java/Kotlin
| in a single-page app, I've been using Flavour successfully for
| many years.
|
| I've written a book about it here:
| https://frequal.com/Flavour/book.html
| dj_gitmo wrote:
| What are the drawbacks of these "simple" frameworks? Do you run
| the risk of being constrained if your requirements expand?
| michaelcampbell wrote:
| Sure? I mean any framework will constrain you to what it
| provides. These frameworks usually include some set of
| functionalities:
|
| - an underlying service to listen for http/https requests (eg:
| "web server")
|
| - easily map inputs to code/services ("routing"); often also
| providing helper functionality to extract data from paths, map
| and convert JSON (etc) to domain objects
|
| - some way to inject your data into a return "view" (json,
| html, xml, ???). Might also include reusable view code snippets
| (eg: "partials"), and/or some "design pattern" (eg: "layouts")
| system
|
| - an ORM or other db-layer abstraction
|
| - some background job processing abstraction
|
| That's about all you need; the extent to which the framework
| simplifies doing those things is akin to the amount of
| constraints. Everything else is gravy.
|
| Do note that "big" frameworks that provide ALL of that plus
| more can often be harder to work with since you might be forced
| to learn more than you need, and it's overwhelming.
|
| There's also the concern of modularity... if I don't like their
| ORM, can I use my own? How hard is it to add functionality not
| provided, etc.
| andrewoneone wrote:
| Totally agree. The modularity and the amount of "batteries
| included" can eventually become a negative. The last thing I
| want is for someone to reinvent RxJava yet it seems to happen
| in every one of the more bloated frameworks. "Are you
| familiar with reactive programming? Oh cool - but are you
| familiar with mixing RxJava and Spring's reactor? That's what
| we now have and it's a real treat sometimes." This is just
| one sad and possibly poorly outdated example as I haven't
| worked with spring in some years now.
| michaelcampbell wrote:
| I worked in a place using Django, with dozens of additional
| plugins and enhancements.
|
| And my PR's were routinely flagged for writing 3-5 lines of
| idiomatic python that any python programmer (indeed, any
| PROGRAMMER) would have understood instead of spending half
| a day to try and find the "Django way" (or worse, the
| "whatever 5000 line plugin we installed to save the
| programmer from having to repeat 2 lines of idiomatic
| python 10-12 times") way to do it.
|
| Their (IMO insane) adherence to the common, but
| misunderstood idea of DRY was insanely unproductive.
|
| These frameworks become "languages" in themselves, and
| unless you're in it all day every day, it's _harder_ to get
| things done due to their incredibly large attack surface.
| ahmedfromtunis wrote:
| Can you give an example of this "Django way" code vs
| pythonic code dichotomy?
|
| I'm very curious to see how that may look like. I've been
| using Django for years now and was never faced with such
| choice.
| fuzztester wrote:
| >Sure? I mean any framework will constrain you to what it
| provides.
|
| By definition, almost, compared to the bunch of libraries
| approach, whch is more flexible and composable.
| StevePerkins wrote:
| It's a philosophical thing.
|
| The advantages of microframeworks (e.g. Sinatra, Flask,
| Javelin, etc) are that as your needs expand, you can bolt-on
| the additional functionality as you see fit, from a "best of
| breed" selection of your favorite libraries.
|
| The advantages of batteries-included frameworks (e.g. Rails,
| Django, Spring, etc) are that your application is easier to
| find people to work on, and has a greater change of remaining
| coherent and maintainable for longer.
|
| In the real world with microframeworks, some rock star starts a
| greenfield project, and has a delightful fun time selecting
| their personal picks of various community libraries to bolt
| functionality on top of the microframework. Then that original
| developer moves on 6 months later. The best-case scenario is
| that half of their pet community libraries are no longer being
| maintained 12 months after that, and the team has to constantly
| sink time into migrating pieces of the app to other actively
| maintained libraries. The worst-case scenerio is that you get
| the next-generation rock star, who wastes time ripping out
| pieces for no real reason other than using their own personal
| pet favorites.
|
| In my experience, the microframeworks are ideal for apps where
| you can be fairly confident that the scope will never expand
| (e.g. simple Lambda functions). Otherwise, they're popular toys
| for startups, and nooks and crannies of large enterprises where
| no one's really providing any oversight over the juniors.
| the-smug-one wrote:
| Is the main advantage of frameworks then a social thing? You
| can depend on the future development of the framework as a
| whole, as opposed to a bunch of smaller libraries, so it
| doesn't matter if the sum total quality of those smaller
| libraries is greater than the framework.
|
| Does it also have the advantage of not having to remember to
| import things? Like, does Spring prevent CSRF attacks etc.
| out of the box, and it's very difficult to accidentally
| create a vulnerability using it?
| olavgg wrote:
| Yes Spring Boot 2.2+ prevent csfr attacks out of the box.
| mattgreenrocks wrote:
| Big factor in rise of frameworks is outsourcing the
| architecture to it.
|
| Lots of devs need the prebaked structure. It is honestly
| helpful in many cases, but can also be a frustrating maze
| at times to find the hook/extension point you need.
| okeuro49 wrote:
| Spring Boot uses a lot of libraries and integrates them for
| you to make sure they all work together.
| jmspring wrote:
| I used Javalin for a startup I helped with a few years back. I
| found It much easier and lightweight to turn up REST endpoints
| compared to Springboot/etc.
|
| While it may not be as featureful as Springboot, it could
| generate swagger specs and had the features I needed at the time.
| cryptos wrote:
| In my experience the web layer is (or should be) pretty thin,
| so a framework in this layer shouldn't change too much in the
| overall application architecture.
| _bax wrote:
| Java _is_ agile, like said by @venkat_s
| michaelcampbell wrote:
| I'm a little surprised this framework hasn't gotten more
| mindshare. I've found it pretty easy to grok and work with.
|
| Seems right now everyone is under Spring's "boot", if you'll
| pardon the pun.
| BossingAround wrote:
| It's either Spring, or Java EE's way (together with the new
| Jakarta EE paradigm, which is actually pretty cool if you ask
| me). I've seen the latter a lot more in the enterprise sphere.
| zokier wrote:
| Jakarta EE was purely a rebrand of Java EE, what do you mean
| new paradigm?
| ysleepy wrote:
| https://microprofile.io/
| fuzztester wrote:
| >MicroProfile
|
| >Optimizing Enterprise Java for a Microservices
| Architecture
|
| Captain Kirk:
|
| When the spaceship nears colossal planet Enterprise, two
| kinds of developers on board will be revealed:
|
| - those who jetpack enthusiastically down to the planet
| (their Buzzwordite (TM) foam resumes will softpad their
| landing)
|
| - and those who retrorocket desperately away, seeking
| lean, mean, computing machines
|
| Spock:
|
| Logical flaw - you forgot off-by-one errors.
| zokier wrote:
| [delayed]
| arunix wrote:
| What is cool about the new Jakarta EE paradigm?
| adamredwoods wrote:
| Years ago when I was investigating Spring and Java EE, I was
| taken aback by how much additional work was involved. Not only
| do some tutorials only show how to install through Java's
| dedicated IDE, but also deciding on which application server to
| use, which adds another layer of technical decisions and slows
| down the process of "quickly testing" frameworks.
|
| Javelin breaks free of that. Excellent stuff!
| reactordev wrote:
| @SpringBootApplication was all you needed on top of a main
| class. The biggest issue is somewhere along the Spring ->
| Pivotal -> VMWare -> Spring hot potato, their tutorials and
| documentation fell off a cliff. Everything became "just use
| initializer..."
| StevePerkins wrote:
| If you were "deciding which application server to use", then
| that WAS "years ago" indeed! The paradigm shifted, from
| applications being deployed to a server such as Weblogic or
| Websphere, to applications bundling their own HTTP server
| like Node or Golang. This shift happened around 15 years ago.
| Modern Java development looks almost nothing like it did back
| in that era.
| bbkane wrote:
| Do you have any good Modern Java web dev links you could
| drop?
| reactordev wrote:
| Micronaut has a share of the space too.
|
| https://micronaut.io/
|
| However, you're right that Spring Boot has the lions share of
| the Java ecosystem.
| sureglymop wrote:
| What about Ktor? I always see that being pushed, maybe because
| it's from Jetbrains..
| michaelcampbell wrote:
| What about it? This is just a post about Javalin.
|
| I often wonder why people always post these "sure, but what
| about..." replies. Hot take: There's more than one way to skin
| a cat, here's one.
| ydnaclementine wrote:
| They're looking for comparisons dawg
| jeltz wrote:
| Not a fan of it. Too much DSL magic for unclear gains, at least
| in the way the manual recommends you to write your code.
| cushpush wrote:
| "simple"
| binkHN wrote:
| I glanced at this a while back, but, ultimately, went with Ktor.
| Reason being, well, I was using Kotlin and wanted something even
| more simple.
| sureglymop wrote:
| I don't like that the logging just happens implicitly? Like, it
| asks to install slf4j... But can't I just start out with the
| standard kotlin logger before installing another dependency. That
| part imo is a little underdocumented.
| michaelcampbell wrote:
| https://javalin.io/tutorials/javalin-logging seems pretty good,
| IMO; YMMV of course.
|
| Logging in Java has always been a weird amalgam of interface
| libraries and implementation libraries with an XKCD'ish "14
| competing standards" issue.
| kaba0 wrote:
| Either slf4j or java's standard lib API interface (since java
| 9 I believe) works with everything basically.
| KronisLV wrote:
| Personally, I rather enjoyed Dropwizard, because it had a bunch
| of idiomatic Java packages that most developers would have
| already seen elsewhere, all put together in a way that doesn't
| seem to have too much boilerplate:
|
| https://www.dropwizard.io/en/stable/
|
| https://github.com/dropwizard/dropwizard
| waynesonfire wrote:
| I'm a fan of dropwizard but couldn't get swagger to work with
| it. Maybe it's improved since then?
| fuddle wrote:
| Kudos for the great documentation.
| BossingAround wrote:
| Wow, this is a blast from the past for me - I was examining the
| framework in 2015. Amazing to see it's still well and alive. Back
| then, I'd simply use some resteasy framework.
| simonw wrote:
| This is a really nice API design:
| https://javalin.io/documentation
|
| Feels lightweight but powerful - it seems to cover everything I
| need from a framework in terms of URL routing and
| request/response handling, with minimal cruft and boilerplate.
| jmspring wrote:
| That was why I picked it awhile back. I hate that most Java
| development these days has a large component that deals with
| writing XML. It allowed me to focus on the code I needed to
| write and not figure out what parts I needed to cobble
| together.
| matsemann wrote:
| Are you comparing to legacy java applications? Haven't
| written xml in soon a decade in spring boot.
| kitd wrote:
| One of the good things about it is that using asynchrony is
| optional. If you don't have to call out anywhere to build the
| response, processing can all stay in the handler's calling
| thread. If you do, you can return a future and have the library
| handle the async for you.
|
| One downside is that it is based on Jetty which isn't
| considered the most performant backend. A lib with a similar
| API but based on Netty is Jooby [1] which scores well in the
| Techempower benchmarks.
|
| [1] - https://jooby.io/
| javajosh wrote:
| _> Jetty which isn't considered the most performant backend_
|
| This definitely needs some supporting links. Jetty itself is
| extremely fast in my experience.
| silvestrov wrote:
| The cookie support seems lackcluster. I'd prefer good support
| for real cookies instead of "stuff JSON into a single cookie".
|
| Also the URL parameter API is clumbersome:
| Integer myValue = ctx.queryParamAsClass("value",
| Integer.class).getOrDefault(788) // validate value
|
| I would prefer some specialized API like: int
| myValue = ctx.queryParamAsInt("value", 788);
| matsemann wrote:
| Given that it's kotlin, one could easily make an extension
| function like that yourself and enhance the API to your
| liking.
| derefr wrote:
| My API SaaS company chose Javalin for our API backend to start
| with, for several reasons:
|
| * it is "just enough" web framework for our needs, without all
| the bloat that a framework targeting browsers/serving HTML would
| have;
|
| * it has an annotation-based OpenAPI auto-summarization plugin,
| to allow us to immediately get some docs and autogenerated SDKs
| up;
|
| * and it explicitly owns the lifecycle for its components --
| using e.g. an embedded Jetty instance that gets started +
| configured _in code_ by the framework -- where you can inject
| config into that code, or replace it wholesale. (This is what we
| were used to in other web frameworks, and is unusual in Java
| land, where web servers seem to be separate "background
| services" that happen to start up independently in the same JVM,
| and then auto-discover and runtime-bind to your web service's
| "background service" through XML files the framework generates
| and the web server probes for. Which is a bit much when you're
| not running an enterprise-y "app server" with tons of different
| servlets mounted to it that can be hot-upgraded without
| restarting the server, but instead a single-purpose Java app in a
| Docker container as a k8s Deployment.)
|
| That being said, as our company grew, we eventually ran into the
| disadvantages:
|
| 1. Scanty documentation.
|
| The https://javalin.io/documentation page is all you get. Want,
| say, a list of the HTTPResponse exceptions Javalin offers? Or to
| know the _types_ -- rather than just the _behaviors_ -- of the
| getters and setters on Context? Well, too bad -- go read the
| (Kotlin) source code!
|
| (Why no per-module JavaDoc docs? Even the hollowed-out docs that
| just give constants + methods, that you get by generating docs
| from a module with no docstrings, would be better than _no_
| JavaDoc! IDEs do give you some of the same info as a trivial
| Javadoc, but JavaDoc docs are a lot more browsable as a reference
| when you don 't know the _name_ of the thing you want, just the
| _type_.)
|
| 2. Static routes!
|
| Javalin routes must be bound to _static methods_ of Java classes.
| You can 't+ build an object, pass the object to your Javalin app
| constructor, and have it bind routes to that object's methods.
| Which makes constructing any kind of DDD service contexts -- and
| having them be _testable_ , with separate e.g. DB providers in a
| test context -- near-impossible. Javalin and _dynamic_ Dependency
| Injection -- the kind you do in tests -- just don 't get along.
|
| + Or, well, you _can_ do that -- in that you can bind each route
| to a _closure_ which _calls_ the method on the object. But those
| closures need to be able to bubble arbitrary checked exceptions
| back to the Javalin exception handler (which the trivial examples
| in the Javalin docs carefully avoid the need for by only calling
| pure code.) Which means so you can 't use the syntax-sugar'ed
| kind of functional closure. So each route balloons into 10 lines
| of instance-subclass boilerplate, and your routes module is no
| longer a readable + greppable DSL definition of "what your app
| reacts to", but instead a big mess.
|
| 3. No support for writing Java Servlet middleware.
|
| Javalin _uses_ servlets under the covers, but doesn 't expose the
| servlet "stack" for injection. Instead, you have to write Javalin
| plugins (Which haven't been good for much for most of Javalin's
| lifetime -- though they seem to be pretty flexible _now_ , so
| this might not be as much of a concern if you're doing a
| greenfield Javalin project today.)
|
| I'm guessing that most devs still just end up just dumping all
| their middleware-ish concerns (auth, rate-limiting, etc) in
| app.before + app.after. Which thereby accidentally leaks
| resources -- because some exceptions can cause app.after to not
| run! (You have to do a little dance with app.after and
| app.exception calling into common code -- essentially "rewriting
| the framework to do the thing it should have done" -- to resolve
| that.)
|
| 4. The Javalin devs are slow to add very critical features that
| tons of people ask for, sometimes leaving outstanding requests on
| the backburner for years.
|
| Until Javalin 6, there was no app.beforeMatched, and therefore,
| no request-lifecycle callback point for "after routing has been
| resolved, but before actually calling the route."
|
| So, before recently, you couldn't do rate-limiting or auth or etc
| _generically in middleware_ , while also taking the static route-
| name of the resolved endpoint -- the string that looks like
| "/account/:id/binding" that the Javalin context gives you access
| to _inside_ your controller code -- into account as an input.
| Instead, to do this, you had to let the route trigger, and then
| call generic code from _inside_ the controller (see e.g.
| https://javalin.io/plugins/how-to#creating-a-plugin-with-con...,
| which seems to show that the Javalin devs still think of this as
| the idiomatic way to do this.)
|
| Even with this _particular_ feature request finally resolved,
| there are still several outstanding ones. And given the shape of
| Javalin as a framework, the way to work around these missing
| features, always ends up involving writing redundant generic code
| inside your MVC controllers. If you do this enough times -- and
| you follow the natural desire to factor them out -- then you end
| up basically building a framework on top of your framework! (And
| then, when these new features _do_ finally come along, you 're
| already added all this now-unneeded architecture that's very hard
| to get rid of.)
|
| ---
|
| A while ago, we got fed up with the disadvantages -- so we're
| very likely going to be moving to Spring Boot.
|
| At some point. (Given the particular shape Javalin forces your
| code into, though, such a move is a lot of work!)
| breakpete wrote:
| Regarding 2, you can actually bind routes to instance methods:
| var obj = new SomeObjectWithHandlerMethods(dependency);
| var app = Javalin.create().get("/",
| obj::handlerMethod).start();
|
| Edit: For 4, Javalin 6 also has some documentation regarding
| Servlets here: https://javalin.io/documentation#adding-other-
| servlets-and-f...
| derefr wrote:
| Strange -- I swear this wasn't the case. I and several other
| devs tried for a good three weeks to get Javalin to accept
| such route bindings. This _was_ a year or two ago, though.
| Maybe the interface type for a handler function was changed
| in some more recent version of Javalin?
| breakpete wrote:
| Not sure about the older versions of Javalin, but from my
| experience with v5+ it just uses regular Single Abstract
| Method conversion for the Handler interface, which has a
| single method with just one parameter (the Context).
| Yhippa wrote:
| Just reading through the examples, the fluent API really shines.
| vbezhenar wrote:
| If you like lightweight libraries, check out Helidon SE 4. It's
| built on Java 21 virtual threads, embraces blocking paradigm,
| built by Oracle, fully open source, of course, comes with some
| batteries included. Worth checking out, IMO.
| kitd wrote:
| Note that Javalin also supports virtual threads.
|
| https://javalin.io/documentation#concurrency
| vips7L wrote:
| Supporting and being built upon them is a bit different.
| Helidons web server was written from scratch with virtual
| threads in mind.
| pipeline_peak wrote:
| Should've called it Kava
| ysleepy wrote:
| Nowadays I prefer starting with a microprofile subset consisting
| of jersey+jetty offering the standard JAX-RS APIs.
|
| Is really lightweight at only 6MiBs shaded and grows
| opportunistically into the microprofile stack of quarkus etc. -
| you can even integrate the jax-rs bits into spring if you want.
| Microprofile has a bunch of standards compliant implementations,
| so you aren't locked into a specific implementation project.
|
| I think the option is overlooked because the landscape is complex
| and this setup doesn't have a marketing name, but it is very
| stable and polished.
|
| You also get IDE support, because JAX-RS is part of microprofile,
| and formerly part of JavaEE.
| mightyham wrote:
| Springboot's dependency injection, auto configuration and yaml
| configuration system is a value proposition that I find hard to
| beat. I find it's fairly effortless to build almost any kind of
| backend software, and if I want something "lightweight" I
| probably wouldn't use java in the first place.
|
| While that's my pragmatic view, to be less critical, I am glad to
| see a project that provides a robust and elegant API for building
| rest services in Java.
| nullzzz wrote:
| The aforementioned are huge detractors for me to be honest. I
| find a no-magic, code-only solution like Javalin (and Express
| etc) far more intuitive.
| koufatz wrote:
| It's actually not that hard to beat. Quarkus proved that it's
| way better than Spring Boot in a lot of aspects based on open
| standards and battle tested frameworks like Vertx. Also on
| Quarkus you can use in parallel blocking and non-blocking IO
| and also high level declarative routes with annotations to
| lower lever vertx routes and handlers.
| vips7L wrote:
| You don't even need a framework to beat it.
|
| Pick a DI library: Guice, Avaje Inject, Weld, countless
| others
|
| Pick a configuration library: Avaje Config, Typesafe Config,
| Microprofile Config, countless others.
| xienze wrote:
| There's a lot more to Spring Boot than DI and
| configuration.
| dang wrote:
| Recent and related:
|
| _Spark - A web micro framework for Java and Kotlin_ -
| https://news.ycombinator.com/item?id=39331126 - Feb 2024 (35
| comments)
___________________________________________________________________
(page generated 2024-02-11 23:01 UTC)