Thursday 27 October 2022

Entity-Relationship Diagrams

I tend to forget what the arrows mean in an entity-relationship diagram.

Example

In the diagram above, there's strong limitations on the values possible in the GuildMember table. Unfortunately, these cannot be expressed in Foreign Key Relationships.

For example:

  • a Person can hold only one rank in a Guild.
  • a Person can only be a GuildMember in a Guild once.

The way to fascilitate this, is to put a unique index on GuildMember regarding the columns GUILDNR and PERSONNR.

References

PlantUML - Entity Relationship Diagram
https://plantuml.com/ie-diagram
LucidChart - Wat is een Entity Relationship Diagram?
https://www.lucidchart.com/pages/nl/wat-is-een-entity-relationship-diagram

Thursday 20 October 2022

Renewing LetsEncrypt SSL Certificates automatically

I found a little script (that I changed a little) to accomodate me in automating SSL certificate renewals.

First of all, the script is executed using a crontab, every 73 days. Why every 73 days? Because that is 5 times a year. Any less, and we (just) go past the 90 days validation period1. (365/4 = 91.25)

The script that basically delegates everything to either other scripts or is dependent of other scripts:

For the script that automatically imports into keystore, see [2].

References

[1] FAQ - Let's Encrypt
https://letsencrypt.org/docs/faq/
[2] LetsEncrypt with Webroot
https://randomthoughtsonjavaprogramming.blogspot.com/2021/11/letsencrypt-with-webroot.html

Thursday 13 October 2022

Why don't record classes follow the Java Bean conventions?

Records are named tuples1.

Notice that the name of the field accessors does not start with get and, therefore, does not conform to the JavaBeans conventions.

We can declare getter methods if we really want to, and let them refer to the record method, but I'd opt not to if possible. We can do it, for a little while, until frameworks catch up to the new code convention, which will be pretty quick.

As Brian Goetz wrote in an online thread2:

“. . . the language has a responsibility to look forward as well as backward, and balance the needs of existing code with the needs of new code. Taking a bad library naming convention and burning it into the language forever would have been the worse choice.”

Builders

We can create builders for Records, if we like. See [3] for instance, but I'm not a fan of automatic code generation.

FreeMarker

The reason I started on this blog, is because there's a plethora of different frameworks/tools/what-have-you available that all center around the Java Beans conventions.

In most cases, records are not a good fit for these, as those frameworks and tools operate on the notion that these are mutable data classes.

But sometimes, there are definitely simple use cases where it would come in handy.

For example with the use of Freemarker4, a templating engine that converts your templates and Java POJOs to nice html pages (or other kinds of pages, there's no limit really).

And these follow the getX() convention.

So, one way would be to create the blasted getter methods in the Record class, but then you're adding boilerplate again, and I feel uncomfortable with that.

Perhaps an idea is to create my own DefaultObjectWrapper5.

So, Freemarker will need some changes to support record classes6. Something like automatically generating a hashmap of all the methods that have no arguments, yet return something... and preferable do not start with get?

References

[1] Data Classes and Sealed Types for Java - Brian Goetz February 2019
https://openjdk.java.net/projects/amber/design-notes/records-and-sealed-classes
[2] ForumPost - Feedback for records: Accessors name() vs. getName()
https://mail.openjdk.java.net/pipermail/amber-dev/2020-August/006414.html
[3] GitHub - RecordBuilder
https://github.com/Randgalt/record-builder
[4] FreeMarker
https://freemarker.apache.org/
[5] FreeMarker - Object wrappers
https://freemarker.apache.org/docs/pgui_datamodel_objectWrapper.html#pgui_datamodel_defaultObjectWrapper
[6] Apache JIRA - FREEMARKER-183
https://issues.apache.org/jira/browse/FREEMARKER-183
JLS - 8.10. Record Classes
https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-8.10
JavaMagazine - Records Come to Java
https://blogs.oracle.com/javamagazine/post/records-come-to-java
JavaMagazine - Java records: Serialization, marshaling, and bean state validation
https://blogs.oracle.com/javamagazine/post/diving-into-java-records-serialization-marshaling-and-bean-state-validation

Wednesday 5 October 2022

Paving the on-ramp

Brian Goetz wrote an interesting article1 about what Java could do to lessen the big bulk of context needed for first-timers to write a simple Hello-World program in java. The whole "public static void main(String[] args)" conundrum.

I especially like the following quote (out of context) in de article:

“We will never be able to satisfy programmers’ insatiable appetite for typing fewer keystrokes, and we shouldn’t try, because the goal of programming is to write programs that are easy to read and are clearly correct, not programs that were easy to type.”

So I went and tried to see what's the absolute minimum that still compiles in Java. Of course, the "real" main method is hidden in the Main class. And the class below is in the nameless package.

class MyProgram extends Main {
  void main() {
    println("Hello, world.");
  }
}

The hidden "Main" class looks like this, and can be safely ignored (for now) by new programmers:

/**
 * Hello world!
 */
public class Main {

  public void println(Object x) {
    System.out.println(x);
  }

  public static void main(String[] args) {
    new MyProgram().main();
  }
}

Added benefit, you can simply "run" this class, as its parent class has a "public static void main(String[] args)".

Also, the parent class has a "println" method, so we do not need to import System.out.println as well.

Admittedly, this is all a bit "hacky", where we just hide what we don't want beginning programmers to know in another class. But hey, hiding implementation details that are not important to the current "thing", is one of the core principles of Software Design, isn't it?

Updated 2023/04/17

An example in JDK 21

The reference [1] is implemented in JDK 21, using reference [2].

A simple program can now look like this:

void main() {
    System.out.println("Hello, World!");
}

Updated 2024/02/20

References

[1] Paving the on-ramp (Brian Goetz September 2022)
https://openjdk.org/projects/amber/design-notes/on-ramp
[2] JEP 445: Unnamed Classes and Instance Main Methods (Preview)
https://openjdk.org/jeps/445