In short, if you are a conservative institution like a bank and evolving your tech stack at a glacial pace; yes you can still use Java. Everybody else, you probably should be using Kotlin.
My advice to anyone looking to do this is:
1) Do it, it's easy and you end up with better code. You can start simple and mix Java and Kotlin code. I would advice starting with some tests or some new features.
2) Beware of the java idioms and cruft in Spring and do things the Kotlin way. So, DSLs instead of annotations + AOP, co-routines instead of spring flux, immutable data classes instead of java beans, etc.
3) Spring has a lot of stuff and not all of it is great or even good. IMHO the added advantage of e.g. spring-cloud or spring-data is very limited and sometimes it's just very limiting/backwards. I ripped out spring-data on several projects where people naively supposed it was the easiest/best way to interact with Elasticsearch. It turns out it is neither. Spring cloud sounds nice until you realize most of the stuff you need is supported in the amazon driver but yet not exposed in spring-cloud. Also all the code samples on Amazon are for their own driver and not for spring-cloud.
4) Re-assess if you actually want to go anywhere near hibernate. IMHO it made a lot of sense when java beans were hard to write. Kotlin data classes take away most of that pain and there are some nice alternatives. Also, you should be using non blocking IO for talking to your DB and hibernate is still stuck on blocking IO. That in itself is a good reason to not use it on new projects.
Once you get a bit further, you'll find yourself wondering if ktor would work. The answer is probably yes. It's actually pretty good. Spring does a lot of things but ultimately do you really need all of that and the associated complexity?
I think it's a good sign when you see it start to creep into random, seemingly disjointed areas, like how Kotlin DSLs are invading a lot of areas of dev-ops/infra-as-code. It speaks to the strengths of the language rather than the passion of the supporting community, imo.
Performance driven purists can continue to doubt, but I'm betting long by a mile on Kotlin, all it will take is time, more and more frameworks and ecosystems will integrate Kotlin, and rough edges can be polished.
>I would advice starting with some tests
The way that Kotlin extension functions and DSLs breathe fresh air into JUnit testing is hard to fully communicate. For me at least, it makes writing test code actually not suck anymore, and even fun in some cases.
You can thank the Oracle lawsuit for this.
Google has been preparing Kotlin as their escape hatch.
In about 5 years it will be as meanigfull as former guest languages are today.
Without having any language support for what Java 25 will be capable of doing with value types, GPGPU, SIMD, Graal integration, as per JVM/Java roadmap, as it will be jailed by what Android is able to do.
Admittedly I haven't looked at Spring w/ Kotlin at all, but I can't imagine it would solve fundamental annoyances I have with it (Why can't I capture logs globally while actually handling my exceptions locally?).
IMO the best library for Kotlin web stuff is http4k. Really nice documentation, first class integration for marshalling JSON with Moshi instead of Gson/Jackson, and very good, up-to-date consistent documentation.
Maven is a bit easier to Google; mainly because it stopped evolving in any meaningful way about a decade ago and nothing is really changing. The XML feels really backwards at this point It seems attempts to move away from that have stalled. It's also a lot slower to run. We're using it on the project I'm currently on and it eats up a lot of my time. Every time I do an mvn spring-boot:run, it goes off and compiles stuff. Even after it just did that and literally nothing changed. Gradle is much better at eliminating unnecessary work.
It looks like there is a kotlinx-coroutines-reactor module, I'm not sure if that's what you are referring to.
Basically, with co-routines you lose the need for all the container types like Mono, Flux, etc. and replace them with simple suspend functions. This makes code a lot more readable, easier to test, and reason about.
Instead of callbacks for errors, you can rely on the normal try/catch. Any uncaught exception causes the co routine and co routine scope to fail and cancel in a controlled way. The Flow API allows you to do reactive style processing. It also handles back pressure and a few other things.
Basically fully reactive code written using this is structurally very similar to the normal blocking version of the code.
But you mention not using Hibernate. I fully agree myself, and used JOOQ, but what is your preference?
For database stuff; I've always preferred good old JdbcTemplate in Spring combined with TransactionTemplate. IMHO writing mapping code is not that much of a problem; especially if you stop pretending that your complex object hierarcy maps 1 to 1 to tables and do a proper database design instead.
Writing that code sounds harder than it is. Compared to littering your models with annotations to say "this field is that column and this type", it's about the same lines of code. Except it's in one place where it is easy to maintain. Several frameworks exist to automate this business of course but given how trivially easy it is to do this manually, I don't see the value.
Have you tried using Spek?
Scripting is better because Kotlin doesn't have simple dependency management like Grape and compilation speed is way faster than Kotlin's. One of Kotlin's downsides is compilation speed and kts (kotlin script) is even slower. Also, Groovy still has ton of utility methods in GDK not matched in kotlin stdlib.
Other than that, I'm sad to say, Groovy is dead or in process of dying. I'm seeing companies rewriting Grails apps to Spring Boot and switching to Kotlin dsl in Gradle. It's a shame really, such a fun language to program in.
Though there are some experimental non-JDBC drivers using non-blocking I/O to move your blocking code from backend into database. In the end you're still blocking.