[HN Gopher] Show HN: I finished v5 of a JVM framework I've spent... ___________________________________________________________________ Show HN: I finished v5 of a JVM framework I've spent spent half a decade making Author : tipsee Score : 274 points Date : 2022-10-03 14:30 UTC (8 hours ago) (HTM) web link (javalin.io) (TXT) w3m dump (javalin.io) | sandGorgon wrote: | 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. | | e.g. https://stackoverflow.com/questions/73225314/accept-proxy- | pr... | tipsee wrote: | 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). | matsemann wrote: | 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. | kitd wrote: | Congrats on v5. | | Have you tried it yet with GraalVM and native compilation? | | Any gotchas? | tipsee wrote: | Thanks! We had some interest in running Javalin on GraalVM in | the past, but no one has updated the tutorial in many years. It | used to work though, so I bet it still would, if you really | wanted it to. | pron wrote: | Very nice! | | Just a minor nitpick (for those who care about the details of | OpenJDK's development): virtual threads are not Project Loom, but | rather one of the JEPs contributed to the JDK by Project Loom. | There are two in JDK 19 (425 and 428), another in advanced stages | (429), and there will probably be more. OpenJDK Projects aren't | features but teams working on producing features focused on some | area and then offering them to the JDK. | tipsee wrote: | > Just a minor nitpick (for those who care about the details of | OpenJDK's development): virtual threads are not Project Loom, | but rather one of the JEPs contributed to the JDK by Project | Loom. | | Thanks for clearing that up. Would adding a "from" be | sufficient? | | _and it uses Virtual Threads ("Project Loom") by default_ | | _and it uses Virtual Threads (from "Project Loom") by default_ | pron wrote: | Yeah, _from Project Loom_ (no need for quotes) would be | better, but even the current usage has become colloquial and | is okay. :) | tipsee wrote: | Fixed, thank you :) | helfire wrote: | 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. | ris58h wrote: | If you use IDEA you can right-click modified .java file and | click 'Compile and Reload File' | https://www.jetbrains.com/help/idea/altering-the-program-s-e... | tipsee wrote: | 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. | potency wrote: | 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. | tipsee wrote: | 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 :) | davidoniumz wrote: | 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. | tdudzik wrote: | JDBI also could be really nice as a minimalistic layer for a db | access | didip wrote: | Javalin is the bomb! I don't know why Java community likes to | make things complicated. | takoid wrote: | "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 | robertlagrant wrote: | Would prefer if this were worded more simply. | the_only_law wrote: | I mean, you see who it's attributed to... | manishsharan wrote: | I like Jetty. Javalin is nice for Kotlin but Jetty + java has | worked well for me. | Scarbutt wrote: | What do you use for routing and DI? do you use Jetty handlers | or the servlet API? | mateuszf wrote: | Dropwizard is cool if you write REST microservices. It uses | embedded jetty, JAX-RS, Jackson, metrics, etc. | | As far as I know it's inspiration for Spring Boot, and it's | simpler and ready to use on production. | stevoski wrote: | This is Javalin and it is great. We switched to it a few months | ago from another micro-framework. | tipsee wrote: | Indeed it is! May I asked what you switched from? | iammiles wrote: | 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. | tipsee wrote: | Hey, thank you for using it. Single-page docs are also my | favorite, and Javalin/jdbi/SQLite is my goto for quick stuff! | | > but with a very persistent project manager | | Your partner? :D | Scarbutt wrote: | 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? | tipsee wrote: | Hard disagree on needing a DI library, manual DI is great. | Scarbutt wrote: | Disagree on using a lib? cause I guess doing manual DI is | still DI. | tipsee wrote: | 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 :) | mkingston wrote: | Could you be more explicit, perhaps with an example? Do | you simply mean you prefer function/constructor | parameters over DI? | vips7L wrote: | Any DI lib would probably work, it depends on your | preferences and use cases though. | | 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 | iammiles wrote: | Yep! At least they didn't mind when I was drinking on the | job. | peanut_worm wrote: | just wondering, what did you use SQLite for on a wedding | website? | yobert wrote: | 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. | | It was overkill and I loved it. | samatman wrote: | 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? | NikolaNovak wrote: | 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 ) | peanut_worm wrote: | 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. | Scarbutt wrote: | _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. | javajosh wrote: | 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. | freedomben wrote: | I truly mean this with love, but this is the most Java | comment I've seen in a long time :-D | | And (in the Java/enterprise world) is completely correct. | javajosh wrote: | 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. | zmmmmm wrote: | Well done! Can't wait to see Loom become the default for web | frameworks. | | Also spotted the Vue plugin - great to see this as so many light | weight web apps with a few pages can benefit from using Vue but | setting up all the build chain is such a drama that it's usually | not worth it. Look forward to trying it out. | tipsee wrote: | Thank you! The Vue support is the thing in Javalin I'm the most | proud of. There are a hundred web frameworks for the JVM, but | none of them have anything close to the Vue support Javalin | has. Some people think it's trash, but for me it's perfect. | rrampage wrote: | How does Javalin compare with Dropwizard which is also quite | lightweight? | tipsee wrote: | Javalin offers way less, it's more or less just the web routing | layer. No databases, no ORM, no config loading, etc. | danaugrs wrote: | Javalin is a great name! | ekvintroj wrote: | I usted Javalin a few months ago for a kotlin api. It's awesome! | recursivedoubts wrote: | Javalin is amazing. | | Kudos. | kcbanner wrote: | Javalin has been powering one of my projects for years now | without issues. Really great framework. Thanks! | sgt wrote: | Great work. It's fascinating to see how "modern" Java looks these | days. | markhahn wrote: | doesn't JVM sniff of the 00's? | heurisko wrote: | Given Project Loom hasn't been available, how does it utilise | Virtual Threads already? | tipsee wrote: | 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). | daveidol wrote: | How does it compare to coroutines in Kotlin? | tipsee wrote: | 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. | stefs wrote: | i'd be interested in this too. my guess: virtual threads | are slightly more memory efficient and slightly faster, but | same ballpark. | oweiler wrote: | Project Loom is in preview, and far from available. As far as I | can see, Javalin doesn't make use of virtual threads yet. | pron wrote: | 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). | tipsee wrote: | It does :) | | 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... | speedgoose wrote: | It looks inspired by express.js, is it the case or are they both | inspired by an older framework? | samtheprogram wrote: | 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. | tipsee wrote: | Both inspired by Sinatra, the OG :) | adamredwoods wrote: | 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. | | Virtual threads in Java 19: https://www.infoq.com/articles/java- | virtual-threads/ | dopidopHN wrote: | Excellent resource on virtual thread by one of the authors! | Thanks. | | 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 | the-alchemist wrote: | Some quick questions: - are you using an already-existing HTTP | engine, like Jetty or Tomcat? | | - how do virtual threads fit into a web framework? | | - do virtual threads make debugging more difficult? (A more | general JVM question, I suppose) | | - any performance / readability benefit, or just a coolness | factor? | tipsee wrote: | _are you using an already-existing HTTP engine, like Jetty or | Tomcat?_ | | Yes, Javalin is built on top of Jetty. | | _- how do virtual threads fit into a web framework?_ | | Most JVM web frameworks (Jetty included) have a thread based | request lifecyle (one thread handles one request from beginning | to end). The java.lang.Threads are extremely expensive (~1mb | memory), while Virtual Threads are very cheap (~0mb memory). We | also have another ThreadPool for JSON streaming, and one for | writing async responses. Using Virtual Threads for these things | reduces overall memory pressure. | | _- do virtual threads make debugging more difficult? (A more | general JVM question, I suppose)_ | | Not that I know, but I've never used this in production myself. | | _- any performance / readability benefit, or just a coolness | factor?_ | | The alternative here is java.lang.Threads, so primarily the | memory footprint. There is no readability difference. When | developing, you don't see this at all. | NightMKoder wrote: | 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. | uup wrote: | Having recently implemented a WebSocket service in Go, the | Javalin way seems preferable. This is what a similar Go version | would look like: wsHandler := func(w | http.ResponseWriter, r \*http.Request) { conn, err | := upgrader.Upgrade(w, r) if err != nil { | w.SendStatus(http.StatusInternalServerError) | return } ctx, ctxCancel := | context.WithCancel(context.Background()) var wg | sync.WaitGroup wg.Add(1) go func() | { defer sync.Done() for { | msg, err := conn.ReadMessage() if err != | nil { return } | } }() msgPipe := make(chan []byte, | 1024) wg.Add(1) go func() { | defer wg.Done() for { | select { case <-ctx.Done(): | return case msg := <- msgPipe | if err := conn.WriteMessage(msg); err != nil { return } | } } }() go func() | { <- ctx.Done() wg.Wait() | close(msgPipe) }() } | | I like Go, but I found writing WebSocket code very annoying. | pron wrote: | 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). | simonw wrote: | I find that hello world example very pleasant to look at. Love | that it's effectively a one-liner. public | static void main(String[] args) { var app = | Javalin.create(/*config*/) .get("/", ctx -> | ctx.result("Hello World")) .start(7070); | } | jannes wrote: | Looks very similar to Express.js which came out in 2011 and has | been one of the most popular frameworks in the Node.js world. | | https://expressjs.com/en/starter/hello-world.html | dang wrote: | Related: | | _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) | tipsee wrote: | The good old days! | pkulak wrote: | I'm pretty sure the "Hello Javalin World" Kotlin example won't | compile, just FYI. | tipsee wrote: | Seems to compile fine here, what's the issue? | | Edit: I was looking at the wrong snippet, the offending snippet | has been fixed. | pkulak wrote: | Huh, I wonder what's different with my setup. I would need to | put curly braces around that closure before it would compile, | i.e: .get("/", { ctx -> ctx.result("Hello | World") }) | | Closures defined only by the arrow are a Java thing... or so | I thought. :D | tipsee wrote: | > 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. | pkulak wrote: | Sweet, thanks! | gavinray wrote: | Probably not used to seeing lambdas inside of parens: | .get("/", ctx -> ctx.result("Hello World")) | | Could also be written as .get("/") { ctx -> | ctx.result("Hello World") } | | The second form seems much more common in Kotlin. | tipsee wrote: | Yeah, no, he was 100% correct, I was just looking at the | wrong snippet. It's been fixed now :) | de6u99er wrote: | Peeking int the docs, it reminds me a little bit of Vert-X. What | do you think qbout such a statement? | tipsee wrote: | 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. | jpgvm wrote: | I have used Javalin for a number of Kotlin backend projects of | late, thanks for all your hard work! | stefs wrote: | i'm using javalin in production without problems. i have a custom | html templating engine and can't wait to try the virtual threads. | | had no problems at all. i really like it. thanks! | moralestapia wrote: | Congratulations! This is great! | | Java deserves its comeback among the wave of nu-programming we | are going through. | tasuki wrote: | > 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? | moralestapia wrote: | >nu-programming | | 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... | stefs wrote: | you can also use it with kotlin | voidfunc wrote: | Javalin is great and a worthy successor to its predecessor | Sparkjava | vincnetas wrote: | What happened to sparkjava? | | Edit: looks like its alive and kicking : | https://sparkjava.com/news | cies wrote: | Congrats on the release! I reviewed Javalin lately and it was | high on my list. We use quite a bit of Kotlin and look for a | framework. I really dislike the magic that annotations bring to | most popular Java frameworks (and Hibernate). I prefer most is | just code". Kotlin helped us a lot in making our code more type | safe, especially the KProperty way of referring to methods made a | difference. | | Though I ended up leaning towards KTor, with Javalin as a close | second. | | How would anyone with more knowledge compare the two (Javalin and | KTor)? | spapas82 wrote: | Can we use this to render traditional apps (no js frameworks)? | skibz wrote: | Absolutely! | spapas82 wrote: | Excellent thank you! Which template engines are supported? | kcbanner wrote: | https://javalin.io/documentation#views-and-templates | freedomben wrote: | This looks great! I did Java professionally for years but when | all the jobs moved to EE I bailed for Ruby/Rails and similar. | Java the language I've always really enjoyed. It's the frameworks | and hundreds of design patterns that repelled me. I felt like | they were all needlessly complex. If frameworks like this one | were more common in Java world, I may never have left. | | This looks really nice! I wish more Java devs approached things | with KISS and simple in mind, rather than looking at every | problem as a way to apply some obscure design pattern that | involves 15 levels of abstraction and indirection for a | relatively simple microservice. ___________________________________________________________________ (page generated 2022-10-03 23:00 UTC)