An open API service indexing awesome lists of open source software.

https://github.com/bmarwell/openliberty-content-negotiation-example

Try it out on the command line: `curl https://api.diceroll.bmarwell.de/`
https://github.com/bmarwell/openliberty-content-negotiation-example

dice java javaee open-liberty rest-api

Last synced: 5 months ago
JSON representation

Try it out on the command line: `curl https://api.diceroll.bmarwell.de/`

Awesome Lists containing this project

README

          

= OpenLiberty Content Negotiation Example
:icons: font
:toc: macro
:toclevels: 4

https://github.com/bmarwell/openliberty-content-negotiation-example/actions/workflows/maven.yaml[image:https://github.com/bmarwell/openliberty-content-negotiation-example/actions/workflows/maven.yaml/badge.svg[Maven
CI]]
https://opensource.org/licenses/Apache-2.0[image:https://img.shields.io/badge/License-Apache_2.0-blue.svg[License]]
https://renovatebot.com[image:https://img.shields.io/badge/renovate-enabled-brightgreen.svg[Renovate]]
link:https://openliberty.io/[image:https://img.shields.io/badge/AppServer-Open%20Liberty-blue[AppServer]]

This is a port of link:https://github.com/diceroll-dev/dice-parser[Brian‘s Dice Parser] using link:https://github.com/oktadev/quarkus-content-negotiation-example[Quarkus with Content negotiation example] to link:https://openliberty.io/[OpenLiberty], using a lot more CDI (just for the fun).

This example runs only at Java 15, because IBM still has not published Java 16 or 17 images with OpenLiberty (as of 2021-11-04).

toc::[]

== Differences from Brian‘s API

Just for the fun of it, and because JSON is derived from JavaScript, I did set the config option `PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES`.

The output will have `under_scores` in field names instead of `lowerCamelCase` (as derived from Java getter methods).

As already mentioned, most classes were converted to interfaces and CDI beans.

== Using the API

The calls are similar to Brian‘s API.

=== Help API

==== Curl user agent

[source]
----
$ curl --url "https://api.diceroll.bmarwell.de/"
Welcome to the Dice Parser!!

Roll dice by making a request:
curl https://api.diceroll.bmarwell.de/roll?dice=2d6 -H "Accept: text/plain"

Or get the result in JSON (the default):
curl https://api.diceroll.bmarwell.de/roll?dice=2d6 -H "Accept: application/json"
----

==== HTTPie user agent

----
$ curl -H "User-Agent: HTTPie/1.0.0" --url "https://api.diceroll.bmarwell.de/"
Welcome to the Dice Parser!!

Roll dice by making a request:
http https://api.diceroll.bmarwell.de/roll dice==2d6 "Accept: text/plain"

Or get the result in JSON:
http https://api.diceroll.bmarwell.de/roll dice==2d6 "Accept: application/json"
----

==== Generic User Agent (or none/unknown)

----
$ curl -H "User-Agent: " --url "https://api.diceroll.bmarwell.de/"
Welcome to the Dice Parser!!

Roll dice by making a request:
GET https://api.diceroll.bmarwell.de/roll?dice=2d6
Accept: text/plain

Or get the result in JSON:
GET https://api.diceroll.bmarwell.de/roll?dice=2d6
Accept: application/json
----

==== German Language

----
$ curl -H "accept-language: de" --url "https://api.diceroll.bmarwell.de/"
Willkommen beim Würfelparser!!

Würfeln Sie, indem Sie eine Anfrage stellen:
curl https://api.diceroll.bmarwell.de/roll?dice=2d6 -H "Accept: text/plain"

Oder rufen Sie das Ergebnis in JSON ab:
curl https://api.diceroll.bmarwell.de/roll?dice=2d6 -H "Accept: application/json"
----

=== Dice roll API

See link:https://github.com/diceroll-dev/dice-parser#supported-notation[Brian’s Docs] for all available options.

==== Accept `text/plain` (or none specified):

[source]
----
$ curl --url "https://api.diceroll.bmarwell.de/roll?dice=2d6"
2d6 = 10
--d6 = 6
--d6 = 4
----

==== Accept `application/json`

----
$ curl -H "accept: application/json" --url "https://api.diceroll.bmarwell.de/roll?dice=2d6"

{
"expression": {
"number_of_dice": 2,
"number_of_faces": 6
},
"results": [
{
"expression": {
"number_of_dice": 1,
"number_of_faces": 6
},
"results": [
],
"value": 2
},
{
"expression": {
"number_of_dice": 1,
"number_of_faces": 6
},
"results": [
],
"value": 2
}
],
"value": 4
}
----

== How to build

=== Environment

Make sure your java version is recent enough.

[source,bash]
----
sdk env
----

=== Quick build with all checks

[source,bash]
----
./mvnw verify
----

=== Build docker image

[source,bash]
----
# needed for podman beforehand:
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock"
systemctl enable --user --now podman.socket
systemctl enable --user --now podman.service
# actual build
./mvnw package -Pdockerize
----

Image will be built as `openlibertycontentrenegotiation/olcr-app-ol-docker:latest`

=== Enable Open Liberty InstantOn

This feature is powered by Eclipse OpenJ9 and Linux CRIU.

Prerequisites:

* podman
* podman-docker
* set-up UNIX-host as can be seen above
* jq -- as we enabled JSON logging

[source,bash]
----
# remove old dangling image
docker rm olcr-checkpoint-container

# build the InstantOn-Image
podman run --name olcr-checkpoint-container --privileged --env WLP_CHECKPOINT=applications openlibertycontentrenegotiation/olcr-app-ol-docker:latest | grep -E '^{' | jq -s
# now you should have a checkpointed container (check the logs)

# to make it available, use:
podman commit olcr-checkpoint-container oclr-instanton

# this is now something you can start:
podman run \
--rm \
--cap-add=CHECKPOINT_RESTORE \
--cap-add=NET_ADMIN \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--security-opt systempaths=unconfined \
--security-opt apparmor=unconfined \
-p 9080:9080 \
oclr-instanton
----

== What does this example show?

=== OpenLiberty features

* Resful WebServices 3.0, CDI 3.0, JSON-B(inding) 2.0 on OpenLiberty
* Some OpenLiberty features, like
** TLS1.3 over http/2
** disabling CDI implicit bean archives
** Preferred server compression
** Modified cookie length
** skipping META-INF processing
** A bit of hardening (remove server header, disabled welcome page)
** JSON logging for the docker container.
** the easiness of using features

As well as

* Using the `liberty-maven-plugin` for integration testing
* Using link:https://github.com/eclipse/jkube/tree/master/kubernetes-maven-plugin[kubernetes-maven-plugin] for building Docker images
* Using a shared class cache with OpenJ9 for insane startup times!
* JVM options like:
** Insanely low memory (64M to 128M max)
** Less idle CPU by using https://www.eclipse.org/openj9/docs/xxidletuninggconidle/[`-XX:+IdleTuningGcOnIdle`].
** Reduce startup time by delaying class verification until needed (https://www.eclipse.org/openj9/docs/xxclassrelationshipverifier/[`-XX:+ClassRelationshipVerifier`]).
** Tune for virtualized environments (https://www.eclipse.org/openj9/docs/xtunevirtualized/[`-Xtune:virtualized`]).

=== Startup time

Some classes are pre-compiled using OpenJ9‘s AOT compiler.
The files are then saved to a shared class cache file.
This way, Java does not need to compile the files again on every startup.

[source]
----
$ docker run -p 9080:9080 de.bmarwell.examples.openlibertycontentrenegotiation/olcr-app-ol-docker:1.0.0-SNAPSHOT

[…]
[2021-11-04T20:00:31.258+0000] 00000034 id= com.ibm.ws.app.manager.AppMessageHelper A CWWKZ0001I: Application olcr-web-restv1-1.0.0-SNAPSHOT started in 0.526 seconds.
----