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

Thursday 21 October 2021

Netlify and Github pages

So, I created a small Angular app (a website basically), self contained (for now), that works nicely. I used it to help me in learning Croatian, so it's basically a word app. There's plenty of them online, but none that I liked.

I wanted to access the app from my phone, which means it needs to be hosted somewhere.

Nginx on Raspberry Pi

Initially I installed Nginx on my Raspberry Pi at home

Started it using the usual /lib/systemd/system/nginx.service.

Configurations as usual in /etc/nginx.

I uploaded the Angular files in /var/www/html and that worked fine.

The IP adress is http://192.168.2.4/, only accessible locally from my own network, of course.

But, of course I wanted it available for travelling as well (and didn't want to expose my Raspberry Pi to the Terrors of the Internet).

There's plenty of ways to make the Angular website available.

Github Pages

I could have hosted the Angular files in a repository on Github.pages1 and then accessed them from there. That would work.

But I didn't feel like doing that2.

It would mean making a repository with the name of the project or my account name and putting all the build Angular files there.

Netlify

I choose to go with Netlify. They have a free tier and play well with Github.

As soon as I commit new changes to my Angular project in github3, Netlify picks up those changes, builds the Angular project and deploys it to the website4.

I was very impressed!

It's a good example of Continuous Delivery5.

So, the steps were basically as follows:

  • sign up at Netlify with your github account
  • create a new site from Git
  • pick a repository
  • specify site and build settings and all that.

Some notes

Automatically a hostname is generated for you, something like belnazzar-troublesome3.netlify.app. If that is not to your liking you can change the hostname of the site (just the first part) or even get a authentic hostname alltogether. (But I didn't need that.)

I did have the outputpath originally set to dist/polygo in my Angular app, and I changed that to "dist". Otherwise everyone has to go to "polygo.netlify.app/polygo" all the time.

Then there's the fact that Angular wants to do its own routing, but it cannot do that if you do not end up at de index.html page. For instance if you go directly to https://polygo.netlify.app/wordgame instead of https://polygo.netlify.app/.

Luckily the folks at Netlify have taken this into account6.

I created an src/_redirects file for redirecting everything to /index.html, so Angular can take over the routing.

I changed angular.json by adding src/_redirects on the assets array.

And bingo, it worked!

What's next?

Well, it suffices for my needs right now, but as I have the REST resources just committed in the Github Repository, expanding on the data is a bit of a hassle. I need to commit data changes to the repo, and Netlify redeploys.

It would be nice to be able to use a database.

I found some information on it at [7] on using Netlify Functions in combination with FaunaDB, but that'll have to wait for another time.

References

[1] Github Pages
https://pages.github.com/
[2] Netlify.com - Github Pages vs Netlify
https://www.netlify.com/github-pages-vs-netlify/
[3] Polygo on Github
https://github.com/maartenl/polygo
[4] Polygo at Netilfy
https://polygo.netlify.app/wordgame
[5] Jetbrains - Continuous Integration vs. Delivery vs. Deployment
https://www.jetbrains.com/teamcity/ci-cd-guide/continuous-integration-vs-delivery-vs-deployment/
[6] Netlify Docs - Angular on Netlify
https://docs.netlify.com/configure-builds/common-configurations/angular/
[7] Building Serverless CRUD apps with Netlify Functions and FaunaDB
https://www.netlify.com/blog/2018/07/09/building-serverless-crud-apps-with-netlify-functions-faunadb/

Thursday 14 October 2021

My Printer's Gone!

I was missing my printer. Turns out I could just add it in the Printer Settings in Linux.

I don't know why it was suddenly missing, though.

Perhaps it happened during an upgrade of Fedora Core.

I know I installed all the required drivers some time ago.

Oh well. I thought it was something serious. It's nice to be disappointed.

References

MyBlog - Installing Printer Driver in Fedora for Epson ET-3750
https://randomthoughtsonjavaprogramming.blogspot.com/2021/03/installing-printer-driver-in-fedora-for.html

Thursday 7 October 2021

Running Payara Micro on Java 11 via GraalVM on Docker on Jelastic

Boy, that title was a mouth full.

Now if you want more information on Docker, you can check out reference [3]. Or if you're looking for Java 11 GraalVM Dockerimages suitable for Jelastic, you can check out [1] and [2].

This blog is more about the contents of the Dockerimage than Docker itself.

GraalVM

Well, I've been using Jelastic for a while now, and it suited my needs, until it didn't.

They provide GraalVM out of the box, but not the Java 11 version yet.

I was using a Payara Server image for Jelastic, and I had good results just installing GraalVM on the Image afterwards and run Payara using that, but I was looking for something a little more lean.

Sooo, in short, I used the GraalVM image used by Jelastic as a baseline in my Docker image (jelastic/javaengine:graalvm-21.0.0.2).

Then it was just install the JDK11 version of GraalVM and create my Image.

Less troublesome than I thought it would be.

Payara Micro

So Payara Micro is awesome. The way this differs from Microprofile, is that Microprofile contains only Microprofile and the Payara Micro basically seems to be a small Payara server run from the command line. It is based off the Payara Embedded Web release. See [4].

So there's basically two things:

  1. you run it from the command line using java and the payara-micro-5.2020.7.jar
  2. you provide a postboot file containing the settings

Example

Let's try an example.

The example basically runs a Payara Micro instance, with some wars deployed and a JDBC library for connecting to a database.

All configuration of the database connection is done using the afore mentioned postboot file.

Some notes on the postboot file.

  • I am not interested in Hazelcast, so I turned this off. The main result should be faster startup.
  • I added eclipselink.target-database to the jdbc string, otherwise the JDBC driver will identify itself as MariaDB driver, and it is unknown. You can immediately tell by the following error message in the log:

    Not able to detect platform for vendor name [MariaDB[10.4.20-MariaDB, 10]]. Defaulting to [org.eclipse.persistence.platform.database.DatabasePlatform]. The database dialect used may not match with the database you are using. Please explicitly provide a platform using property "eclipselink.target-database".

  • I also added a config property to it. Microprofile (which is included) has support for Configuration. And it's great!

Secure Socket Layer

There's a simple self signed SSL Certificate included in the Payara Micro, which works fine, unless, like me, you wish to use a genuine SSL Certificate.

The idea here is to expand on the command line (see above in run.sh) with SSL options, for example as follows:

  • -Djavax.net.ssl.trustStore="/home/jelastic/cacerts.jks"
  • -Djavax.net.ssl.keyStore="/home/jelastic/keystore.jks"
  • -Djavax.net.ssl.trustStorePassword="changeit"
  • -Djavax.net.ssl.keyStorePassword="changeit"

References

[1] Dockerhub - my jelastic graal with jdk 11 docker image
https://hub.docker.com/r/maartenl22/jelasticgraaljdk11
[2] Github - Docker file
https://github.com/maartenl/jelasticgraaljdk11
[3] MyBlog - Docker
https://randomthoughtsonjavaprogramming.blogspot.com/2021/06/docker.html
[4] Payara Micro Documentation
https://docs.payara.fish/community/docs/documentation/payara-micro/payara-micro.html
Releases - graalvm/graalvm-ce-builds
https://github.com/graalvm/graalvm-ce-builds/releases
How to install GraalVM on Linux with alternatives
https://gist.github.com/ricardozanini/fa65e485251913e1467837b1c5a8ed28
GraalVM - GraalVM Community Images
https://www.graalvm.org/docs/getting-started/container-images/
Github - graalvm-ce
https://github.com/orgs/graalvm/packages/container/package/graalvm-ce

Saturday 2 October 2021

JDK17: The next Long Term Support Java

Due as a production release on September 14, Java Development Kit (JDK) 17 will be a long-term-support (LTS) release, with extended support from Oracle expected for several years.

Now I just have to wait for all my libs and tools to be compatible.

References

Oracle Press Release: Oracle Releases Java 17
https://www.oracle.com/news/announcement/oracle-releases-java-17-2021-09-14/
Oracle Blogs - Java - The arrival of Java 17!
https://blogs.oracle.com/java/post/announcing-java17
TechGeekNext - JDK 17 Arrived - What's new features released in Java 17
https://www.techgeeknext.com/java/java17-features
InfoWorld - JDK 17: The new features in Java 17
https://www.infoworld.com/article/3606833/jdk-17-the-new-features-in-java-17.html