Back to Posts

Reactive Kotlin vs Java

Posted in Programming

For me the best way to learn something is by example, so instead to create HelloWords I’ve been translating my Java Reactive Spring 5 Webflux example into Kotlin, and now that is done is time to analyze the results.

I’m not going to talk about performance here, I’ve done JMeter load tests on both services and they virtual identical, response times are just decimals apart. However sometimes Kotlin seams to perform better, I’ll not get into conclusions until I research more.

First lest look at how many life of code we have create for each project:

Lines of Code Src Test
Java 1004 1172
Kotlin 721 1017

This is a expected result since Kotlin syntax will be always shorten and easer to understand.

Now when we look at the maxim complexity reported by

Complexity Max
Java 45
Kotlin 8

I think we need to do a deep down on this.

I’ve need to modify some line breaks in order to fit the web, please check the repos

Let’s look at one of the methods in the more complex class in Java:

  Mono<SunriseSunset> createResult(final Mono<GeoTimesResponse> geoTimesResponseMono) {
      return geoTimesResponseMono.flatMap(geoTimesResponse -> {
          if ((geoTimesResponse.getStatus() != null) && (geoTimesResponse.getStatus()
              .equals(STATUS_OK))) {
              return Mono.just(new SunriseSunset(geoTimesResponse.getResults().getSunrise(),
          } else {
              return Mono.error(new GetSunriseSunsetException(SUNRISE_RESULT_NOT_OK));

And the equivalent method for the same class in Kotlin:

  open internal fun createResult(geoTimesResponseMono: Mono<GeoTimesResponse>) =
    geoTimesResponseMono.flatMap {
            if (status == STATUS_OK) with(results) { SunriseSunset(sunrise, sunset).toMono() }
            else GetSunriseSunsetException(SUNRISE_RESULT_NOT_OK).toMono()

Many times this is because of the extensions system that allow to write really tide code.

Let’s look at one of the methods in one of the handler class:

  Mono<ServerResponse> serverResponse(Mono<LocationResponse> locationResponseMono) {
      return locationResponseMono.flatMap(locationResponse ->
              ServerResponse.ok().body(Mono.just(locationResponse), LocationResponse.class));

And the equivalent method for the same class in Kotlin:

  fun serverResponse(locationResponseMono: Mono<LocationResponse>): Mono<ServerResponse> =
    locationResponseMono.flatMap { ok() withBody it }

In fact spring framework has create custom extensions for Kotlin.

Let’s look at our api router function class:

  static RouterFunction<?> doRoute(final ApiHandler apiHandler, final ErrorHandler errorHandler) {
                      route(GET(LOCATION_WITH_ADDRESS_PATH), apiHandler::getLocation)
                      .andRoute(POST(LOCATION_PATH), apiHandler::postLocation)
                  ).andOther(route(RequestPredicates.all(), errorHandler::notFound))

And the equivalent class in Kotlin:

  fun doRoute() = router {
      (accept(APPLICATION_JSON_UTF8) and API_PATH).nest {

Definitely Kotlin is more simpler and readable, but this is not only the main code lest check the test for our tests.

Testing our ThrowableTranslator in Java

  void translatePathNotFoundExceptionTest() throws Exception {
    assertThat(PathNotFoundException.class, translateTo(HttpStatus.NOT_FOUND));

And the same test in Kotlin

  fun translatePathNotFoundExceptionTest() {
      PathNotFoundException::class `translates to` HttpStatus.NOT_FOUND

But lets use a more complex test that includes mocking.

Testing one of the services error in Java

  void getLocationNotFoundTest() {
      ServerRequest serverRequest = mock(ServerRequest.class);

      ServerResponse serverResponse = apiHandler.getLocation(serverRequest).block();
      assertThat(serverResponse.statusCode(), is(HttpStatus.NOT_FOUND));
      ErrorResponse error = HandlersHelper.extractEntity(serverResponse, ErrorResponse.class);
      assertThat(error.getError(), is(NOT_FOUND));


And the same test in Kotlin

  fun getLocationNotFoundTest(){
      (geoLocationService `will return` LOCATION_NOT_FOUND).fromAddress(any())
      (sunriseSunsetService `will return` SUNRISE_SUNSET).fromGeographicCoordinates(any())
      val serverRequest = mock<ServerRequest>()
      (serverRequest `will return` GOOGLE_ADDRESS).pathVariable(ADDRESS_VARIABLE)

      val serverResponse = apiHandler.getLocation(serverRequest).block()
      serverResponse.statusCode() `should be` HttpStatus.NOT_FOUND
      val errorResponse : ErrorResponse = serverResponse.extractEntity()
      errorResponse.message `should equal to` NOT_FOUND

      geoLocationService reset `mock responses`
      sunriseSunsetService reset `mock responses`

In these cases the number of lines is not the key factor but the readability of the Kotlin test is great.


With a syntax that make things simpler and more readable I’ll stick with Kotlin for my personal projects for a while meanwhile I still learning Reactive Programming.

About Juan Medina
I'm just a normal geek that code all kind of stuff, from complex corporate applications to games.

Games, music, movies and traveling are my escape pods.

Read Next

Why we should use functional programming with Kotlin?