Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Javalin 1.0 – A Kotlin/Java web framework (javalin.io)
271 points by tipsy- on Nov 7, 2017 | hide | past | favorite | 87 comments


Good job reaching a stable release.

I have a Kotlin microframework that never made it past hobby-level stability[1].

One thing I found out is that you really have to write a library in Java if you want it to be used in both Java and Kotlin. Java -> Kotlin is effectively one-way interop.

I also found async programming to be really hard in Java which is why I wrapped Jetty. Meanwhile async APIs like Netty and Undertow were completely exotic to me.

For example, I couldn't figure out how to go from `Request -> Response` to `Request -> Promise<Response>` by wrapping Netty.

One thing I did find out was that Kotlin is probably my favorite language. Very similar to Swift, though I wish you could re-open 3rd party classes to make them conform to additional interfaces which you can do with Swift protocols.

I also never figured out how to hot reload code without restarting the server. Even JRebel didn't work for me. Looking at Jetbrains' own framework, their code that implements reloading is pretty intimidating[2].

OP is also the author of https://github.com/tipsy/j2html which I've been using in my own small servers. I couldn't figure out a better way to get typesafe html templating in the ecosystem.

[1]: https://github.com/danneu/kog [2]: http://ktor.io


This is definitely NOT TRUE. I've written a library which is used from both Java and Scala and it just works. Here: https://github.com/Hexworks/zircon

Just because you didn't manage to get it working does not mean that interop is not two-way.


> Java -> Kotlin is effectively one-way interop

Could you provide some more details? I'm a bit surprised by your statement because Kotlin team has put a lot of effort into providing mostly seamless two way interop. Kotlin project itself is ~50% Java (specifically to test interop).


I'm really rusty, but if I can recall the simplest example correctly, you can't just naively go from this Kotlin code:

    Server { req -> Response().html("<h1>Hello world</h1>") }
to this Java code:

    new Server(req -> new Response().html("<h1>Hello world</h1>") 
Because Server is implemented in Kotlin and the Java lambda certainly isn't a kotlin.Function.

If that's a bad example (foggy memory), another one would be the use of @DslMarker or reflection to build my type-safe router: https://github.com/danneu/kog#type-safe-routing. Or how about inline functions with reified generics.

Kotlin does have Kotlin->Jvm interop annotations, but my take-away was that you would have to put some thought into your API and possibly make concessions so that you could sufficiently annotate it to the point that it's pleasant to use from Java. Not everything maps.

For example, you can see that OP went the route of using Java at the interface edges yet Kotlin internally to solve interop for their project.

I admit that "effectively one-way interop" is too heavy-handed of a statement, but there's definitely asymmetry that I ran into on my own project. For example, I would not recommend building something in Kotlin in the hopes that, once you're done, you can just sprinkle on some @Jvm annotations and end up with an API that's compelling to use from Java.


That's because the concept of a typed lambda function doesn't really exist in Java; in Java 8 lambdas are syntactic sugar for SAM-type object creation. (There are other interface warts too: @DslMarker and parameterized receivers, as you mention; treatment of void vs. Unit; different default collection types; destructuring data types, and the need to clutter your code with 'new' if you use them a lot; etc.)

It's similar to any interop problem: if you want your library to be accessible from lots of languages, its interface better be the lowest common denominator of the features they support.

There's nothing stopping you, though, from defining your interfaces in Java and then implementing those interfaces in Kotlin. The Kotlin interop code even will do a good job letting you use Kotlin's syntactic sugar for this, eg. you can pass Kotlin lambdas to functions that expect a SAM-type, or use 'with()' to treat a conventional builder pattern as a DSL.


Hasn't really been my experience - I've found it pretty easy to write eg. Hadoop classes, Rome plugins, servlets from Kotlin. You do need to be aware of what code Kotlin is generating for you, and there are occasional warts, but in general you just implement your interfaces and enjoy the boilerplate that Kotlin frees you from typing.


I don't have interop issues with your examples either. Calling Java from Kotlin is very pleasant.

What I found is that it's the other direction that takes some thought. For example, my Kotlin library needs more help than just @Jvm annotations to be usable from Java.


All my examples are calls into Kotlin from Java. With Hadoop, you're implementing interfaces that the framework instantiates via reflection and then the Java framework calls the Kotlin code. With Rome, you're creating Kotlin objects that implement a Java interface and then they're called from Java code. With servlets, the servlet container (Jetty, in this case) holds a reference to the servlet and then calls its serve() method upon an HTTP request.


You are surprised because it is not true. I can prove that you can write two-way interop just check the library I've written and posted above.


You can write two-way interop -- I didn't mean to suggest otherwise.

But there are Kotlin features that don't map like type-safe @Dsl's which puts you in a position where you have to make concessions for interop.


Now that is true. You also can't use reified generics (which is a bit hacky anyway).


"It totally works...except for A, B....oh yeah and C, but C kinda sucks....well D is awful too, you should never use D...."

So basically, he was right, and you weren't. There is no seamless 2-way interop, yes?


I don't understand this sentiment. I understand Kotlin has more features than Java, and of course it's tough to call the advanced things from Java. At least so I would think.


No he was not right. You can write two-way interop and it is not hard. I have actually written a library which does it. He did not say that "the two-way interop is not seamless". He said that you "can't write two way interop code" which is not true.


> One thing I found out is that you really have to write a library in Java if you want it to be used in both Java and Kotlin. Java -> Kotlin is effectively one-way interop.

Hah. As someone who remembers the early days of Scala - the promise of seamless interop followed by the realisation that a language-idiomatic API requires much more than being able to seamlessly invoke a method - I can't say I'm surprised.

> One thing I did find out was that Kotlin is probably my favorite language. Very similar to Swift, though I wish you could re-open 3rd party classes to make them conform to additional interfaces which you can do with Swift protocols.

Maybe look at Scala; implicit conversions offer an easy-but-somewhat-hacky way to do that, while typeclasses are a very elegant general solution that a lot of libraries are based on these days.


"One thing I found out is that you really have to write a library in Java if you want it to be used in both Java and Kotlin. Java -> Kotlin is effectively one-way interop."

Could you please explain this.


I think it means that a library written in Kotlin is difficult or impossible to use from Java.


Not really true from my experience. For example, here's a Markdown library written in Kotlin that you can use with a plain Java interface: https://github.com/valich/intellij-markdown


No no no no. Kotlin provides a lot of tools to make your library usable from Java and it works.


You have to write your Kotlin anticipating it'll be called from Java though (e.g. by using SAM interfaces instead of function types for your arguments)


This does not mean that it is a one-way interop. When you write it the right way, it will work from Java.


Is Kotlin's function not an SAM interface? I'm pretty sure Scala's is.


> though I wish you could re-open 3rd party classes to make them conform to additional interfaces which you can do with Swift protocols.

Mmmh really? I just reread the Protocol section of the Swift documentation and I didn't find this.

If I have a class I can't modify and that doesn't conform to protocol `Foo`, can I make it conform to that protocol?

A similar feature is being considered for Kotlin since this opens up all kinds of interesting mechanisms (notably, ad hoc polymorphism) but I don't see how to do that in Swift right now.


> If I have a class I can't modify and that doesn't conform to protocol `Foo`, can I make it conform to that protocol?

Yes, you can.


Not sure if that's a good thing though. I read some of the Swift standard library source code and found it very difficult to piece together all the stuff added by extensions, where they come from and where the original class definition is.

Obviously, it's going to be easier if you have written the code yourself, but what if someone else needs to read it?


Can you point to the relevant documentation section? I couldn't find it.


Thanks! Yeah, I had to leave a few parts as Java in order to get the interop right. Anything that takes an functional interface needs to be Java, so the main API entry points are all Java. Most other classes and all internal code is Kotlin. I originally wrote it all in Java, and ended up with about 30% less code after I rewrote it to Kotlin.


Can someone illuminate me on the necessity/benefits of embedding Jetty? I can never seem to understand what it offers that java.nio does not on a fundamental plumbing level (for sure, Jetty provides a lot of convenience classes on top of that plumbing), yet I see a lot of projects that could potentially get away with the plumbing embed Jetty and its thousand(s?) of minimally documented classes.


I can never seem to understand what it offers that java.nio does not on a fundamental plumbing level (for sure, Jetty provides a lot of convenience classes on top of that plumbing)

Creating a minimalist server is an interesting excercise, everyone should do it to see how it's done imo. BUT it's the stuff like parsing http headers, query parameters, and request bodies (formencoded, chunked files?) that make a solution like Jetty worth while. Again, writing an http parser is a valuable learning experience, but your boss really doesn't want you spending time on it, OR paying to support it going forward.

As an aside, it used to be a thing in the late 90's early 2000's for every application out there to have it's own "XYZ Transport Protocol" ie XYZTP, and it really, really sucked.


And it isn't like this stuff is exactly trivial: with content transfer encodings, trailers, and exotic stuff like Expect: 100-continue, no one ever does this stuff correctly when they think they can just throw it together :/.


Makes sense. I guess I was a bit biased because I saw it used in projects that didn't need HTTP at all (can't unfortunately remember them).


> for sure, Jetty provides a lot of convenience classes on top of that plumbing

That's really the benefit. I have been using jetty for years. I trust them a lot more than I trust myself to create a web-server. If I were to write everything from scratch, I would never have finished the project.


It depends what you want to focus on: build a web server or a simple REST framework.

About a decade ago I worked on the query processor component for the Yahoo Vespa platform and I spent a month writing a web server to squeeze as much performance out of the JVM as possible. And indeed it was quite a bit faster than Jetty. Speed being a bit significant when you have a stringent latency budget.

However, I ended up deciding it wasn't really worth it. The extra millisecond or so consumed by Jetty wasn't worth the cost of having to maintain a relatively complete implementation of HTTP. So I took out my implementation and put Jetty back in.


There's also undertow, lighter and smaller memory/size footprint.


Yeah looks very good.

http://undertow.io/


Great framework. I hope it takes off.

Oh a separate note, I'm relieved that for once the java version of demo code isn't twice as long as $otherJvmLanguage. Java's come a long way.


Thanks! Java8+ is what you make of it really. The syntax and standard APIs are still a bit clunky compared to $otherJvmLanguage, but you can make great APIs in Java.


This is a bit off-topic, but, as we are already discussing Kotlin, for a person new to the whole Java world, does anyone have a suggestion for a good ORM which plays nicely with Kotlin? (Elephant in the room being Hibernate but I'm intimidated by the complexity. Looking for something way more lightweight).


Have you tried jOOQ?

https://blog.jooq.org/2017/05/18/10-nice-examples-of-writing...

It might be a bit too lightweight for your tastes, but I'm very satisfied with it. Never used it with Kotlin tho, but according to the above link it seems to be supported just fine.


JDBI3 [1] has Kotlin plug-ins [2], and makes it easy to create simple DAOs without having to inform the framework about the entire database structure.

1: https://jdbi.github.io/ 2: https://jdbi.github.io/#_sqlobject


The library created by JetBrains:

https://github.com/JetBrains/Exposed


This reminds me of NancyFx for .Net and Flask for Python. I enjoy micro-frameworks like these, They make web development a bit less intimidating.

I hope this projects takes off.


NancyFx was also the first thing I thought off when looking at the examples. Before the .NET Core days I always used NancyFx as a drop-in REST service when I needed one in a non-web app setting, like a Windows service.


Out of curiosity, what about .net core changed this picture for you?


Now you can use .UseRouter extension to achieve something similar in ASP.NET Core 2 (https://github.com/dodyg/practical-aspnetcore/blob/master/pr...)


Thanks, it does look nicely similar, but I still far prefer NancyFX's modules - this is an awkward context to do all this wiring.


I'm not sure if I would call a framework that uses jetty under the hood, that micro...


Personally I don't use macro/micro to describe the bytecode footprint, but rather the API/conceptual footprint. If Jetty is secure and performant, and Javalin keeps it encapsulated, I think micro is a fair descriptor still.


Why not? Jetty is pretty lightweight as far as JVM http servers go...


Well if nancyfx is micro so is Javalin. NancyFX is nowadays built on Kestrel from ASP.NET Core.


Looks nice and clean. What use cases make this a better choice than Ktor? This is an important question to answer because Ktor seems a bit more complete, has more contributors, and is backed by IntelliJ.

One big point in Javalin's favor: it does have more documentation than Ktor, which is currently missing some rather important parts (e.g. having no documentation for authentication and authorization is kinda unforgivable).


I'm slightly biased of course, but Javalin is just a lot simpler to use. That might be because it's inherently simpler, or because Ktor's docs (as you pointed out) are very incomplete. I've tried to setup simple apps in Ktor to compare how it feels to write apps in it compared to Javalin, but I have given up on a lot of them because of the lack of documentation.

Other than that, Javalin is aimed at java-devs who have switched (or are interested in switching) to Kotlin, and works equally well in Java and Kotlin. Ktor is probably a better fit if you're a Kotlin purist.


I just came here to say I am using your project and I like it. Good job and thanks!


Thanks, I appreciate it.


I'm glad more frameworks follow the simple and concise way of Spark.

However, why support both Java and Kotlin, it seems that would create more work with no real need ? Admittedly, I've been burned in the past with Play! which said they would support both Java and Scala but using the Java version I always felt a lot behind in feature support.


It's not that much more work. You have to be careful with a few concepts (like SAM/Functional interfaces), but most of the time you can just write in Kotlin. I want to support both because a lot of companies are probably like the one I work for, where there are a lot of java-devs, and a few of them are pushing for kotlin. This seems like a good compromise to me.

Play was two different projects tho? There is only one Javalin source.


There is only one for play as well


Okay, poorly worded. I think (please correct me if I'm wrong) that in play you have distinct parts of the code-base that are for Java developers, while other parts are for Scala developers.

In Javalin, although some parts are written in Kotlin and some parts are written in Java, there is 0 duplication. If one part is written in Kotlin, both Java and Kotlin developers use that part. If a part is written in Java, both Java and Kotlin developers use that part.


That is correct. There are 2 separate APIs (that come from a single project). This is because Scala can support a bunch of functionality that Java (and Kotlin) can't support (type classes, higher kinded types, etc.). So your options are to hamstring the API for Scala or have 2 separate APIs.


From looking at the codebase, looks like there isn't any explicit "support Kotlin and Java", because most of the code's written in Kotlin.

Also, Kotlin and Java are meant to be well interoperable, so the Java support sort of comes by default. So it won't be the same as Scala + Java. I've been burnt by Apache Spark which has an awful Java API compared to Scala (and Python).

If someone has a better answer, I'd love the education :)


Not a Java developer by any means, but I wanted to say this looks like a very clean and well thought out design.


It says it's 'inspired by Sparkjava', what does it do differently and/or better?


Looks like Java version is not that different in terms of readability and lines of code...


That's the point. It's not a framework for kotlin purists, but for java-shops/java-devs who want to try out kotlin. It should work more or less the same in both languages.


Awesome! Why are routes added after the server has started? That makes me a bit worried, I would like to initialize the app completely before accepting requests, that's more or less necessary when under high load...


You can add them before starting the server if you want. I usually put them after just because I like separating them out. Should only take a few milliseconds to add them.


How would I find it coming from Flask and SQLAlchemy? Seems only a matter of time before such a transition comes quite easily, have been watching Kotlin and Swift with interest


How does Javalin comapres to ktor ?


I've been thinking about porting from sparkjava (another jvm jetty based microframework) to this. Cool. My problem with Sparkjava is the slow development time.


I wonder what the benefits of this API surface is? Yes, it is beautiful but what are the benefits? Declaring some routes and map them to lambdas or functions is not exactly something new and also not that mission critical. Why not working on something established?

I am a C# dev and neck deep in .NET Core with all its flexibility. Maybe that is the reason I miss the point.


Hey man, im currently learning web dev and want to learn asp.net core for web development, im attracted to it after seeing that Stackoverflow uses it and also bcoz i can do a little bit of C#. Your thoughts?


Does Javalin have support for REST endpoint versioning?

I.e. does it support any of versioning types mentioned here: https://www.troyhunt.com/your-api-versioning-is-wrong-which-...


This looks clean and concise. A very good start. I like it, easy to pick up. Kudos for releasing 1.0.


That github pop-up was quite infuriating. Made me lose concentration and close the page when I realized it was just to get stars on github.


Sorry about that. Getting people to participate on GitHub is pretty hard. I feel dirty for doing it, but it helps.


I find it kind of cute myself (and went ahead and starred it) but I could see how others might find it distracting.


Still not used to see lambdas in java. Nice I guess


How would this compare with something like vert.x? http://vertx.io


Javalin is better suited for smaller/simpler projects (the library is a lot easier to understand and easier to setup). Vertx is a lot more powerful. If I ever found myself in a position where I'd need to create a massive and performant service (10m+ daily users), I'd probably choose vertx.


How about metrics/healthchecks?



I've used dropwizard for years, that is why I was asking ;-)


Java + Kotlin = Javalin :D


Except Oracle lawyers wouldn't like Java being literally used as part of the name, though I hate to say this.

That's why javaslang was renamed to Vavr: https://github.com/vavr-io/vavr


I always thought Kava would be a good name for a Kotlin/JVM framework.

Java was named from the coffee from Java, Indonesia. Kava is a beverage consumed throughout the Pacific Ocean cultures. Similar enough :)


Not interested in new web frameworks until they appear here

https://www.techempower.com/benchmarks/#section=data-r14


.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: