9 ms·
Show HN: Minum – A minimal Java web framework
I am happy to announce my minimalist zero-dependency web framework, Minum, is out of beta.
http://github.com/byronka/minum http://github.com/byronka/minum
You will be hard-pressed to find another modern project as obsessively minimalistic. Other frameworks will claim simplicity and minimalism and then, casually, mention they are built on a multitude of libraries. This follows self-imposed constraints, predicated on a belief that smaller and lighter is long-term better.
Caveat emptor: This is a project by and for developers who know and like programming (rather than, let us say, configuring). It is written in Java, and presumes familiarity with the HTTP/HTML paradigm.
Driving paradigms of this project:
* ease of use
* maintainability / sustainability
* simplicity
* performance
* good documentation
* good testing
It requires Java 21, for its virtual threads (Project Loom)
- jabradoodle 3y agoAwesome, love to see more Java devs pushing back on the spring madness. In Db.java, with the write/update/delete locks, that mutate both in memory and on disk, is there not a bunch of race conditions there?
- 7ep 3y agoThere are locks around those - for example, writeLock
- jabradoodle 3y agoI mean race conditions between the operations, e.g. an update followed by a delete: 1. update x in memory 2. delete x in memory 3. update fn checks for file on disk 4. delete x from disk 5. update x on disk Is this not possible and you end up with different state in memory and on disk.
- 7ep 3y agohmmm. it does seem possible. Let me look into that, thanks!
- 7ep 3y agogreat find. i’ve got some adjustments in mind, mainly carefully placed locks. i’d like to give you credit for the call out in the docs/acknowledgment file. is there some better way to reference you than jabradoodle? the code i’m considering is in the branch under_consideration.
- jabradoodle 3y agoThanks that is kind of you. For the time being I would rather not tie my real life identity to my Internet identity.
- mongol 3y agoI can see clear value in a framework that minimizes dependencies. The choice to supply both a web framework and a persistence / database layer puzzles me somewhat. I understand this can be the basis of an "everything included" framework, but I think especially for persistence, most would like to make a conscious choice independently.
- 7ep 3y agoThere’s nothing to prevent using any external db if desired. In fact i’m doing that for a client.
- mongol 3y agoSure, but do you want to elaborate why you included it?
- 7ep 3y agoin case you truly want to go as absolutely minimal as possible. i do. for my own personal projects, i use that database.
- ljm 3y agoWhat does ‘minimal’ even mean though? Code is code - either you pull it down as a dependency or you write it yourself, it all executes the same in the end. The minimal/zero-dep solution will have have bugs that have already been fixed or avoided by battle-tested libraries, and it will very rapidly lose minimal status as you start to build something serious in it.
- avmich 3y ago> What does ‘minimal’ even mean though? It doesn't include the batteries. The batteries - extra features - weight you down if you don't need them. So you'd better be able to avoid them. Large projects can be hard to audit to remove things which could be nice and often useful - but just not in your case. Smaller projects have an advantage that you can easier understand them and decide what you need to add and, crucially, how to add that better, from your personal viewpoint. It's really hard to have nice, tiny, composable building blocks, so we have rather few attempts at that. Actually, a big part of programmer's education is teaching him how to properly write something which is well known, just have many small variations which depend on both requirements and some preferences. With a smaller project you can see those choices easier - and have better chance to correct them the way you need. > The minimal/zero-dep solution will have have bugs that have already been fixed or avoided by battle-tested libraries Maybe. Maybe not - you need to have all branches of execution checked, and with all possible input data combinations - and then all problems to get noticed and, crucially, corrected. Some problems, like unnecessary delays, can avoid e.g. representation in the logs. On the other hand, with smaller projects you have less moving parts and better visibility where, and how, things could go wrong. If you want ultimate reliability with proofs, you'll find it easier going with smaller projects. So, as they say, there are programs so simple they're obviously correct and so complex it's not obvious which errors they have.
- kevincox 3y agoAm I missing something or does the quickstart recommend an XSS vulnerability? String name = request.startLine().queryString().get("name"); return Response.htmlOk(String.format("<p>Hi there %s!</p>", name)); Maybe having a little bit more available would be valuable.
- 7ep 3y agohere’s a more realistic example: https://github.com/byronka/minum_usage_example_mvn/blob/d649af5aae5087a3b23901fc6e5c2b3dc80df204/src/main/java/com/renomad/sampledomain/SampleDomain.java#L36 https://github.com/byronka/minum_usage_example_mvn/blob/d649...
- kevincox 3y agoLooks like that should be the example rather than promoting unsafe coding.
- ptx 3y agoMaking the user manually escape parameters (and be very careful not to miss any) seems at odds with the goals of ease of use and maintainability. Most template libraries do this automatically by default.
- 7ep 3y agoYou are not wrong. Just, here, priority is 1. minimalism 2. ease of use It's an uneasy balance. I am well aware of the value of fully-powered templating engines.
- schemescape 3y agoFor the record, I love this project's minimalist goal. Having said that, I agree with the other commenter that escaping by default (with an opt-out mechanism) is probably the better choice. I don't even think this violates your prioritization because it should result in less code when considering an app in its entirety (framework + logic).
- smrtinsert 3y agoI'm thinking of this as a nice programming exercise for the author. As for being a framework which promises more with less, that only holds until feature x is required.
- 7ep 3y agoa perfect example of the thinking behind most frameworks. I don’t think most people are looking for minimal. For those that are, this might be right up their alley. Minimalism is an interesting ideology. it’s about choosing to do more with less, and there’s a great deal of ingenuity in saying, i only have this one knife and a rope, how do i cross this chasm. so to speak. no offense intended to the batteries included crowd. this is just something i have developed a taste for.
- JackFr 3y agoYour kind of playing a little fast and loose with the term 'database'. You've implemented a naive persistent cache. (Don't get me wrong, I have too at times. they can be quite useful.)
- 7ep 3y agoI'll accept the naive mantle. But is this not a database? A database is an organized collection of structured information, or data, typically stored electronically in a computer system.
- quickthrower2 3y agoModularism is my favourite. I am enjoying using ExpressJS of all things, because it comes bare bones but you are a few mix/match middlewares from having it set up as you like. And the process of setting them up is not a chore, it is valuable, you now know how your thing works. Whereas frameworks give you the kitchen sink behind a facade that makes most happy paths easy. But eventually you have to deal with that complexity one way or another, and usually it is by hacking together stack overflow and github issue answers :-)
- deleted 3y ago
- beders 3y agoNames. The problem always comes down to naming. `StartLine.Verb.GET` is not a good name. Neither StartLine nor Verb are used in that context in the HTTP spec. The most widely used name for GET/POST etc. is Method. The author will find that these seemingly small things will hinder adoption.
- deleted 3y ago[deleted]
- ivan_gammel 3y agoAgree. Looking at the example project, this is not a single case, when a name could be better. Helpers and Utils are naming anti-patterns, so naming function ˋ(de)serializeHelperˋ is not a good idea.
- 7ep 3y agoNames. One of the two hard problems in computer science, along with cache invalidation. And off-by-one errors.
- 7ep 3y agoValid point. I was going off documentation like here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#start_line https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#s...
- jen20 3y agoThat page uses Method though, and places nouns at equal importance with verbs when describing them?
- msgilligan 3y agoThis is really cool to see. Congratulations! The existence of a project like this can lead to feedback that can improve other web frameworks and the JDK itself.
- revskill 3y ago[flagged]
- galdosdi 3y agoActual Java dev here, not just someone who used it in college and got annoyed -- but I have no idea what you're talking about. Java has not been boilerplatey for a long time, I'd say since sometime between Java 5 and Java 8. You do know you can declare multiple classes in a single file (static nested classes), contrary to the popular convention, right? And "public static void main" doesn't count as boilerplate, that's like one line in the whole program... The real nice thing about Java is everything is statically typed, unlike in TypeScript where just your code and if you're lucky some of your dependencies BUT NOT ALL OF THEIR TRANSITIVE DEPENDENCIES are properly statically typed, and before you know it you've lost the nice safety and it's a crapshoot whether your type errors will really be caught, because a transitive dependency can do whatever it wants with your callback that you typed one way but it didn't care because it was plain javascript.... This is why I am not a fan of either Typescript or PEP 484 statically typed python. Typing works best when it was mandatory from day one, as long as there is some random untyped code in there somewhere nothing is really guaranteed.
- jen20 3y ago> The real nice thing about Java is everything is statically typed Optional and generics would like a word... Edit: OK, since this got a downvote, let me be clearer, with some help from the parent: You just use Optional<T>, and if you're lucky some of your dependencies BUT NOT ALL OF THEIR TRANSITIVE DEPENDENCIES also use Optional<T> correctly and don't return null, and before you know it you've lost the nice safety and it's a crapshoot whether your Optional<T> will be null.
- kaba0 3y agoI have never ever ever seen a null inside an Optional -- the most common constructor actually Optional::ofNullable makes the correct decision, so you can't even fck it up, and if you deliberately try to, I'm sure intellij would scream your head off.
- Dungenesst 3y ago[dead]
- tofflos 3y agoGood job on coming out of beta. It's crowded out there so best of luck! I think the initial README could do a better job of showcasing the framework. I think including the Maven coordinates and the quick start example instead of linking to other pages could be a step in the right direction. Check out the README I wrote in https://github.com/tofflos/undertow-examples https://github.com/tofflos/undertow-examples to get an idea of what I'm looking for.
- theanonymousone 3y agoCongratulations. I believe there is room for a micro framework that is smaller than Javalin or SparkJava. That said, if you want to cash even more on minimalism, you may want to provide a single-file example using JBang[0]. [0]. https://jbang.dev/ https://jbang.dev/
- deleted 3y ago[deleted]
- tantamounta 3y agoYour run of Apache Bench only specifies -c20. Please try this with Platform Threads - not virtual ones. It'd be very interesting to see the performance. (This should just need a 1-line change of the Executor?)
- KronisLV 3y agoThe size statistics page is super cool: https://github.com/byronka/minum/blob/master/docs/size_comparisons.md https://github.com/byronka/minum/blob/master/docs/size_compa... Reasoning this way about software and dependencies more often seems like a good thing, just so we're aware of what we're actually getting into, especially with projects that use npm. I actually hadn't heard of Javalin before, which also seems nice: https://javalin.io/ https://javalin.io/ Aside from that, I've also had good experiences with Dropwizard - which is way simpler than Spring Boot but at the same time uses a bunch of idiomatic packages (like Jetty, Jersey, Jackson, Logback and so on): https://www.dropwizard.io/en/stable/ https://www.dropwizard.io/en/stable/ I do wonder whether Minum would ever end up on the TechEmpower benchmarks and how it'd stack up against the other libraries/frameworks there, those benchmarks are pretty interesting.
- karmakaze 3y agoI did a survey of light frameworks and settled on the Javalin + JDBI (from DropWizard) combo. That was at a Spring/Boot shop where we needed something with very short startup time for rapid scaling.
- scoot 3y ago3,757 what? KB, MB, GB, TB, PB, LOC, hours to download?
- voxelghost 3y agoLOC + Dependency LOC, it seems.
- js2 3y agoLOC
- twic 3y agoOn that page it says: > (all measurements of lines of code are for production code - that is, non-test-code) Given that this is Java, the author could have measured the total size of the bytecode, which is probably a more style-neutral way of measuring the fundamental quantity of code.
- rezaprima 3y agoI didn't see looping support for templating, like for rendering collection to HTML table. Did I miss something?
- 7ep 3y agoYou did not miss anything. It lacks that functionality, making it necessary to template the inner part, and then use that within an outer part. Fully-featured templating libraries provide this in the form of special syntax. This does not provide that level of capability.
- rezaprima 3y agoI see. So you intend to make templates logic-free. Perhaps you can implement like xtemplate that I used to use last century https://eeperry.wordpress.com/2009/08/08/php-xtemplate-the-basics/ https://eeperry.wordpress.com/2009/08/08/php-xtemplate-the-b...
- brap 3y agoTo anyone developing libraries: please, for the love of god, just put a damn code snippet right at the top. A simple hello world would do. If you're pitching me something, show it to me. People don't have to dig around to see what you've made. I think the average visitor will give you about 10 seconds to decide if this is something they might be into, and if they can’t tell then they’ll leave.
- animex 3y agoClick the giant "QUICKSTART" link and you'll get what you're asking for.
- RussianCow 3y agoI agree with the OP: you shouldn't have to click anything to get an idea of what it even is and whether it's remotely interesting to you. To me, "quick start" implies that my interest has been piqued enough for me to dive in further. If you can't convince me to continue reading in the first ~10 seconds, there's a high probability that I'm closing the tab.
- colonelpopcorn 3y agoIt's near the bottom of the page. It's admittedly a very little bit of with, but other frameworks don't make you work as hard.
- deleted 3y ago[deleted]
- waynesonfire 3y agoI think I gave it 3 seconds.
- p4bl0 3y agoI was thinking the same thing so I dived in the example. And now I understand why there wasn't a code snippet in the README: even a minimal app seems to requires multiple files in many subdirectories. I guess java stays Java, even when using a "minimal" framework.
- chunsj 3y agoWhy does almost all the Java based web development framework use "template" system, instead of generating HTML from code(like Flutter/Swift)? Is this due to the inherent limitation of Java language/syntax?
- Tainnor 3y agoIn order to make this not extraordinarily painful, you need some good language support for internal DSLs, or a template language / preprocessor, both of which Java doesn't really have. You could still do it somehow, but it probably wouldn't be the nicest experience. Plus, historically, the Java community has been in love with XML, so you'll find lots of templating libraries based on XML. Swift has function builders which are part of the magic that makes such DSLs practical. In Kotlin, which also runs on the JVM, this is possible much more easily than in Java: https://kotlinlang.org/docs/typesafe-html-dsl.html https://kotlinlang.org/docs/typesafe-html-dsl.html
- ecshafer 3y agoI wonder why more java frameworks don't reuse the parsing from JSP, but just drop the servlett part. Though maybe that's not as easily done as said.
- drdec 3y agoJSPs are implemented by transpiling them into servlets, so JSPs without the servlets doesn't really save anything (assuming you want to re-use what's out there).
- xxs 3y agoJSP literally compiles/translates to Servlets, as in extends them in the code, and everything you see is in their 'service' method effectively. JSP can consider JSP alike to C's preprocessor.
- xxs 3y ago>instead of generating HTML from code At the relative bottom (Servelet API level) it works that way, servlets have a direct access to input/output stream, and they have to write plain byte[] (or string via Writer). As for java syntax, it's not great for string manipulation, encoding (you will need some functions for all the html/javascript escaping). If you see url's containing ".do" extensions - that was the standard for calling servlets w/o anything, it has changed, of course.
- turbobooster 3y ago[dead]
- vbezhenar 3y agoI like this Java movement back from overbloated frameworks with decades of cruft. I thought about building my own libraries as well. Don't have time for that yet. What I don't like about this library: Java 21 requirement. Virtual threads are performance optimization, they should not be a requirement. If I'm fine with running thread per request, that's on me. I mean, we built apps 20 years ago which did that and they worked. They wouldn't work worse today. Everything bundled. I'm fine with mini-framework with everything, however it should be split with separate libraries. No module-info.java. I mean, we're talking about Java 21 which is 12 releases after Java 9. Time to embrace modules.
- deleted 3y ago[deleted]
- android521 3y agoit is my first time seeing java web framework project on HN. I am sure that this is a great project but for the love of god, just let Java die , please. There are plenty of better alternatives to choose from (nodejs,go, python, elixir, clojure, Ruby etc)
- deleted 3y ago[deleted]
- ilvez 3y agoI chose Java for one of the microservices that leverages JTS library, which was the tool I wanted for the purpose. I wanted to use normal Java, because the thing I needed to do was very simple. It works very well. Used Micronaut by the way. Java has its place.
- aspyct 3y agoHow is maven nowadays? Every time I see an interesting java project, I think about using it, and then I see "maven" and I remember the terrible experiences I had with it. Has it improved at all in the past 10 years?
- deleted 3y ago[deleted]
- kaba0 3y agoIt usually ‘just works’ on your side. Configuring it properly is also fine, but a bit more involved.
- frant-hartm 3y agoMaven is always more or less the same - you have properties, dependencies, build (plugins), profiles, maybe modules and dependencyManagement if you have multi-module build. That's it, every project is the same. In Gradle there is are infinite number of ways how to configure it. I haven't seen 2 projects done in the same way, when I want to understand a new gradle build, I need to learn few new Greadle (or Groovy) features. Sure, in very complex Maven builds there might be some quirks and some plugins have bugs, but it works so much better than anything else out there.
- ngcc_hk 3y agoName same as a python visual framework closely related to 3b1b. One may say it is apple record vs apple computer.
- SillyUsername 3y agoI built my bread and butter with Java and Spring for ~20+ years, and I can safely say whilst commendable to reduce the bloat, it's the language itself which is bloated af. Features bolted on late like function pointers (sorry lambda functions, which are effectively delegates, something they said they'd never do https://web.archive.org/web/20080127045532/java.sun.com/docs/white/delegates.html https://web.archive.org/web/20080127045532/java.sun.com/docs... ), too many deprecated APIs, keywords that mostly go unused and have alternatives (volatile - a CPU option for memory access with shared threads, transient - now handled by serialisation frameworks, synchronized - now handled by locks, protected - barely used in preference to package etc). I moved to Typescript, AWS lambdas and Express framework, it has all this framework's simplicity baked in. To other Java Devs who have made their bread and butter with the language (and perhaps nothing else), don't knock it until you try it, the path from Java to Typescript or other typed language is easier than it looks and you'll wonder why it ever took so long to knock up quick systems.
- deleted 3y ago[deleted]
- croo 3y agoJava is 28 year old, Typescript is 10. Give it another 20 year and similar patterns will emerge as the language matures.
- SillyUsername 3y agoTrue, but imho at some point people need to let go of legacy code because of the maintenance headache and start again, same is true for the whole eco system. I fully expect if I'm still alive in another 10 I'll be choosing something other than TS as a main language (fwiw I still do Java).
- thih9 3y agoMinimum usage example: https://github.com/byronka/minum_usage_example_smaller https://github.com/byronka/minum_usage_example_smaller
- tonyjstark 3y agoCongratulations! Looks like a fun project and Java really could need a bit of minimalism. I'm always intrigued by small frameworks like Minum et al. even if it's just to learn how things are done in an approachable way. Love to see stuff like this on HN, and I'm a bit surprised about the negativity in the comments.
- twic 3y agoThe author has written their own HTTP server rather than using the one provided with the JDK. They need to have a really, really good reason to do this, and i haven't seen such a reason reason documented anywhere. Other, much larger, web frameworks provide their own HTTP servers (or bundle Jetty etc), because they can make them more scalable, or more featureful, or support protocols the JDK one doesn't. But i don't think the author's HTTP server does that.
- lemper 3y ago> You will be hard-pressed to find another modern project as obsessively minimalistic. ... This follows self-imposed constraints, predicated on a belief that smaller and lighter is long-term better. the reason: obsession and self-imposed constraints.
- spuz 3y agoThere is a severe lack of minimal web frameworks available in Java so I appreciate the effort behind this project. Would it be possible to separate the database and templating packages into separate libraries? For example, could I used Minum with JDBI for the db library and Thymeleaf for templating?
- 7ep 3y agoyes, certainly you could.
- adrianmsmith 3y agoOne way in which this could be slightly more minimal is to remove the mvnw wrapper. Honestly if you want to do development on a Java/Maven project, I don’t think it’s unreasonable to have Java and Maven installed. The wrapper adds three directory entries to the top-level repo directory, and is lots of copy/pasted code.
- 7ep 3y agoit’s all a balance. i’m obsessive, yeah, but i’m also trying to have a bit of balance for the bigger picture to each choice. if you look back a few commits you’ll see where i wasn’t even using maven, just GNU Make! But i was convinced over time that taking a more conventional route for that would yield better returns.
- twic 3y agoIt's absolutely unreasonable to expect that, and the wrapper should stay. I don't have Maven installed anywhere, and i don't have Gradle on the global path, because i work on projects which require different versions of Gradle. Saying that removing this would make the project more minimal seems deeply confused to me. Minimalism is not measured in the number of directory entries at the top level, but by the amount of stuff the user has to understand. Taking the wrappers out does not reduce that.