Spark was fine, but was abandoned. Which means it was stuck using an end-of-life’d version of Jetty. Which meant that we could no longer pass security audits.
Whereas Javalin continues to get frequently updated.
Spark ruined me. Everyone expects Spring, but dealing with Spring and all the pointless annotation magic is a misery; I find myself longing to just use Spark and forgo all that crap.
I suppose I'll try Javalin then next time I have the choice.
“An idiot admires complexity, a genius admires simplicity, a physicist tries to make it simple, for an idiot anything the more complicated it is the more he will admire it, if you make something so clusterfucked he can't understand it he's gonna think you're a god cause you made it so complicated nobody can understand it. That's how they write journals in Academics, they try to make it so complicated people think you're a genius.” - Terry A. Davis
> Closures defined only by the arrow are a Java thing... or so I thought. :D
In fairness, I think you did copy the Java version. There's a little switch in the code boxes where you can toggle the language, if you switch to Kotlin you get the version with trailing closures :)
Edit: I'm an idiot, I see the snippet you mean now. It's been updated now, give it a minute.
Express is inspired by Connect JS in terms of middleware — middleware written for Connect works in Express. The middleware style I believe is originally inspired by Rack, a Ruby project.
Sinatra, also Ruby, predates Express and is based on Rack (in a similar way to Express, which used to be based on Connect if I’m not mistaken).
I’m not sure what inspired Sinatra, but that’s probably the influence you’re seeing in these frameworks.
I just started using this! Spring Boot seemed so convoluted, having to go to a website to even begin. And then to have the Tomcat dependency seemed like a heavy lift just to get a "hello world" working. Virtual threads seems to be the way to go.
I haven’t tried this framework, but just looking at some examples, the web sockets and sse seem a bit out of place. In a Loom world you’d expect these to use channels or queues or something similar in a loop - not callbacks. Callback hell is what virtual threads try to avoid. I’m not sure if loom has any primitives like go’s multi-channel select that might make this workable though.
In either case Loom and frameworks that use it are super exciting! I’m looking forward to removing the 20 different thread pools we need to avoid deadlocks and just using the common one in our Clojure apps.
We don't have selectable channels yet, but they're not needed as much in Java as they are in Go, because often multiple channels are used to signal cancellation, whereas in Java there's a standard mechanism for cancellation (Thread.interrupt() at the low level, with Future.cancel being higher level, and JEP 428's structured concurrency being higher level still https://openjdk.org/jeps/428).
Java is an extremely mature piece of technology, and having used it on the enterprise, I can attest that few things come close on flexibility and stability. Also, functional languages on top of the JVM (clojure, kotlin, scala) are very interesting on their own. Java deserves some love from this new wave of paradigm changes like "write-once-run-anywhere" v2.0, monadic programming, serverless functions, etc...
> Java is an extremely mature piece of technology, and having used it on the enterprise, I can attest that few things come close on flexibility and stability.
Very much agreed, as long as you don't have to deal with legacy projects with Java 8 to Java 11 migration, which might sour the view of the language as a whole for some folks. I think Java doesn't get as much love nowadays due to some of the frameworks having to deal with historical baggage (e.g. Spring being unwieldy, which is at least partially why people prefer Spring Boot), though Java probably isn't the only language for which this is the case: https://earthly.dev/blog/brown-green-language/
That said, Java and .NET are both good options in my eyes - reasonably productive, with pretty decent type systems and good runtime performance. Not perfect, but almost always decent choices. Oh, and the runtimes themselves are pretty great, especially because we get languages like Kotlin, Scala for the JVM and F# for the CLR.
Then again, for different use cases I wouldn't scoff at Python, Ruby or Node either. Even something like PHP can be passable in some cases.
I just wanted to say thank you for your work. The straightforward docs are some the best in my opinion when you want to go from "How do I do ..." to answer.
I ended up using Javalin with Kotlin and SQLite to build my wedding website.
Most of my projects are lucky to see the light of day, but with a very persistent project manager and a simple lightweight framework, I was able to ship a fantastic product with very little fuss.
I can see how DI will be overkill for a wedding website and Javalin/jdbi/sqlite is more than enough but for most business applications written in Java you really wish you had started with DI. Any DI libs you recommend for working with Javalin?
Yes, disagree on needing a library. The way your comment was worded made it seem to me like you were saying all serious Java applications need a DI library, I'm sorry if I misunderstood you. I prefer doing my ID manually, so no recommendation :)
It took me a hot moment to adjust after leaving classic spring Java land to a Scala shop that doesn’t use DI framework, but now I love it. I agree with what you said.
It does help to keep services small so the manual DI arg passing doesn’t get too spread out and boilerplate-y. But I have worked on a dozen services here and don’t miss an automatic DI framework.
I have a few questions about this approach, cards on the table I mainly deal in C# where DI (through the framework) is the default. How do you manage the initialization of all of the dependencies? Do you need some sort of "root" where everything is initialized and passed in? That was all I could come up with while keeping it testable and that doesn't sound maintainable once you build up the number of dependencies.
I'm also a fan of the manual DI approach - I strongly dislike the magic.
I think it helps if you are building test/fakes of your deps that don't really need as many sub-dependencies. Generally you in a test `@BeforeAll` construct a bunch of objects or for a program you do it in `main`.
I did work on a project while I was at Google that was really big and a decade old that instead had a class with a bunch of lazy getters for each item in the dependency graph, then tests would override or reset the getters with testing versions as needed. It was a little clunky but I preferred that approach over the projects I worked on that used dagger.
If you've read through the Dagger dev-guide [0] there is *a lot* in there, while the manual approach it's usually just `new` which is a really simple concept on it's own :) I think this is the right tradeoff because reading code is harder than writing code, so it's worth the extra setup. In practice I haven't seen it to amount to be an overwhelming amount.
What dependencies are multiplying? I organize my code so that the very top level of the api has all external dependencies injected there, there is no public classes below a single exposed class that would need to be directly injected into. The only thing I need to actually inject are things that are outside of my memory space, ie network calls, event buses, dbs. If it's not using something outside of my memory space I am just using new inside my classes, it's far easier to test.
For example, if I'm adding a new feature to allow a user to change their address, I would have a single class at the top level "CustomerAddressChange" or whatever. I would inject an interface that wraps everything external, and that is the only thing that anything would be injected into. My tests would all stub only that interface. Everything else is done without any sort of DI container.
When I switched from Java to Go and started doing DI like this, I was amazed at how simple and efficient DI could be. I was taught DI with Spring and never fully grasped why and how it worked. With Go it just clicked and to this day I still have no idea why DI libs are so complicated. If I ever come back to Java, I’ll make sure to do DI manually.
> Calling a constructor is DI. ‘new’ is the only DI framework required.
This feels like the sane thing to do, but sadly for historical reasons this won't work with many (if not the most) Java frameworks out there, or even certain options in the .NET ecosystem.
When you get non-trivial frameworks that are deeply entrenched in having DI and using it internally for a bunch of stuff, you'll find yourself out of options, e.g. if you use Spring/Spring Boot.
And in many places something like Spring Boot might be considered an "industry standard" and you might get looked at funny if you suggested using another framework, even more so if they have their own configuration/plugin/utility solutions for it already built within the org.
Personally, however, I rather enjoy alternative takes on how web frameworks could look and even something like Dropwizard/Vert.X/Quarkus have nice quality of life aspects to them.
In a sense, it's nice that the industry is moving towards smaller service based architectures, where you might spin up a new service with whatever tech fits the problem that you're trying to solve, as opposed to being locked into adding code on top of some bloated monolith (though that comes with certain tradeoffs and drawbacks, in regards to complexity and maintenance).
For a website, the question should be why not use SQLite.
Given the various compelling and (by now, here, I hope) well-understood advantages, it should be the default choice. Certainly for a site expecting hits in the mid-hundreds, total. Maybe ten simultaneous connections the day of?
Interesting, I interpreted the question completely differently, i.e. why use database at all?
FWIW, I'm not in the web app world, so my wedding website was a single page HTML; not a single page app, let alone a content management system - I googled something like "Wedding page HTML template", then grabbed a HTML template from w3schools, opened it in notepad, and put my own words and IMG tags. It looked pretty, was "responsive" by default, took very little time to create, and worked solidly.
I'm sufficiently old school / ignorant / pragmatic / lazy / focused / something, to wonder why complicate a wedding page with anything else :-)
(I mean, I'm old and ignorant and simple enough that I keep misinterpreting what "static site generator" is :P )
Interesting, I interpreted the question completely differently, i.e. why use database at all?
Maybe the wedding page has forms, needs to store data and author is most familiar with Java or maybe they are getting creative and are calling third party services for convenience, lots of reasons. A simpler solution could be nginx/cgi and a local file for the DB, or cloudfare workers(you can render HTML from them) and their key/value storage.
Yeah that was what I meant but everyone else seems to be commenting except the person I was replying to lol. I am not attacking databases I am just wondering what they used it for on a wedding website.
It's been SOP for some time (at least 20 years) to use an RDBMS to store your site's content and write a stateless application server to pull data from it and compose a response. Call it the "CMS pattern".
Static site generation, and a few other ideas, challenges this basic pattern, but most of the worlds applications use it. Javelin is trying to make the pattern better on several axes, simplicity first-and-foremost, and not replace it.
Funny, I had a LAMP stack in mind while writing it, and more specifically WordPress. For all the enterprise Java webapps out there, I bet there are 1000x more php sites. And they all use the same basic cms pattern.
heh, very good point. WordPress is absolutely everywhere and is exactly this model. I think WordPress forged the path too, so definitely deserves the "blame"
I used PostgreSQL for my wedding website. People could RSVP, say how many were coming, volunteer for support roles since we did too much of it ourselves, etc.
Similar to other use cases mentioned already, it was a way for us to create a privacy-focused site to manage guests and give guests the opportunity to update their RSVP, dietary needs, and requested song for the DJ. Additionally there were a few sections of the site where my fiancée could update content as she saw fit by logging in and hitting save. We found the database useful to keep track of RSVPs, gifts, and who we still needed to send thank you's to after the event.
The main drawbacks were people who are not comfortable using the web and people remembering their unique adjective-noun passphrase. Also, I'm not very savvy when it comes to CSS or design so my giddiness was crushed demoing what I thought was the MVP to the "project manager".
I don't want to detract this from being about Javalin though. It's fantastic. I would recommend it and use it again for projects.
Re: pass phrases, my go-to for projects like that is to put a unique hash or something in the URL for each different person. The experience for users is that there's no password to remember or anything like that. They're not going to remember the URL anyway.
You can put the hash in a #xxxx part of the URL so it doesn't show up in logs if thats important to you. The downside is you need to give everyone their own URL (maybe via a QR code on a paper invite). But you already had to give everyone a pass-phrase so whatever :)
For anyone who wants to get started with this stack you can do `git clone https://gitlab.com/asad-awadia/kotlin-server-app.git` to get a full maven project with javalin, sqlite with ktorm and jdbi everything setup
this is very cool.
quick question though - do u have a gradle build setup ? im new to java and saw this problem on spring boot. That you needed to have this bunch of complex directory structures cos of the way java packages worked. for e.g. the test directories were parallel to the src directory, so they could be named with the same package name.
for a single file...i can just run java. but it would be nice to see a gradle setup that keeps simplicity and yet can have thousands of files and testcases organised in a nice structure.
secondly, it is nice that you have Jetty hooks. Can you also have CORS & proxy protocol ? its literally mandatory to have this stuff if ur deploying on any of the k8s based clouds.
I'm not super sure what you're asking, but Javalin doesn't care at all about your directory structure. You can add it as a dependency to any existing gradle project you have, and import it like any other Java library (like java.lang.String).
That's not a spring thing, but a java tools convention (having a src and test folder etc).
Nothing stops you from doing it differently, but most tools work out of the box if you follow that setup. So better to just do it than having to fight with / configure every part of your pipeline.
I successfully used Javalin in a project using Kotlin + Koin for dependency injection + jOOQ for database access. Was a joy to setup and work in that project.
Thank you!
Congratulations on the major release and keep up the good work.
Virtual threads are already available in the current version of the JDK (19) as a Preview feature. Because it's not a preview language feature but a preview API, libraries can use it without compiling with --enable-preview, either with reflection or by having the application supply a virtual thread ThreadFactory, which means they can make use of virtual threads if the application turns preview features on.
Preview language features are different as they require compiling with --enable-preview, which creates a "poisoned" class file that cannot be loaded at all without preview enabled, so preview language features are not recommended for use by libraries, but preview APIs are fine (see JEP 12: Preview Features https://openjdk.org/jeps/12).
If you run this on JDK19 with *--enable-preview*, Javalin will use Virtual Threads for the Server ThreadPool (as well as all other ThreadPools it has).
I mean, it sort of doesn't? Coroutines is a whole concept, Virtual Threads can in most cases just replace java.lang.Threads, which is how it's implemented in Javalin. We just swap out the OS Threads for Virtual Threads.
now that i think about it i'm pretty sure my guess is completely wrong. memory usage (and thus concurrent-inactives) might be similar, but i expect the virtual threads to be much more efficient.
I respect Vert.x a lot, so I'm flattered, but Vert.x is a huge beast with focus on performance. Javalin is basically a tiny UX layer on top of Jetty. I don't think they are very similar frameworks. Javalin's focus is on being "good enough" all around, but with the best possible developer experience.
Curious as to what has kept you motivated to continue working on the project this long? So many open source developers don't last nearly as long or jump to something new once the novelty of the project wears off.
I've been dogfooding it hard, which is a great incentive to keep working on it. I think we have 20 Javalin projects where I work. It's also gotten pretty popular lately (3m downloads last 12months), which of course helps a lot :)
How does the dev tooling work? Rebuild & restart the app each time? I find working on any sizable codebase this can take minutes even on the latest spring-boot. Quakrus has an interesting live reloading classloader.
Rebuild and restart. Javalin itself starts in milliseconds (the test suite starts and stops servers across 600+ tests in less than 10 seconds). If you run in debug mode in IDEA, or use some hot-swapping tool like dcevm or jrebel, you won't always need to restart. I don't think there will ever be a dedicated tool provided by Javalin for this.
138 comments
[ 5.3 ms ] story [ 211 ms ] threadNot the big data Spark. This one: sparkjava.com
A nice piece of work in its own right.
Spark was fine, but was abandoned. Which means it was stuck using an end-of-life’d version of Jetty. Which meant that we could no longer pass security audits.
Whereas Javalin continues to get frequently updated.
I suppose I'll try Javalin then next time I have the choice.
Aw, that's sad to hear. I've been out of JVM-in-anger space for awhile, but I always liked Spark when I was.
Show HN: Javalin 1.0 – A Kotlin/Java web framework - https://news.ycombinator.com/item?id=15644430 - Nov 2017 (87 comments)
Show HN: Javalin, a Java/Kotlin REST API Framework - https://news.ycombinator.com/item?id=14434089 - May 2017 (21 comments)
As far as I know it's inspiration for Spring Boot, and it's simpler and ready to use on production.
Edit: I was looking at the wrong snippet, the offending snippet has been fixed.
In fairness, I think you did copy the Java version. There's a little switch in the code boxes where you can toggle the language, if you switch to Kotlin you get the version with trailing closures :)
Edit: I'm an idiot, I see the snippet you mean now. It's been updated now, give it a minute.
Sinatra, also Ruby, predates Express and is based on Rack (in a similar way to Express, which used to be based on Connect if I’m not mistaken).
I’m not sure what inspired Sinatra, but that’s probably the influence you’re seeing in these frameworks.
Virtual threads in Java 19: https://www.infoq.com/articles/java-virtual-threads/
I have to see I’m pleased to see Java moving fast those days.
I’m still digesting 17 and 18, but that give me a reason to look at 19.
I honestly project loom was far from reaching that level of “standardness” … so I haven’t looked into it in years
https://expressjs.com/en/starter/hello-world.html
In either case Loom and frameworks that use it are super exciting! I’m looking forward to removing the 20 different thread pools we need to avoid deadlocks and just using the common one in our Clojure apps.
Java deserves its comeback among the wave of nu-programming we are going through.
What is nu-programming? And why would Java deserve a comeback?
I made that one up.
>And why would Java deserve a comeback?
Java is an extremely mature piece of technology, and having used it on the enterprise, I can attest that few things come close on flexibility and stability. Also, functional languages on top of the JVM (clojure, kotlin, scala) are very interesting on their own. Java deserves some love from this new wave of paradigm changes like "write-once-run-anywhere" v2.0, monadic programming, serverless functions, etc...
Very much agreed, as long as you don't have to deal with legacy projects with Java 8 to Java 11 migration, which might sour the view of the language as a whole for some folks. I think Java doesn't get as much love nowadays due to some of the frameworks having to deal with historical baggage (e.g. Spring being unwieldy, which is at least partially why people prefer Spring Boot), though Java probably isn't the only language for which this is the case: https://earthly.dev/blog/brown-green-language/
That said, Java and .NET are both good options in my eyes - reasonably productive, with pretty decent type systems and good runtime performance. Not perfect, but almost always decent choices. Oh, and the runtimes themselves are pretty great, especially because we get languages like Kotlin, Scala for the JVM and F# for the CLR.
Then again, for different use cases I wouldn't scoff at Python, Ruby or Node either. Even something like PHP can be passable in some cases.
Kudos.
I ended up using Javalin with Kotlin and SQLite to build my wedding website.
Most of my projects are lucky to see the light of day, but with a very persistent project manager and a simple lightweight framework, I was able to ship a fantastic product with very little fuss.
> but with a very persistent project manager
Your partner? :D
Benefits:
Unbelievably fast startup time
No magic
No annotations, XML or YAML required
No classpath scanning related security vulnerabilities
Conpletely deterministic
In no other language is ‘calling a constructor’ considered so complicated a framework is required.
Try it!
It does help to keep services small so the manual DI arg passing doesn’t get too spread out and boilerplate-y. But I have worked on a dozen services here and don’t miss an automatic DI framework.
I think it helps if you are building test/fakes of your deps that don't really need as many sub-dependencies. Generally you in a test `@BeforeAll` construct a bunch of objects or for a program you do it in `main`.
I did work on a project while I was at Google that was really big and a decade old that instead had a class with a bunch of lazy getters for each item in the dependency graph, then tests would override or reset the getters with testing versions as needed. It was a little clunky but I preferred that approach over the projects I worked on that used dagger.
If you've read through the Dagger dev-guide [0] there is *a lot* in there, while the manual approach it's usually just `new` which is a really simple concept on it's own :) I think this is the right tradeoff because reading code is harder than writing code, so it's worth the extra setup. In practice I haven't seen it to amount to be an overwhelming amount.
[0]: https://dagger.dev/dev-guide/
This feels like the sane thing to do, but sadly for historical reasons this won't work with many (if not the most) Java frameworks out there, or even certain options in the .NET ecosystem.
When you get non-trivial frameworks that are deeply entrenched in having DI and using it internally for a bunch of stuff, you'll find yourself out of options, e.g. if you use Spring/Spring Boot.
And in many places something like Spring Boot might be considered an "industry standard" and you might get looked at funny if you suggested using another framework, even more so if they have their own configuration/plugin/utility solutions for it already built within the org.
Personally, however, I rather enjoy alternative takes on how web frameworks could look and even something like Dropwizard/Vert.X/Quarkus have nice quality of life aspects to them.
In a sense, it's nice that the industry is moving towards smaller service based architectures, where you might spin up a new service with whatever tech fits the problem that you're trying to solve, as opposed to being locked into adding code on top of some bloated monolith (though that comes with certain tradeoffs and drawbacks, in regards to complexity and maintenance).
I'm personally a fan of Weld since its the reference implementation of the CDI spec.
https://weld.cdi-spec.org/
A friend of mine built an MVC library around Javalin that uses Dagger as the DI container: https://github.com/jehugaleahsa/javalin-mvc
Given the various compelling and (by now, here, I hope) well-understood advantages, it should be the default choice. Certainly for a site expecting hits in the mid-hundreds, total. Maybe ten simultaneous connections the day of?
FWIW, I'm not in the web app world, so my wedding website was a single page HTML; not a single page app, let alone a content management system - I googled something like "Wedding page HTML template", then grabbed a HTML template from w3schools, opened it in notepad, and put my own words and IMG tags. It looked pretty, was "responsive" by default, took very little time to create, and worked solidly.
I'm sufficiently old school / ignorant / pragmatic / lazy / focused / something, to wonder why complicate a wedding page with anything else :-)
(I mean, I'm old and ignorant and simple enough that I keep misinterpreting what "static site generator" is :P )
Maybe the wedding page has forms, needs to store data and author is most familiar with Java or maybe they are getting creative and are calling third party services for convenience, lots of reasons. A simpler solution could be nginx/cgi and a local file for the DB, or cloudfare workers(you can render HTML from them) and their key/value storage.
OP can reply why a database was useful for his wedding site, if he wants; I can think of some reasons why it might be.
Static site generation, and a few other ideas, challenges this basic pattern, but most of the worlds applications use it. Javelin is trying to make the pattern better on several axes, simplicity first-and-foremost, and not replace it.
And (in the Java/enterprise world) is completely correct.
It was overkill and I loved it.
The main drawbacks were people who are not comfortable using the web and people remembering their unique adjective-noun passphrase. Also, I'm not very savvy when it comes to CSS or design so my giddiness was crushed demoing what I thought was the MVP to the "project manager".
I don't want to detract this from being about Javalin though. It's fantastic. I would recommend it and use it again for projects.
You can put the hash in a #xxxx part of the URL so it doesn't show up in logs if thats important to you. The downside is you need to give everyone their own URL (maybe via a QR code on a paper invite). But you already had to give everyone a pass-phrase so whatever :)
for a single file...i can just run java. but it would be nice to see a gradle setup that keeps simplicity and yet can have thousands of files and testcases organised in a nice structure.
secondly, it is nice that you have Jetty hooks. Can you also have CORS & proxy protocol ? its literally mandatory to have this stuff if ur deploying on any of the k8s based clouds.
e.g. https://stackoverflow.com/questions/73225314/accept-proxy-pr...
Thank you!
Congratulations on the major release and keep up the good work.
We use reflection to build the Virtual Thread Factory if the user has Loom enabled in their enviroment: https://github.com/javalin/javalin/blob/master/javalin/src/m...
Preview language features are different as they require compiling with --enable-preview, which creates a "poisoned" class file that cannot be loaded at all without preview enabled, so preview language features are not recommended for use by libraries, but preview APIs are fine (see JEP 12: Preview Features https://openjdk.org/jeps/12).
Edit: looks like its alive and kicking : https://sparkjava.com/news
had no problems at all. i really like it. thanks!