Showing posts with label Kotlin. Show all posts
Showing posts with label Kotlin. Show all posts

Friday, 27 June 2025

Brain fart

Sometimes, when I'm programming, I haven't got a good idea of how to do something. What I do have is a large collection of really bad ideas, that I use when I don't have a good idea.

Apparently, good ideas take time. And sometimes they only happen after trying out some really horrendous ideas.

So, I checked the follwing String expression in Kotlin in, and I got some code review comments on it.

"$description $additionalDescription"

The comment was: "put a trim() on the entire thing, as the additionalDescription, which is provided by the user, can be anything (like for example spaces or just empty)".

And I got stuck on that. I came up with something horrendous like the following:

"${(description + additionalDescription).trim()}"

Of course you can immediately see where I went wrong, but once you get invested in the String template solution, sometimes it's hard to break out of that solution again.

The solution I went for was (obviously):

"$description $additionalDescription".trim()

Thursday, 24 April 2025

Compatiblity between Kotlin and Java regarding Default Methods

In short, default methods in interfaces in Kotlin are not compatible with Java.

That's the short version.

The long version follows.

Let's have a simple Person interface written in Kotlin:

Now we wish to use it in Java.

This doesn't work. Although the interface defines a default implementation of getGender(), this default implementation is invisible when called from Java.

java: org.mrbear.kotlin.interfaces.MrBear is not abstract and does not override abstract method getGender() in org.mrbear.kotlin.interfaces.Person

Now, in the past there used to be something called @JvmDefault, but that is deprecated and doesn't work.

Instead it has been superseded by @JvmDefaultWithoutCompatibility1 and @JvmDefaultWithCompatibility2 (which, quite frankly, makes it a tad less understandable).

Also, when you use either annotation, you are required to add a command line parameter when you compile, or it won't work.

With compatibility requires -jvm-default=enable.

Without compatibility requires -jvm-default=no-compatibility.

However, it seems that the default is with compatibility that it is turned on automatically in Kotlin 2.2. Which will be released soonish hopefully.

How it works

Apparently what happens is that Kotlin automatically creates an Abstract class in the Interface that implements the methods that are default (under water). The abstract class is called Interface$DefaultImpls.

If you run Without Compatibility, it means that the DefaultImpls won't be generated but only "real Java default methods in the Interface". This means your interface in Kotlin will actually change (and is therefore not backwards compatible).

See reference [3] for more details.

References

[1] Kotlin LangRef - JvmDefaultWithoutCompatibility
https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.jvm/-jvm-default-without-compatibility/
[2] Kotlin LangRef - JvmDefaultWithCompatibility
https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.jvm/-jvm-default-with-compatibility/
[3] KT-4779 Generate default methods for implementations in interfaces
https://youtrack.jetbrains.com/issue/KT-4779/Generate-default-methods-for-implementations-in-interfaces

Tuesday, 4 March 2025

Kotlin Operator Overloading

So my colleague mentioned operator overloading, and how much fun it is.

So I wrote a little test.

It works pretty good, but for infix functions it has a very high "syntactic sugar" and less about "real" operator overloading.

Also, the reference page in [1] indicates that for Infix functions, the precedence has fixed rules that do not (always) conform to precedence that we would assume.

My colleague told me that a number of infix functions were created for QueryDSL, so we could write a semblance of SQL in Kotlin, but the precedence tends to screw things up.

We removed these infix functions from our source code again.

So, use sparingly and only when it makes sense. For example if it makes your code a magnitude easier to read/reason about and preferable with as small a scope as possible.

References

[1] KotlinLang - Functions
https://kotlinlang.org/docs/functions.html#function-scope
Baeldung - Operator Overloading in Kotlin
https://www.baeldung.com/kotlin/operator-overloading
Baeldung - Infix Functions in Kotlin
https://www.baeldung.com/kotlin/infix-functions

Thursday, 19 December 2024

Kotlin and Java and Interfaces and Automatic Getters and Setters

Kotlin is great, Java is great, but there are sometimes little things that can be a little bit tricky. Especially when combining the two.

I am going to talk about one tricky thing now.

So we have an interface in Java:

And I wish to implement it using an enum in Kotlin.

Like so:

Obviously this will break, because a public val description automatically gets a getter in Kotlin, which conflicts with the implementation of the getDescription method.

You'll get error messages during compile time like this:

Platform declaration clash: The following declarations have the same JVM signature (getDescription()Ljava/lang/String;):
Platform declaration clash: The following declarations have the same JVM signature (getDescription()Ljava/lang/String;):

Well, you think, that's fine. If Kotlin already makes a getDescription automatically, I can simply remove my method getDescription() from the enum.

But that doesn't work. It immediately starts complaining that you have not implemented all members of the interface.

The way to solve it is to make the description field private ("private val description: String") so Kotlin no longer automatically creates a getter.

Trivial but a bit surprising.

From what I can tell, Kotlin is being careful not to create what they call "accidental overrides".

References

YouTrack - KT-6653 - Kotlin properties do not override Java-style getters and setters (created 10 years ago)
https://youtrack.jetbrains.com/issue/KT-6653
YouTrack - KT-19444 - Add JVM-specific annotation to permit "accidental" overrides of interface members
https://youtrack.jetbrains.com/issue/KT-19444

Thursday, 28 November 2024

Solution: Problems with Kotlin

Well, the solution to [1] is obviously that you are missing a "&&".

This causes Kotlin to assume the expression:

it.address.country == "United Kingdom"

... is the expression that needs to be returned. This causes the code to spit out all people currently in the United Kingdom.

It took me a little while to notice the problem. My IDE didn't help in the slightest.

References

[1] Problems with Kotlin
https://randomthoughtsonjavaprogramming.blogspot.com/2024/11/problems-with-kotlin.html

Tuesday, 26 November 2024

Problems with Kotlin

So, I was working and it didn't work.

And I really could not understand why.

Here's the code:

    @Test
    fun test() {
        val addressInNetherlands =
            Address(housenumber = 11L, street = "Kerkstraat", city = "Amsterdam", state = null, country = "Netherlands")
        val addressInEngland = Address(12, "Morsestreet", "London", null, "United Kingdom")
        val anotherAddressInEngland = Address(28, "Trinity Ln", "Cambridge", null, "United Kingdom")
        val addressInAmerica = Address(23, "32nd Street", "Columbus", "Ohio", "United States of America")

        val mrBear = Person("Mr.", "Bear", 50, addressInNetherlands)
        val mrBell = Person("Bell", "Graham", 55, addressInAmerica);
        val mrBoole = Person("George", "Boole", 82, addressInEngland);
        val lordKelvin = Person("William","Kelvin",84, anotherAddressInEngland);

        val addressBook = listOf(mrBear, mrBell, mrBoole, lordKelvin)

        var findMrBooleInEngland = addressBook.filter {
            it.firstName == "George" &&
                    it.lastName == "Boole"
                    it.address.country == "United Kingdom"
        }

        assertThat(findMrBooleInEngland).hasSize(1)
    }

Why does the assert fail? (it's programmer error, but almost invisible)

Solution in the next blog post.

Friday, 12 July 2024

Kotlin: The Spead Operator

Recently ran into a brick wall trying to pass a varargs parameter to another function that also has a varargs parameter.

A colleague mentioned the "spread" operator to me and it took me a little while to find information about it.

An example

package org.mrbear.kotlin

enum class ErrorCode(val description: String) {
    OBJECT_NOT_FOUND("Object %s not found."), NO_DEFAULT_PROVIDED("No default provided for parameter %s."), MALFORMED_URL(
        "Malformed url (%s)"
    )
}

abstract class MyException : Exception {
    constructor(errorCode: ErrorCode, cause: Throwable, vararg params: Any) : super(
        String.format(
            errorCode.description,
            *params
        ), cause
    )

    constructor(errorCode: ErrorCode, vararg params: Any) : super(String.format(errorCode.description, *params))
}

class ObjectNotFoundException(vararg params: Any) : MyException(ErrorCode.OBJECT_NOT_FOUND, *params)

Now to throw it in a test.

class ExceptionTest {

    @Test(expectedExceptions = [ObjectNotFoundException::class], expectedExceptionsMessageRegExp = "Object User mrbear not found.")
    fun testException() {
        throw ObjectNotFoundException("User mrbear")
    }
}

References

Kotlin - Variable number of arguments (varargs)
https://kotlinlang.org/docs/functions.html#variable-number-of-arguments-varargs
Kotlin - Java varargs
https://kotlinlang.org/docs/java-interop.html#java-varargs
Baeldung - Convert Kotlin Array to Varargs
https://www.baeldung.com/kotlin/array-to-varargs
Baeldung - Varargs in Java
https://www.baeldung.com/java-varargs

Monday, 3 June 2024

Kotlin Scope Functions

Scope function examples below:

  • let
  • with
  • run
  • apply
  • also
  • takeIf and takeUnless
  • Using them all at the same time!!!

I really hope I'm not the only one that gets confused about the different Scope functions1 in Kotlin and what they mean and when to use what.

The reference in [1] is excellent, but if I have to look up documentation on what certain methods do, the methods are not very well named.

So, in short, here's some examples, actually gleaned from the documentation and given my own spin on it with things that actually make sense.

Let

    /**
     * Useful if you do not wish to assign the result to an intermediate variable.
     * Useful with ? in case the result is NULL.
     */
    fun getDescription(address: Address?): String? =
        address?.let { address.getDescription() }

With

    /**
     * "with this object, do the following."
     * We're not interested in the result.
     */
    @Test
    fun withTest() {
        with(addressInEngland) {
            assertThat(street).isEqualTo("Morsestreet")
            assertThat(city).isEqualTo("London")
        }
    }

    /**
     * "with a helper object, do the following."
     */
    @Test
    fun withHelperTest() {
        val description = with(addressHelper) {
            computeAddress(addressInEngland)
        }
        assertThat(description).isEqualTo("12 Morsestreet London")
    }

Run

    /**
     * "run the code block with the object and compute the result."
     * Nice if you need to use it in an expression.
     */
    @Test
    fun runAsExtentionFunctionTest() {
        val didItWork: Boolean = database.run {
            val address = retrieveAddressFromDatabase()
            addressInAmerica.pobox = "43000"
            updateInDatabase(addressInAmerica)
        }
    }

    /**
     * "run the code block and compute the result."
     * Does not have a "this" or "it". Nice if you need to use it in an expression.
     */
    @Test
    fun runAsNonExtentionFunctionTest() {
        val didItWork = run {
            val address = database.retrieveAddressFromDatabase()
            with(shippingService) {
                sendItemToAddress(address)
            }
            log("Item sent")
            success
        }
    }

Apply

    /**
     * "apply the following assignments to the object."
     * The most common use case is object configuration, as below.
     */
    @Test
    fun applyTest() {
        val sameObject = Address().apply {
            housenumber = 12L
            street = "Morsestreet"
            city = "London"
        }
    }

Also

/**
     * "and also do the following with the object."
     * A common use case is to also assign the object to a property/variable.
     */
    private fun createHomeAddress() =
        Address().apply {
            housenumber = 12L
            street = "Morsestreet"
            city = "London"
        }
            .also { homeAddress = it }

TakeIf and TakeUnless

    /**
     * "return/use the value if this condition is true"
     * The opposite is takeUnless.
     */
    @Test
    fun takeIfTest() {
        assertThat(addressInEngland.takeIf { it.state != null }).isNull()
        assertThat(addressInAmerica.takeIf { it.state != null }).isEqualTo(addressInAmerica)
    }

And now for the big one!!!

    /**
     * Let's try all of them at the same time!
     */
    @Test
    fun allScopesTest() {
        val mailingSentForNewAddress = Address()
            .apply {
                housenumber = 12L
                street = "N. High Street"
                city = "Columbus"
                state = "Ohio"
                country = "United States of America"
            }
            .also {
                homeAddress = it
                with(database) {
                    updateInDatabase(it)
                }
            }
            .takeUnless { mailingAlreadySent(it) }
            ?.run {
                sendMailing()
                log("Mailing sent to ${getDescription()}.")
                success
            } ?: false

        val mailingSentForAddress =
            with(addressInEngland) {
                takeUnless { mailingAlreadySent(this) }
                    ?.run {
                        sendMailing()
                        log("Mailing sent to ${getDescription()}.")
                        success
                    } ?: false
            }
    }

Here I have tried to make use of the Scope functions in such a way that the different operations make sense.

P.S. I take offence on using "it" as the automatic name for the argument of the lambda. It sounds too much like the old Java "int i" in for loops. In other words, "it" has no meaning and the meaning depends entirely on context.

There's too much "it" and too much "this" and the context switching when using several Scope functions makes my head hurt.

References

[1] Kotlinlang.org - Scope Functions
https://kotlinlang.org/docs/scope-functions.html#functions

Friday, 14 April 2023

KotlinConf 2023

So I was able to attend my first KotlinConf1.

My experience with Kotlin is fairly new. I enjoy programming in both Java and Kotlin. I decide on a case by case basis what I pick.

Our current code base is a mixed bag of the two.

Sessions

I attended the following sessions on April 13 2023:

Opening Keynote2
I got some interesting news on the Kotlin version 2.0. It's coming.
Kotlin & Functional Programming: pick the best, skip the rest (Urs Peter)
Finally a nice talk about functional programming, a clear explanation of the illusive Monad, and what the advantages are of functional programming and which way we're going. Also took a look at Arrow3 for more idioms with functions.
Dissecting Kotlin: Unsealing the Sealed, the SAM, and Other Syntax (Huyen Tue Dao)
What is idiomatic Kotlin? It gave a great overview of the different features there are already in Kotlin, and how they should be used, and what little things we need to pay attention to when we do use them.
Replacing SQL with Kotlin's 'dataframe' on the Las Vegas Strip (Andrew Goldberg)
A nice talk which explains well what a dataframe is. And that with dataframes you can basically do all the operations that I am used to performing on (relational) databases with SQL, but a lot faster, as you're doing things locally? Coupling different data sources together.
Confetti: building a Kotlin Multiplatform conference app in 40min (John O'Reilly, Martin Bonnin)
A good example of using GraphQL and Compose to multiplatform create different mobile apps. Interestingly, they decided not to use Compose for the IPhone, as using Compose apparently causes different UI behaviour (Android behaviour) on the IPhone. Also extremely interesting use of livetemplates.
The Changing Grain of Kotlin (Nat Pryce, Duncan McGregor)
An interesting talk by some folks who wrote a book ("Java to Kotlin: A Refactoring Guidebook"). The talk was about how Kotlin has evolved and how this impacts old code, how it shapes new code, and how it all interacts.

Sessions I would like to have seen if I had the time:

Writing backend APIs in a functional programming style (James Lamine)
Transforming Farmer's Lives Using Android in Kenya (Harun Wangereka)

I attended the following sessions on April 14 2023:

Six Impossible Things (Kevlin Henney)
Massively entertaining talk about software design in general, and some of its history.
Coroutines and Loom behind the scenes (Roman Elizarov)
Very informative talk, basically centering on what the reason was for creating Loom and what the reason was for creating Coroutines and why they can co-exist.
KotlinX Libraries (Anton Arhipov, Svetlana Isakova)
Very informative talk, basically the extended libraries you can use to make your application independent of platform. Serialization, Coroutines, Immutable collections, and more.
How we’re improving performance of IntelliJ IDEA Kotlin plugin (Vladimir Dolzhenko)
Very interesting, contains some tidbit on why some of the things in the plugin are so difficult, as well as how much Kotlin leans on the Java AST and the compiler.
Kotlin Native for CLIs (Ryan Harter)
An explanation on what things to use and what problems you encounter and some benchmarks on creating native commandline tools using Kotlin. In this case it was "differ" a fairly simple tool for compare two images.
Gilded Rose Refactoring Kata (Dmitry Kandalov)
A refactoring kata primarily done with the standard refactoring possibilities for Kotlin in the IntelliJ IDEA. The Kata is from github5 created by Emily Bache6.

Sessions I would like to have seen if I had the time:

Handling billions of events per day with Kotlin Coroutines (Florentin Simion, Rares Vlasceanu)
Evolving your Kotlin API painlessly for clients

I think all sessions will be viewable sometime on the youtubes.

References

[1] KotlinConf 2023
https://kotlinconf.com/
[2] KotlinConf 2023 - Keynote
https://www.youtube.com/watch?v=c4f4SCEYA5Q
[3] Arrow brings idiomatic functional programming to Kotlin
https://arrow-kt.io/
[4] http4k - The Functional toolkit for Kotlin HTTP applications
https://www.http4k.org/
[5] github.com - Gilded Rose Refactoring Kata by Emily Bache
https://github.com/emilybache/GildedRose-Refactoring-Kata
[6] Emily Bache
https://github.com/emilybache

Thursday, 8 December 2022

Null handling in Kotlin

Just some notes, as I find myself forgetting the Null-safety features of Kotlin.

Actually, most of the text in this blog is basically already written in [1], so you might want to check there as well.

So, there are three possibiltiies:

// always has a value:
val name: String = "Mrbear"

// sometimes has a value:
val sometimesName: String? = null

// function in java, so no clue what it might be:
val date = LocalDate.now()
// the return value shows up in IntelliJ hints as LocalDate!

You can use if statements, of course, to check for nulls.

Sometimes this doesn't work, because it might be mutable, see [2].

Safe calls can be used, like so for example when person might be null:

val person: Person? = getPerson()
val name: String? = person?.name

Using let:

person?.name?.let{ println(it) }

Default values:

person?.name?:"Mrbear"

Throwing an exception if it's not there:

person?.name?:return null
person?.name?:throw NullPointerException("name is not there")

And then there's !!, for those who know what they're doing:

val now: LocalDate = LocalDate.now()!!

Safe casts if the cast is unsuccesfull:

val aInt: Int? = a as? Int

References

[1] Kotlin - Null safety
https://kotlinlang.org/docs/null-safety.html
[2] Smart cast to 'Type' is impossible, because 'x' is a mutable property that could have been changed by this time
http://randomthoughtsonjavaprogramming.blogspot.com/2022/09/smart-cast-to-type-is-impossible.html

Wednesday, 7 September 2022

Smart cast to 'Type' is impossible, because 'x' is a mutable property that could have been changed by this time

So I run into this problem quite often lately, most of the time it happens when I have defined a Hibernate Entity in Kotlin, and I wish to use it in my code.

It happens when there's a property that could conceivably be accessed in another thread, cause the two statements, the if-statement and the execution statement to look at different states, and cause a ClassCastException.

The following code demonstrates the message Kotlin provides when writing such a program:

Possible solutions

References

Youtube - Let, Also, Apply, Run, With - Kotlin Scope Functions
https://www.youtube.com/watch?v=Vy-dS2SVoHk

Monday, 9 May 2022

Hibernate Entities in Kotlin

Did a little research what kind of Kotlin classes I should use when creating Entities for the Hibernate framework.

Data classes

Just a short blurp on the requirements that data classes need from [1]:

  • the primary constructor needs to have at least one parameter
  • all primary constructor parameters need to be marked as either val or var
  • data classes cannot be abstract, open, sealed or inner

Hibernate Entities

Just a short blurp on the JPA requirements of entities from [2]

  • The entity class must have a public or protected no-argument constructor.
  • The entity class must be a top-level class.
  • The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
  • The persistent state of an entity is represented by instance variables, which may correspond to JavaBean-style properties. An instance variable must be directly accessed only from within the methods of the entity by the entity instance itself. The state of the entity is available to clients only through the entity’s accessor methods (getter/setter methods) or other business methods.

Conclusion

  • we need to define constructor parameters with var - as they should be mutable
  • we need to specify defaults for every constructor parameter, in order to generate the no-argument constructor
  • Hibernate entities should be "open" in Kotlin (so not final) in order for Hibernate to generate proxies. (this is fixed with the allopen addon in Maven)

So data classes are not a good fit, but a "normal" Kotlin class with just a constructor with annotated vars parameters with default values will work just fine.

References

[1] Kotlin - Data Classes
https://kotlinlang.org/docs/data-classes.html
[2] Hiberante ORM 5.5.9. Final User Guide
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#entity
Medium.com - Defining JPA/Hibernate Entities in Kotlin
https://medium.com/swlh/defining-jpa-hibernate-entities-in-kotlin-1ff8ee470805

Thursday, 28 October 2021

Kotlin, AssertJ and Overloads

So, I ran into a novell problem recently.

I've got the following Java code, which is a basic POJO following the Java Bean conventions:

  private Integer orderNumber;

  private Integer amount;

  public Integer getOrderNumber() 
  {
    return orderNumber;
  }

  public void setOrderNumber(Integer orderNumber) 
  {
    this.orderNumber = orderNumber;
  }

  public Integer getAmount() 
  {
    return amount;
  }

  public void setAmount(Integer amount) 
  {
    this.amount = amount;
  }

Now, I've got a Kotlin1 class that I use for testing, and I am using AssertJ2 as the library for comparing values.

At first try it looked very easy:

assertThat(get.orderNumber).isNull()
assertThat(get.amount).isNull()

This caused a serious java.lang.NullPointerException: get.orderNumber must not be null.

This is a typical Kotlin message, as Kotlin has Null safety built in. Kotlin is telling me that orderNumber may not be null. In the Java code it all seems fine, it's an Integer and nulls are allowed.

So what went wrong here?

Well, if I check out which assertThat is being used, I end up at:

  public static AbstractIntegerAssert<?> assertThat(int actual) {
    return new IntegerAssert(actual);
  }

And so we see now that it'll automatically be downgraded to a java int. Which Kotlin intercepts as being bad-form when using nulls.

So how to fix this?

I came up with the following little ugly hack:

assertThat(get.orderNumber as Any?).isNull()
assertThat(get.amount as Any?).isNull()

Now, all of a sudden, the method called is:

  public static <T> ObjectAssert<T> assertThat(T actual) {
    return new ObjectAssert(actual);
  }

Which is what I want.

Unfortunately this is neither obvious nor clear.

It's the price we pay for many many overloaded methods. Sometimes the compiler will just pick the wrong one.

However, to be fair, in most cases the Compiler picks the right one. This is just one of those cases, where we have to be specific.

There's some references to tickets on Kotlin in the References.

Addendum

The proper way to fix this problem, is of course, to add an @Nullable to the method in de Java class (if you can). This causes Kotlin to automatically assume it can be "null", and it therefore does not need casting.

P.S. I'm trying out a new code formatter3. It's nice in so far that it does not require additional installs, but it does add spans and styling directly. Pick your poison, I guess.

References

[1] Kotlin Language
https://kotlinlang.org/
[2] AssertJ
https://assertj.github.io/doc/
[3] Source code beautifier / syntax highlighter – convert code snippets to HTML « hilite.me
http://hilite.me/
YouTrack IntelliJ - Argument of Java platform boxed type resolves to primitive parameter method signature from Kotlin
https://youtrack.jetbrains.com/issue/KT-21285
GitHub AssertJ - isNull assertion broken in Kotlin when calling a Java class #1115
https://github.com/assertj/assertj-core/issues/1115

Friday, 23 July 2021

Kotlin : the "by" keyword in Interface/Class Delegation

I'm writing it down here, because I looked at it and didn't understand what was going on.

The "by" keyword in Kotlin is used for two things:

  1. Interface/Class delegation1
  2. Delegated properties2

Delegation is a good alternative to inheritance (thought this last statement really requires explanation, or a blogpost on it's own,... or, dare I say, a study on when to use inheritance and when to use delegation and when to use the good old composition).

With the "by" keyword it is possible to use delegation, without adding to the amount of boilerplate that this entails and without having to use inheritance.

Let us give an example using Stubs in testing.

Stubs

So, it seems it's possible to create a simple stub for a test, by using an interface and an implementation and overriding a method (for stubbing). Naturally, the method is not "overridden", but using delegation it is simply implemented in the test, and all other methods are redirected to the stub (which is the delegation class).

So, the syntax1 looks like this:

val/var <propertyname>: <Type> by <expression>

So, for example if you wish to use a delegation (instead of inheritance) in your stub for an OrderService interface.

You create a OrderServiceStub, which makes an empty implementation of all the methods in de OrderService.

And then you can create an anonymous class, indicating which method you wish to change to benefit the test.

It looks like this:

Notice that the anonymous inner class does not inherit from OrderServiceStub (in Kotlin classes are final by default, and we'd like to keep it that way).

The way this can be done without boilerplace in Kotlin is as follows:

So in the second test we're creating an anonymous class, which implements the interface automatically by delegating to the Stub. The only thing we need to change is the method we're interested in.

The next blogpost, we will be diving deeper into Delegated Properties, which looks a little more complicated but is based on the same ideas.

References

[1] Kotlin Language Reference - Delegation
https://kotlinlang.org/docs/delegation.html
[2] Kotlin Language Reference - Delegated properties
https://kotlinlang.org/docs/delegated-properties.html
[3] StackOverflow - What does 'by' keyword do in Kotlin?
https://stackoverflow.com/questions/38250022/what-does-by-keyword-do-in-kotlin

Thursday, 15 April 2021

Learning Kotlin

Well, trying to get to grips with Kotlin, and actually write something with it.

And I have a two day Kotlin course to attend.

I also managed to pick up Programming Kotlin by Venkat Subramanian.

It also helps that I have been pair programming with a Colleague who is already well versed in the language.

References

Blog - My First Kotlin Reference
https://randomthoughtsonjavaprogramming.blogspot.com/2020/06/kotlin.html
Programming Kotlin
enkat Subramanian

Friday, 27 September 2019

Devvalley Java Meetup

Two sessions were being given at the java dev meeting on the 26th of September 2019, at OpenWeb1 2 in Nieuwegein.

I just thought I'd write some of the things down that were being explained.

Reactive Streams

The first session, provided by Tim van Eijndhoven, was very interesting.

One of the limitations of the Stream API of Java, is that there is no implementation for "back pressure", i.e. the consumer of the stream cannot indicate to the producer of the stream the chunk size of the work it can handle.

Several implementations of reactive streams are already available.

  • RxJava (I noticed it looks a lot like RxJs, and no wonder. It is both based on Reactive Extentions3.)
  • Project Reactor4
  • Akka Streams5

RxJava

It still targets java 6, which makes it very suitable for android development, where it is very popular.

It's used by the Vert.x framework.

Project Reactor

A newcomer available from Pivotal. It's built on Java 8, on version 3 and is used by spring.

Has a feature to pass context.

Akka Streams

Akka Streams is from Lightbend, and is part of Akka. A framework built around Scala.

It seems to be quite different compares to the other two implementations.

There is an Alpakka Library, containing integrations with other systems, for example ElasticSearch, MongoDb, AWS APIs, etc.

Reactive Streams in Java6

Apparently there is already an active JEP (JEP 266) to get Reactive Streams into Java 9.

The different interfaces are called Flow.Publisher, Flow.Subscriber, Flow.Subscription and Flow.processor.

The existing implementations mentioned above all already have functionality to proxy their classes into the Java 9 interfaces.

Some notes

The Publisher is responsible for making decisions regarding what data to send to the Subscribers. For instance to skip data or to send all old data as soon as the subscriber subscribes.

And of course because of the "back pressure" thing, a publisher will have to keep track of how many items has been sent to the subscribers, and how many the subscriber can still receive before the publisher needs to wait for the next request.

The difference seems to be between cold streams and hot streams.

Where cold streams, a new subscriber will receive the same stream, starting from the beginning.

Where hot streams, data that has passed, will not be sent to new subscribers. Ideal for quickly changing values, where the recent value is the most valuable.

Testing is hard, because it's asynchronous. All the frameworks provide ways of adding unit tests.

Frameworks provide performance via:

  • macro fusion: replacing subsequent operators with a single operator
  • micro fusion: share resources or internal structure between operators.

The reactive stream interfaces are easy, but hard to get right frameworkwise.

The learning curve is pretty steep, though.

There are two points, usually, in the stream where you can decide to fiddle with thread-usage.

Supercharged Microservices

The second speaker was Dave Franken.

The second session was regarding the use of Kotlin7, and GraalVM9 and Quarkus8 to supercharge your microservices, making them both small (memory wise), with very fast bootup times (seriously very fast!), and can be developed quickly in Kotlin.

That is basically all I have to say about that.

References

[1] Devvalley 2019 - Open source meetup of the future
https://devvalley.openweb.nl/
[2] Devvalley Java Meetup
https://www.meetup.com/nl-NL/Devvalley/events/261802586/
[3] Reactive
http://reactivex.io/
[4] Project Reactor
https://projectreactor.io/
[5] Akka Streams
https://doc.akka.io/docs/akka/current/stream/index.html
[6] JEP 266: More Concurrency Updates
https://openjdk.java.net/jeps/266
[7] Kotlin Programming Language
https://kotlinlang.org/
[8] Quarkus - Supersonic Subatomic Java - A Kubernetes Native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards
https://quarkus.io/
[9] GraalVM Run Programs Faster Anywhere
https://www.graalvm.org/