Saturday 27 July 2024

jakarta.json.bind.JsonbException: Cannot create instance of a record: class SomeClass, Multiple constructors found.

So I've been trying to use Java Records as data holders for JSONB serialisation and deserialisation. And it works well, until I encountered the following:

jakarta.json.bind.JsonbException: Cannot create instance of a record: class SomeClass, Multiple constructors found.

It turns out, I can put in an annotation @JsonbCreator on it, as explained in reference [1].

It just takes a bit of work, as I cannot put the annotation on top of a record class, it needs to be put on a constructor. The way this works, is to create a compact constructor in the record.

The compact constructor is usually used to put in some sort of validation in the record class upon instantiation, but here we need it for the annotation @JsonbCreate.

Brian Goetz in the comments of reference [2] indicates that this is the proper way to do it.

Unfortunately, it causes one of those "empty constructors" messages of SonarLint.

Warning:(31, 10) Remove this redundant constructor which is the same as a default one.

I assume SonarLint will fix this eventually.

For completeness, my code:

public record AdminItem(Integer id,
                        String belongsto,
                        Long room,
                        String shopkeeper,
                        String owner,
                        LocalDateTime creation)
{

  @JsonbCreator
  public AdminItem
  {
    // empty constructor, because I need to put the annotation @JsonbCreator somewhere.
  }

  public AdminItem(Item item)
  {
    this(item.getId(), 
        item.getBelongsTo() == null ? null : item.getBelongsTo().getName(),
        item.getRoom() == null ? null : item.getRoom().getId(),
        null,
        item.getOwner() == null ? null : item.getOwner().getName(),
        item.getCreation());
  }

}

References

[1] Carlos Chacin - 💾 Java 14 Records 🐞 with JakartaEE JSON-B
https://carloschac.in/2020/04/20/java-records-jsonb/
[2] StackOverflow - Constructor annotation on java records
https://stackoverflow.com/questions/67168624/constructor-annotation-on-java-records

Thursday 18 July 2024

Angular and Updates

Recently was interested if and when Angular upgrades to a new release, as I found myself skipping release 17, and the update process can be a tiny bit troublesome if you skip a major version.

Angular has Semantic Versioning, and releases a new major version every 6 months. Angular 19 will possibly be out and about end of November 2024.

Luckily, from the references below, there's some things that I can hold on to:

  • a major version may require a bit of work by the developer.
  • a minor version can be installed without problems immediately. No developer assistance is expected during update. However, you can optionally decide to use new features in your code or change old features to use new stuff.
  • a fix/patch version can be installed without problems immediately. No developer assistance is expected during update.

And GitHub tends to complain (a lot!) if my Angular projects are a tiny bit old, and there're Security concerns with the javascript dependencies Angular uses.

With that in mind, the following quote on the website seems very good to know:

"We only make npm dependency updates that require changes to your applications in a major release. In minor releases, we update peer dependencies by expanding the supported versions, but we do not require projects to update these dependencies until a future major version. This means that during minor Angular releases, npm dependency updates within Angular applications and libraries are optional."

References

Angular - Roadmap
https://angular.dev/roadmap
Angular - Releases
https://angular.dev/reference/releases
GitHub - Angular Public API Surface
https://github.com/angular/angular/blob/main/contributing-docs/public-api-surface.md
Angular Blog
https://blog.angular.dev/
Angular Dev
https://angular.dev/

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

Sunday 7 July 2024

Upgrading to Angular 18

Upgrading Javascript things is always a chore.

That's why these blogposts keep appearing.

% ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 16.2.5
Node: 18.16.1
Package Manager: npm 9.7.2
OS: darwin x64

Angular: 16.2.8
... animations, common, compiler, compiler-cli, core, forms
... localize, platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1602.5
@angular-devkit/build-angular   16.2.5
@angular-devkit/core            16.2.5
@angular-devkit/schematics      16.2.5
@angular/cli                    16.2.5
@schematics/angular             16.2.5
rxjs                            7.5.7
typescript                      4.9.5
zone.js                         0.13.1

So I've used the tool in [2] to check my dependency requirements but there's also [1] if you're interested.

Upgrading node.js

cd ~
rm nodejs
tar zxvf ~/Downloads/node-v20.15.0-darwin-arm64.tar.gz
ln -s node-v20.15.0-darwin-arm64 nodejs

Upgrading typescript

Upgrading typescript using "npm install -g typescript@latest".

Upgrading zone.js

I'm hoping Angular does this for me.

Upgrading Angular

For my "personal" project.

npm install -g @angular/cli@18

ng update @angular/core@17 @angular/cli@17

ng update @angular/core@18 @angular/cli@18 @ng-bootstrap/ng-bootstrap@17 ngx-cookie-service@18

For my "admin" project, the thing below only worked after upgrading cdk and material to 17.

ng update @angular/core@18 @angular/cli@18 @ng-bootstrap/ng-bootstrap@17 ngx-cookie-service@18 @angular/cdk@18 @angular/material@18

Upgrading dependencies

ng update bootstrap bootswatch material-icons

My dependencies for "personal" project

@kolkov/angular-editor
the editor I use in my webapps
@ng-bootstrap/ng-bootstrap
integration between angular and bootstrap
@popperjs/core
this is used for tooltips by ng-bootstrap
bootstrap
bootstrap, is awesome
bootswatch
free themes for bootstrap, I like/use "cyborg" as a darkmode theme.
material-icons
latest icon fonts and CSS for self-hosting material design icons.
ngx-cookie-service
Angular service to read, set and delete browser cookies.
ng update @angular/cdk@16 @angular/material@16
ng update @angular/cdk@17 @angular/material@17

My dependencies for "admin" project

@angular/material
for creating of a virtual scroller
@angular/cdk
for creation of a virtual scroller
@ng-bootstrap/ng-bootstrap
integration between angular and bootstrap
@popperjs/core
this is used for tooltips by ng-bootstrap
bootstrap
bootstrap, is awesome
bootswatch
free themes for bootstrap, I like/use "cyborg" as a darkmode theme.
material-icons
latest icon fonts and CSS for self-hosting material design icons.
ngx-cookie-service
Angular service to read, set and delete browser cookies.

Things I noticed

Migrate application projects to the new build system.
You can read more about this, including known issues and limitations, here: https://angular.dev/tools/cli/build-system-migration The output location of the browser build has been updated from "../webapp" to "../webapp/browser". You might need to adjust your deployment pipeline or, as an alternative, set outputPath.browser to "" in order to maintain the previous functionality.
Replace deprecated HTTP related modules with provider functions.
HttpClientModule replaced with provideHttpClient, withInterceptorsFromDi

Error messages when upgrading

Package "@ng-bootstrap/ng-bootstrap" has an incompatible peer dependency to "@angular/common" (requires "^16.0.0" (extended), would install "18.0.6").
[WARNING] Polyfill for "@angular/localize/init" was added automatically. [plugin angular-polyfills]

  In the future, this functionality will be removed. Please add this polyfill in the "polyfills" section of your "angular.json" instead.

I found the answer to this one in [3] on StackOverflow.

[WARNING] Unable to locate stylesheet: /assets/css/bootstrap.min.css
[WARNING] Unable to locate stylesheet: /assets/css/karchan.css

Replaced this with a ThemeService (which is nice) which I found at [4].

And removed the hardcoded stylesheets in index.html. These are now added by the ThemeService.

Final result

% ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 18.0.7
Node: 20.15.0
Package Manager: npm 10.8.1
OS: darwin arm64

Angular: 18.0.6
... animations, cdk, common, compiler, compiler-cli, core, forms
... localize, material, platform-browser
... platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1800.7
@angular-devkit/build-angular   18.0.7
@angular-devkit/core            18.0.7
@angular-devkit/schematics      18.0.7
@angular/cli                    18.0.7
@schematics/angular             18.0.7
rxjs                            7.5.7
typescript                      5.4.5
zone.js                         0.14.7

Small note

I am using the assets to store a normal bootstrap (bootstrap.min.css) and a darkmode bootstrap (bootstrap.darkmode.min.css).

These come from respectively node_modules/bootstrap/dist/css/bootstrap.min.css and node_modules/bootswatch/dist/cyborg/bootstrap.min.css.

References

[1] TechiDiaries - Upgrade to Angular 18
https://www.techiediaries.com/upgrade-angular-to-v18/
[2] Official Angular Updater Tool on the Web
https://update.angular.io/
[3] StackOverflow - Angular 18 Polyfills warning
https://stackoverflow.com/questions/78636168/angular-18-polyfills-warning
[4] Medium - Theme Switcher in Angular: From Dark to Light and Back Again
https://medium.com/@davdifr/theme-switcher-in-angular-from-dark-to-light-and-back-again-f42fc3f9fab0