[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)