[HN Gopher] Show HN: Minum - A minimal Java web framework
       ___________________________________________________________________
        
       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  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)
        
       Author : 7ep
       Score  : 81 points
       Date   : 2023-09-25 18:07 UTC (4 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | rezaprima wrote:
       | I didn't see looping support for templating, like for rendering
       | collection to HTML table. Did I miss something?
        
       | beders wrote:
       | Names.
       | 
       | 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.
        
         | ivan_gammel wrote:
         | Agree. 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 wrote:
           | Names. One of the two hard problems in computer science,
           | along with cache invalidation. And off-by-one errors.
        
         | 7ep wrote:
         | Valid point. I was going off documentation like here:
         | https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#s...
        
           | jen20 wrote:
           | That page uses Method though, and places nouns at equal
           | importance with verbs when describing them?
        
         | [deleted]
        
       | KronisLV wrote:
       | The size statistics page is super cool:
       | 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/
       | 
       | 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/
       | 
       | 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.
        
       | mongol wrote:
       | I 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 wrote:
         | There's nothing to prevent using any external db if desired. In
         | fact i'm doing that for a client.
        
           | mongol wrote:
           | Sure, but do you want to elaborate why you included it?
        
             | 7ep wrote:
             | in case you truly want to go as absolutely minimal as
             | possible. i do. for my own personal projects, i use that
             | database.
        
               | slaymaker1907 wrote:
               | One suggestion I have would be to include a very minimal
               | implementation of login management (basically just
               | properly hash/salt passwords and provide some easy way to
               | add users). I've used Django before for the sole reason
               | that it includes a database and user management because
               | some API had to be login only since said API had high
               | resource usage.
               | 
               | I can see how having your own database is kind of
               | "minimal" in the Java sense of the word. You don't need
               | to install 50 different packages just to make a simple
               | web app. There are minimal frameworks in the sense that
               | they only provide a basic web server, but those are so
               | minimal that you are forced to install a bunch of
               | packages. It's minimal in the sense that create-react-app
               | was minimal (RIP).
        
               | 7ep wrote:
               | Your wish is my command ;)
               | 
               | https://github.com/byronka/minum/blob/master/src/test/jav
               | a/c...
        
               | pvorb wrote:
               | Why is this under src/test/java?
        
               | ljm wrote:
               | What 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 wrote:
               | > 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.
        
               | avmich wrote:
               | > Code is code - either you pull it down as a dependency
               | or you write it yourself, it all executes the same in the
               | end.
               | 
               | This looks like an oversimplification sometimes. You
               | surely can solve the same problem in programming in
               | different ways. An important part could be unstated
               | assumptions you relied on when you wrote your code - and
               | sometimes it's really important to understand those
               | assumptions, or the code could strangely misbehave. "All
               | executes the same" could literally be not true - some
               | testing may suggest that, but more expensive testing,
               | which is often not done, could show that for some unusual
               | combinations the behavior is different.
               | 
               | How do you know it's the same?
        
               | schemescape wrote:
               | I'm reading it as "minimal in scope". Scope creep tends
               | to be a given for established/battle-tested libraries,
               | and I'd argue that _over time_ scope creep could
               | counteract security benefits of being battle-tested.
               | 
               | Note that I'm not basing this on data, just on my
               | intuition that a lot of major security bugs seem to be
               | related to obscure/infrequently used functionality.
        
       | kevincox wrote:
       | Am 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 wrote:
         | here's a more realistic example:
         | 
         | https://github.com/byronka/minum_usage_example_mvn/blob/d649...
        
           | kevincox wrote:
           | Looks like that should be the example rather than promoting
           | unsafe coding.
        
           | ptx wrote:
           | Making 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 wrote:
             | You 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 wrote:
               | For 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).
        
         | [deleted]
        
       | tantamounta wrote:
       | Your 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?)
        
       | msgilligan wrote:
       | This 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.
        
       | theanonymousone wrote:
       | Congratulations. 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/
        
         | [deleted]
        
       | jabradoodle wrote:
       | Awesome, 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?
        
       | revskill wrote:
       | [flagged]
        
         | galdosdi wrote:
         | Actual 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 wrote:
           | > 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 wrote:
             | I 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.
        
               | jen20 wrote:
               | The problem is whether the optional itself is null, not
               | whether the contained value is.
        
               | kaba0 wrote:
               | That's not a problem either.
        
             | galdosdi wrote:
             | Yep, this is a great point, and while these days people use
             | stuff like @NonNull/@Nullable, it does not help a lot, for
             | the exact same reason.
             | 
             | I wish Java had had non nullable types as default from the
             | getgo, and it's hard to add now for the same reason JS/PY
             | have a hard time adding static typing
        
           | revskill wrote:
           | You're correct ... in theory.
           | 
           | At least in this project example code, i see tons of empty
           | class like Result.java with empty content, on separate file.
           | 
           | So is this normal convention for Java dev ? No eslint (or
           | similar tool) to prevent boilerplateness ? That's my point.
           | 
           | Do you Java dev have strict standard on prevent such things
           | spread on all codebase, ecosystem,... ?
        
         | peterashford wrote:
         | I think the verbosity of Java is all in your head
        
         | willsmith72 wrote:
         | Yeah if I wanted to write for a JVM, I'd use kotlin
        
           | 7ep wrote:
           | Interesting you say that: https://github.com/byronka/r3z
           | 
           | Basically the same thing as Minum, but in Kotlin.
        
       | Dungenesst wrote:
       | [dead]
        
       | tofflos wrote:
       | Good 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 to get an idea of
       | what I'm looking for.
        
       | smrtinsert wrote:
       | I'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 wrote:
         | a 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 wrote:
           | Your 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 wrote:
             | I'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.
        
           | shrimpx wrote:
           | The 'batteries included' space is definitely a market. For
           | example https://streamlit.io is wildly popular with data
           | teams for quickly making a pre-styled, usable enough web UI
           | to put on top of some model, with controls that are
           | automatically reactive. Those ppl have zero interest in
           | fiddling with modular systems or spending time optimizing and
           | scaling web apps.
        
           | quickthrower2 wrote:
           | Modularism 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 :-)
        
       ___________________________________________________________________
       (page generated 2023-09-25 23:00 UTC)