Skip to main content

Why Jakarta EE is Better than the Competition

by Nicolas DUMINIL at September 30, 2022 01:40 PM

Jakarta EE is the most popular Java server-side framework, way ahead its alleged competitors such as Spring, Quarkus, Micronaut or Dropwizard. With the industry-wide adoption of microservices based architectures, its popularity is skyrocketing and, during these last years, it has become the preferred framework for professional software enterprise applications and services development in Java.

In this blog, I'll explain more about Jakarta EE from my perspective as a Senior Java software architect/developer and why Jakarta EE and its runtimes beat the competition, in my opinion!


by Nicolas DUMINIL at September 30, 2022 01:40 PM

Database portability – Pitfalls when supporting multiple RDBMS with Hibernate

by Thorben Janssen at September 29, 2022 01:39 PM

The post Database portability – Pitfalls when supporting multiple RDBMS with Hibernate appeared first on Thorben Janssen.

The JPA specification and Hibernate, as its most popular implementation, claim to provide database portability. That means you don’t need to change your persistence code…

The post Database portability – Pitfalls when supporting multiple RDBMS with Hibernate appeared first on Thorben Janssen.


by Thorben Janssen at September 29, 2022 01:39 PM

Liberty InstantOn startup for cloud native Java applications

September 29, 2022 12:00 AM

Do you want cloud-native Java applications that can start up in milliseconds, without compromising on throughput, memory, development-production parity, or Java language features? The Open Liberty 22.0.0.11-beta brings you InstantOn, an exciting new feature that provides incredibly fast startup times for MicroProfile and Jakarta EE applications.

In serverless environments, application startup times are important. InstantOn application instances can scale to zero when the application is not in use. Scaling to zero can help reduce the overall cloud costs for deployed applications by reducing the overall number of application instances when there are no ongoing requests. When activity picks up for the application, new instances can start up quickly, without introducing high latency for the user.

How Open Liberty enables InstantOn startup

To enable InstantOn, Open Liberty uses new features of the OpenJ9 JVM and a Linux technology called Checkpoint/Restore In Userspace CRIU to take a checkpoint of the application process as it starts. This checkpoint is a snapshot of the running application process that can be persisted and then quickly restored to bring the application process back into the state it was in when the checkpoint was taken. This process enables the Liberty instance, along with any configured applications, to be restored multiple times into distinct instances of your application.

To see just how fast InstantOn startup is, skip to the "How fast is it?" section. For more details on the advantages of this approach, see the Fast JVM startup with OpenJ9 CRIU Support blog post and this earlier Open Liberty blog post where we first discussed the potential of CRIU for faster startup of Java applications.

The Open Liberty InstantOn feature makes it easy for you to try it out by providing a new checkpoint action, which can be executed against your existing Open Liberty server configurations. With the checkpoint action, you specify a phase at which you want the Liberty startup process to stop and save a checkpoint. When Liberty is launched, it will detect the saved checkpoint process and resume the process from the state that it was saved in during the checkpoint action.

Set up the example application project

Before we get into the details of how the checkpoint action works, let’s set up a working example. For this example, we will have a look at the Getting started with Open Liberty guide. If you want to follow along, start by cloning the Git repository for this guide and use the projects that are provided inside:

git clone https://github.com/openliberty/guide-getting-started.git
cd guide-getting-started

We will work within the finish/ directory for this demonstration. To try out the application, run the following Maven goal to build the application and deploy it to Open Liberty:

cd finish
mvn liberty:run

After you see the following message, your application server is ready:

The defaultServer server is ready to run a smarter planet.

Check out the service at the http://localhost:9080/dev/system/properties URL.

After you finish checking out the application, stop the Open Liberty server by pressing CTRL+C in the command-line session where you ran the server.

To build the WAR for the application run the following :

mvn package

This command builds a target/guide-getting-started.war archive. We can now include this WAR in a container image that uses the InstantOn feature.

Containerizing the application

For an application to use Open Liberty InstantOn support, it must first be containerized using the Open Liberty beta InstantOn image. For general information about how to containerize applications with Open Liberty, see the Containerizing microservices guide or the Containerizing microservices with Podman guide. If you are unfamiliar with Podman, follow the Podman guide first because the Open Liberty InstantOn support currently requires the use of Podman. Support for Docker should come later, once Docker supports the capabilities that CRIU requires.

Containerize an application using the Open Liberty Beta InstantOn image

The Liberty InstantOn beta image contains the prerequisites for building an application container image with a checkpoint server process. Applications can use the Liberty InstantOn beta image as a base to build their own application container images and from that create their own application container image with a checkpoint process. This involves the following steps:

Prerequisites to checkpoint/restore a containerized application

Currently, the beta of Open Liberty InstantOn only supports running on x86-64/amd64 architectures. To build and run container images that use criu, the host Operating System needs a few prerequisites installed. All our testing was done on RHEL 8.6 and RHEL 9.0. Other Linux distributions and versions might be possible if they have the necessary prerequisites. The following conditions are required:

  • The kernel must support the Linux CAP_CHECKPOINT_RESTORE capability. This capability was introduced in kernel version 5.9, but was backported to RHEL kernel versions used in RHEL 8.6.

  • The latest available version of Podman for the Linux distribution must be installed.

  • Podman must be configured to use the crun or runc container runtime.

  • If you use the runc container runtime, then version 1.1.3 or higher is required so that you have the recent fix to runc. This fix enables the successful mount of /proc/sys/kernel/ns_last_pid in the container.

Create the Dockerfile for the application

For the Getting started with Open Liberty example, the first step is to create a Dockerfile that provides the instructions to create a containerized version of the application. Note that podman also supports using the Containerfile format for building container images.

For this example, we will use an official image from the IBM Container Registry (ICR), icr.io/appcafe/open-liberty:beta-instanton, as the parent image. This image is tagged with the word beta, meaning it includes all the Liberty beta features as well as all the Liberty features from the full image. The image is tagged with instanton, meaning it includes all the prerequisites for producing a checkpoint process image, such as the necessary criu binary files.

The Dockerfile for the getting-started application already exists at finish/Dockerfile. Edit the existing finish/Dockerfile and change the FROM instruction to use the icr.io/appcafe/open-liberty:beta-instanton parent image. After you save the Dockerfile, it should look something like this:

Dockerfile
FROM icr.io/appcafe/open-liberty:beta-instanton

ARG VERSION=1.0
ARG REVISION=SNAPSHOT

LABEL \
  org.opencontainers.image.authors="Your Name" \
  org.opencontainers.image.vendor="IBM" \
  org.opencontainers.image.url="local" \
  org.opencontainers.image.source="https://github.com/OpenLiberty/guide-getting-started" \
  org.opencontainers.image.version="$VERSION" \
  org.opencontainers.image.revision="$REVISION" \
  vendor="Open Liberty" \
  name="system" \
  version="$VERSION-$REVISION" \
  summary="The system microservice from the Getting Started guide" \
  description="This image contains the system microservice running with the Open Liberty runtime."

COPY --chown=1001:0 src/main/liberty/config/ /config/
COPY --chown=1001:0 target/*.war /config/apps/

RUN configure.sh

Building the application container image

For criu to be able to take a checkpoint of and restore a process, the criu binary must be granted additional Linux capabilities. In particular, for Open Liberty, it needs to be granted cap_checkpoint_restore, cap_net_admin and cap_sys_ptrace. The Open Liberty InstantOn beta image includes the criu binary with the necessary capabilities already granted to the criu binary file. For the criu binary to be given access to its assigned capabilities at run time, the container that is running criu must also be granted the necessary capabilities when it is launched. You can grant these capabilities to the container in one of two ways:

  1. Use a privileged container using the --privileged option

  2. Assign specific capabilities using --cap-add options

When you use Docker, the daemon typically has root authority. This authority allows it to grant any requested capabilities when it launches a container. With Podman, there is no daemon, so the user who launches the container must have the authority to grant it the necessary Linux capabilities. You have this authority when you run as root or use sudo to run the podman commands. For the purposes of this example, we assume you are running the podman commands as the root user.

With that understanding, we can now build the container image by using the podman build command. From the finish/ directory, run the following command to build the container image for the application:

Build the application container image
podman build -t getting-started .

This command creates the getting-started container image. However, this container image does not contain any checkpoint image files that can be used for InstantOn startup. You can run this application container image with the following command:

Run the application container
podman run --name getting-started --rm -p 9080:9080 getting-started

Note the amount of time Liberty takes to report it has been started and check out the service running in the container at the http://localhost:9080/dev/system/properties URL. After you finish checking out the application, stop the running container by pressing CTRL+C in the command-line session where you ran the podman run command.

Checkpoint an application in-container

Open Liberty has three phases during the startup process where a checkpoint can occur:

  1. features - This is the earliest phase where a checkpoint can happen. The checkpoint occurs after all of the configured Open Liberty features are started, but before any processing occurs for the installed applications.

  2. deployment - The checkpoint happens after processing the configured application metadata. If the application has any components that get run as part of the application starting, the checkpoint is taken before executing any code from the application.

  3. applications - This is the last phase where a checkpoint can happen, so it has the potential to provide the fastest startup time when restoring the application instance. The checkpoint happens after all configured applications are reported as started. This phase happens before opening any ports for listening to incoming requests for the applications.

The applications phase typically provides the quickest startup time for an application, but it also might cause some application code to run before the server process checkpoint happens. This might lead to undesired behavior when restoring the checkpoint process if the application holds on to some state that should not be restored into more than one concurrent instance of the application. For example, connecting to an outside resource such as a database before the checkpoint is taken results in a failure to restore many instances of such a process since this would try to restore the same connection multiple times. However, If your application initialization does not perform operations such as opening database connections, you might be able to use the applications phase for the checkpoint.

After an application container image is built, it can be used to checkpoint the application process at one of the previously described checkpoint phases (features, deployment, applications). You can specify a phase for your checkpoint by using the --env option to podman run to set the value for WLP_CHECKPOINT to one of the available checkpoint phases. For this example, use the applications phase by running the following podman command:

Perform a checkpoint in container
podman run \
  --name getting-started-checkpoint-container \
  --privileged \
  --env WLP_CHECKPOINT=applications \
  getting-started
  • The --privileged option is required to perform the criu checkpoint in-container.

  • The WLP_CHECKPOINT environment variable is used to specify the checkpoint phase. For the getting-started example the applications checkpoint phase will provide the fastest restore time.

This will start the container with the application running on Open Liberty. After Open Liberty starts, it performs the checkpoint at the phase specified by the WLP_CHECKPOINT environment variable. After the container process data has been persisted, the container will stop, leaving you with a stopped container that contains the checkpoint process data. The output will look something like this:

Process checkpoint output
Performing checkpoint --at=applications

Launching defaultServer (Open Liberty 22.0.0.11-beta/wlp-1.0.69.cl221020220912-1100) on Eclipse OpenJ9 VM, version 17.0.5-ea+2 (en_US)
CWWKE0953W: This version of Open Liberty is an unsupported early release version.
[AUDIT   ] CWWKE0001I: The server defaultServer has been launched.
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/checkpoint.xml
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/keystore.xml
[AUDIT   ] CWWKG0093A: Processing configuration drop-ins resource: /opt/ol/wlp/usr/servers/defaultServer/configDropins/defaults/open-default-port.xml
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/ibm/api/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/metrics/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/health/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://f5edff273d9c:9080/dev/
[AUDIT   ] CWWKZ0001I: Application guide-getting-started started in 0.986 seconds.
[AUDIT   ] CWWKC0451I: A server checkpoint was requested. When the checkpoint completes, the server stops.

This process currently cannot be done as part of a podman build step because Podman (and Docker) do not provide a way to grant the container image build the necessary Linux capabilities for criu to perform the process checkpoint.

Create the application checkpoint image

So far, we have created the checkpoint process data for the getting-started application and stored it in a stopped container named getting-started-checkpoint-container. The final step is to create a new container image that contains the checkpoint process data. When this container image is started, it will resume the application process right from the point that the checkpoint was created, resulting in an InstantOn application. You can create the new image by running the following podman commit operation:

Commit the checkpoint to an image
podman commit getting-started-checkpoint-container getting-started-instanton

Now we have two application images named getting-started and getting-started-instanton. Starting a container with the getting-started-instanton container image will show a much faster startup time than the original getting-started image.

Running the instanton application image

Typically, an application container can be started from an application container image with a command like the following:

podman run --rm -p 9080:9080 getting-started-instanton

However, this command will fail because criu needs some elevated privileges in order to be able to restore the process in-container. When Liberty fails to restore the checkpoint process, it will recover by launching without the checkpoint image and log the following message:

CWWKE0957I: Restoring the checkpoint server process failed. Check the /logs/checkpoint/restore.log log to determine why the checkpoint process was not restored. Launching the server without using the checkpoint image.

Running with --privileged option

To grant all the required privileges available you can choose to launch a privileged container with the following command:

podman run --rm --privileged -p 9080:9080 getting-started-instanton

If successful, you will see output like the following:

[AUDIT   ] CWWKZ0001I: Application guide-getting-started started in 0.059 seconds.
[AUDIT   ] CWWKC0452I: The Liberty server process resumed operation from a checkpoint in 0.088 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [cdi-3.0, checkpoint-1.0, concurrent-2.0, distributedMap-1.0, jndi-1.0, json-1.0, jsonb-2.0, jsonp-2.0, monitor-1.0, mpConfig-3.0, mpHealth-4.0, mpMetrics-4.0, restfulWS-3.0, restfulWSClient-3.0, servlet-5.0, ssl-1.0, transportSecurity-1.0].
[AUDIT   ] CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 0.098 seconds.

Running with an unprivileged container

Running fully privileged containers is not recommended. The best practice is to instead reduce the elevated privileges down to only what is required to run the container. You can use the following command to grant the container the necessary privileges without running a fully --privileged container:

podman run with unconfined --security-opt options
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 \
  getting-started-instanton

The --cap-add options grant the container the three Linux capabilities that criu requires. The --security-opt options are necessary to grant criu access to the required system calls and access to /proc/sys/kernel/ns_last_pid from the host.

Running with an unprivileged container with confined security

You can further simplify the checkpoint process by reducing the need for the --security-opt options that use unconfined. By default, podman does not grant access to all the system calls that criu needs (defaults specified in the file /usr/share/containers/seccomp.json). First, you need an additional configuration file that grants all the required system calls that criu needs to the container. Second, the host /proc/sys/kernel/ns_last_pid needs to be mounted. You can do both these steps with the following command:

podman run with limited --security-opt
podman run \
  --rm \
  --cap-add=CHECKPOINT_RESTORE \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_PTRACE \
  --security-opt seccomp=criuRequiredSysCalls.json \
  -v /proc/sys/kernel/ns_last_pid:/proc/sys/kernel/ns_last_pid \
  -p 9080:9080 \
  getting-started-instanton

The --security-opt seccomp= option refers to a file called criuRequiredSysCalls.json. This file specifies the system calls required by criu. The -v option mounts the host /proc/sys/kernel/ns_last_pid for access by the container.

Depending on your Linux distribution, Podman might use runc or crun by default. To check what container runtime is configured for your Podman installation, run the command podman info and look at the ociRuntime section. If runc is used, make sure you are using version 1.1.3 or higher. For this method to work, you must have a version of runc that is 1.1.3 or greater.

Depending on how up to date your RHEL 8.6 or RHEL 9.0 installation is, you might find that the --security-opt for specifying the criuRequiredSysCalls.json is unnecessary. At the time of writing, the most up-to-date versions of RHEL 8.6 and RHEL 9.0 include a Podman that grants the required system calls to the containers it launches by default. This default makes specifying the --security-opt seccomp=criuRequiredSysCalls.json unnecessary.

criuRequiredSysCalls.json
{
        "defaultAction": "SCMP_ACT_ERRNO",
        "defaultErrnoRet": 1,
        "archMap": [
                {
                        "architecture": "SCMP_ARCH_X86_64",
                        "subArchitectures": [
                                "SCMP_ARCH_X86",
                                "SCMP_ARCH_X32"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_AARCH64",
                        "subArchitectures": [
                                "SCMP_ARCH_ARM"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_MIPS64",
                        "subArchitectures": [
                                "SCMP_ARCH_MIPS",
                                "SCMP_ARCH_MIPS64N32"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_MIPS64N32",
                        "subArchitectures": [
                                "SCMP_ARCH_MIPS",
                                "SCMP_ARCH_MIPS64"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_MIPSEL64",
                        "subArchitectures": [
                                "SCMP_ARCH_MIPSEL",
                                "SCMP_ARCH_MIPSEL64N32"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_MIPSEL64N32",
                        "subArchitectures": [
                                "SCMP_ARCH_MIPSEL",
                                "SCMP_ARCH_MIPSEL64"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_S390X",
                        "subArchitectures": [
                                "SCMP_ARCH_S390"
                        ]
                },
                {
                        "architecture": "SCMP_ARCH_RISCV64",
                        "subArchitectures": null
                }
        ],
        "syscalls": [
                {
                        "names": [
                                "accept",
                                "accept4",
                                "access",
                                "adjtimex",
                                "alarm",
                                "bind",
                                "brk",
                                "capget",
                                "capset",
                                "chdir",
                                "chmod",
                                "chown",
                                "chown32",
                                "clock_adjtime",
                                "clock_adjtime64",
                                "clock_getres",
                                "clock_getres_time64",
                                "clock_gettime",
                                "clock_gettime64",
                                "clock_nanosleep",
                                "clock_nanosleep_time64",
                                "close",
                                "close_range",
                                "connect",
                                "copy_file_range",
                                "creat",
                                "dup",
                                "dup2",
                                "dup3",
                                "epoll_create",
                                "epoll_create1",
                                "epoll_ctl",
                                "epoll_ctl_old",
                                "epoll_pwait",
                                "epoll_pwait2",
                                "epoll_wait",
                                "epoll_wait_old",
                                "eventfd",
                                "eventfd2",
                                "execve",
                                "execveat",
                                "exit",
                                "exit_group",
                                "faccessat",
                                "faccessat2",
                                "fadvise64",
                                "fadvise64_64",
                                "fallocate",
                                "fanotify_mark",
                                "fchdir",
                                "fchmod",
                                "fchmodat",
                                "fchown",
                                "fchown32",
                                "fchownat",
                                "fcntl",
                                "fcntl64",
                                "fdatasync",
                                "fgetxattr",
                                "flistxattr",
                                "flock",
                                "fork",
                                "fremovexattr",
                                "fsetxattr",
                                "fstat",
                                "fstat64",
                                "fstatat64",
                                "fstatfs",
                                "fstatfs64",
                                "fsync",
                                "ftruncate",
                                "ftruncate64",
                                "futex",
                                "futex_time64",
                                "futex_waitv",
                                "futimesat",
                                "getcpu",
                                "getcwd",
                                "getdents",
                                "getdents64",
                                "getegid",
                                "getegid32",
                                "geteuid",
                                "geteuid32",
                                "getgid",
                                "getgid32",
                                "getgroups",
                                "getgroups32",
                                "getitimer",
                                "getpeername",
                                "getpgid",
                                "getpgrp",
                                "getpid",
                                "getppid",
                                "getpriority",
                                "getrandom",
                                "getresgid",
                                "getresgid32",
                                "getresuid",
                                "getresuid32",
                                "getrlimit",
                                "get_robust_list",
                                "getrusage",
                                "getsid",
                                "getsockname",
                                "getsockopt",
                                "get_thread_area",
                                "gettid",
                                "gettimeofday",
                                "getuid",
                                "getuid32",
                                "getxattr",
                                "inotify_add_watch",
                                "inotify_init",
                                "inotify_init1",
                                "inotify_rm_watch",
                                "io_cancel",
                                "ioctl",
                                "io_destroy",
                                "io_getevents",
                                "io_pgetevents",
                                "io_pgetevents_time64",
                                "ioprio_get",
                                "ioprio_set",
                                "io_setup",
                                "io_submit",
                                "io_uring_enter",
                                "io_uring_register",
                                "io_uring_setup",
                                "ipc",
                                "kill",
                                "landlock_add_rule",
                                "landlock_create_ruleset",
                                "landlock_restrict_self",
                                "lchown",
                                "lchown32",
                                "lgetxattr",
                                "link",
                                "linkat",
                                "listen",
                                "listxattr",
                                "llistxattr",
                                "_llseek",
                                "lremovexattr",
                                "lseek",
                                "lsetxattr",
                                "lstat",
                                "lstat64",
                                "madvise",
                                "membarrier",
                                "memfd_create",
                                "memfd_secret",
                                "mincore",
                                "mkdir",
                                "mkdirat",
                                "mknod",
                                "mknodat",
                                "mlock",
                                "mlock2",
                                "mlockall",
                                "mmap",
                                "mmap2",
                                "mprotect",
                                "mq_getsetattr",
                                "mq_notify",
                                "mq_open",
                                "mq_timedreceive",
                                "mq_timedreceive_time64",
                                "mq_timedsend",
                                "mq_timedsend_time64",
                                "mq_unlink",
                                "mremap",
                                "msgctl",
                                "msgget",
                                "msgrcv",
                                "msgsnd",
                                "msync",
                                "munlock",
                                "munlockall",
                                "munmap",
                                "nanosleep",
                                "newfstatat",
                                "_newselect",
                                "open",
                                "openat",
                                "openat2",
                                "pause",
                                "pidfd_open",
                                "pidfd_send_signal",
                                "pipe",
                                "pipe2",
                                "poll",
                                "ppoll",
                                "ppoll_time64",
                                "prctl",
                                "pread64",
                                "preadv",
                                "preadv2",
                                "prlimit64",
                                "process_mrelease",
                                "pselect6",
                                "pselect6_time64",
                                "pwrite64",
                                "pwritev",
                                "pwritev2",
                                "read",
                                "readahead",
                                "readlink",
                                "readlinkat",
                                "readv",
                                "recv",
                                "recvfrom",
                                "recvmmsg",
                                "recvmmsg_time64",
                                "recvmsg",
                                "remap_file_pages",
                                "removexattr",
                                "rename",
                                "renameat",
                                "renameat2",
                                "restart_syscall",
                                "rmdir",
                                "rseq",
                                "rt_sigaction",
                                "rt_sigpending",
                                "rt_sigprocmask",
                                "rt_sigqueueinfo",
                                "rt_sigreturn",
                                "rt_sigsuspend",
                                "rt_sigtimedwait",
                                "rt_sigtimedwait_time64",
                                "rt_tgsigqueueinfo",
                                "sched_getaffinity",
                                "sched_getattr",
                                "sched_getparam",
                                "sched_get_priority_max",
                                "sched_get_priority_min",
                                "sched_getscheduler",
                                "sched_rr_get_interval",
                                "sched_rr_get_interval_time64",
                                "sched_setaffinity",
                                "sched_setattr",
                                "sched_setparam",
                                "sched_setscheduler",
                                "sched_yield",
                                "seccomp",
                                "select",
                                "semctl",
                                "semget",
                                "semop",
                                "semtimedop",
                                "semtimedop_time64",
                                "send",
                                "sendfile",
                                "sendfile64",
                                "sendmmsg",
                                "sendmsg",
                                "sendto",
                                "setfsgid",
                                "setfsgid32",
                                "setfsuid",
                                "setfsuid32",
                                "setgid",
                                "setgid32",
                                "setgroups",
                                "setgroups32",
                                "setitimer",
                                "setpgid",
                                "setpriority",
                                "setregid",
                                "setregid32",
                                "setresgid",
                                "setresgid32",
                                "setresuid",
                                "setresuid32",
                                "setreuid",
                                "setreuid32",
                                "setrlimit",
                                "set_robust_list",
                                "setsid",
                                "setsockopt",
                                "set_thread_area",
                                "set_tid_address",
                                "setuid",
                                "setuid32",
                                "setxattr",
                                "shmat",
                                "shmctl",
                                "shmdt",
                                "shmget",
                                "shutdown",
                                "sigaltstack",
                                "signalfd",
                                "signalfd4",
                                "sigprocmask",
                                "sigreturn",
                                "socket",
                                "socketcall",
                                "socketpair",
                                "splice",
                                "stat",
                                "stat64",
                                "statfs",
                                "statfs64",
                                "statx",
                                "symlink",
                                "symlinkat",
                                "sync",
                                "sync_file_range",
                                "syncfs",
                                "sysinfo",
                                "tee",
                                "tgkill",
                                "time",
                                "timer_create",
                                "timer_delete",
                                "timer_getoverrun",
                                "timer_gettime",
                                "timer_gettime64",
                                "timer_settime",
                                "timer_settime64",
                                "timerfd_create",
                                "timerfd_gettime",
                                "timerfd_gettime64",
                                "timerfd_settime",
                                "timerfd_settime64",
                                "times",
                                "tkill",
                                "truncate",
                                "truncate64",
                                "ugetrlimit",
                                "umask",
                                "uname",
                                "unlink",
                                "unlinkat",
                                "utime",
                                "utimensat",
                                "utimensat_time64",
                                "utimes",
                                "vfork",
                                "vmsplice",
                                "wait4",
                                "waitid",
                                "waitpid",
                                "write",
                                "writev",
                                "arch_prctl",
                                "chroot",
                                "clone",
                                "clone3",
                                "fallocate",
                                "fanotify_init",
                                "fsconfig",
                                "fsmount",
                                "fsopen",
                                "guarded_storage",
                                "kcmp",
                                "lseek",
                                "mmap",
                                "mount",
                                "open",
                                "open_by_handle_at",
                                "openat",
                                "pivot_root",
                                "preadv",
                                "process_vm_readv",
                                "ptrace",
                                "readdir",
                                "s390_runtime_instr",
                                "setns",
                                "sigaction",
                                "signal",
                                "syscall",
                                "umount",
                                "umount2",
                                "unshare",
                                "userfaultfd",
                                "wait"
                        ],
                        "action": "SCMP_ACT_ALLOW"
                },
                {
                        "names": [
                                "process_vm_readv",
                                "process_vm_writev",
                                "ptrace"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "minKernel": "4.8"
                        }
                },
                {
                        "names": [
                                "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 0,
                                        "op": "SCMP_CMP_EQ"
                                }
                        ]
                },
                {
                        "names": [
                                "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 8,
                                        "op": "SCMP_CMP_EQ"
                                }
                        ]
                },
                {
                        "names": [
                                "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 131072,
                                        "op": "SCMP_CMP_EQ"
                                }
                        ]
                },
                {
                        "names": [
                                "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 131080,
                                        "op": "SCMP_CMP_EQ"
                                }
                        ]
                },
                {
                        "names": [
                                "personality"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 4294967295,
                                        "op": "SCMP_CMP_EQ"
                                }
                        ]
                },
                {
                        "names": [
                                "sync_file_range2",
                                "swapcontext"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "ppc64le"
                                ]
                        }
                },
                {
                        "names": [
                                "arm_fadvise64_64",
                                "arm_sync_file_range",
                                "sync_file_range2",
                                "breakpoint",
                                "cacheflush",
                                "set_tls"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "arm",
                                        "arm64"
                                ]
                        }
                },
                {
                        "names": [
                                "arch_prctl"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "amd64",
                                        "x32"
                                ]
                        }
                },
                {
                        "names": [
                                "modify_ldt"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "amd64",
                                        "x32",
                                        "x86"
                                ]
                        }
                },
                {
                        "names": [
                                "s390_pci_mmio_read",
                                "s390_pci_mmio_write",
                                "s390_runtime_instr"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "s390",
                                        "s390x"
                                ]
                        }
                },
                {
                        "names": [
                                "riscv_flush_icache"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "arches": [
                                        "riscv64"
                                ]
                        }
                },
                {
                        "names": [
                                "open_by_handle_at"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_DAC_READ_SEARCH"
                                ]
                        }
                },
                {
                        "names": [
                                "bpf",
                                "clone",
                                "clone3",
                                "fanotify_init",
                                "fsconfig",
                                "fsmount",
                                "fsopen",
                                "fspick",
                                "lookup_dcookie",
                                "mount",
                                "mount_setattr",
                                "move_mount",
                                "name_to_handle_at",
                                "open_tree",
                                "perf_event_open",
                                "quotactl",
                                "quotactl_fd",
                                "setdomainname",
                                "sethostname",
                                "setns",
                                "syslog",
                                "umount",
                                "umount2",
                                "unshare"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_ADMIN"
                                ]
                        }
                },
                {
                        "names": [
                                "clone"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 0,
                                        "value": 2114060288,
                                        "op": "SCMP_CMP_MASKED_EQ"
                                }
                        ],
                        "excludes": {
                                "caps": [
                                        "CAP_SYS_ADMIN"
                                ],
                                "arches": [
                                        "s390",
                                        "s390x"
                                ]
                        }
                },
                {
                        "names": [
                                "clone"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "args": [
                                {
                                        "index": 1,
                                        "value": 2114060288,
                                        "op": "SCMP_CMP_MASKED_EQ"
                                }
                        ],
                        "comment": "s390 parameter ordering for clone is different",
                        "includes": {
                                "arches": [
                                        "s390",
                                        "s390x"
                                ]
                        },
                        "excludes": {
                                "caps": [
                                        "CAP_SYS_ADMIN"
                                ]
                        }
                },
                {
                        "names": [
                                "clone3"
                        ],
                        "action": "SCMP_ACT_ERRNO",
                        "errnoRet": 38,
                        "excludes": {
                                "caps": [
                                        "CAP_SYS_ADMIN"
                                ]
                        }
                },
                {
                        "names": [
                                "reboot"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_BOOT"
                                ]
                        }
                },
                {
                        "names": [
                                "chroot"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_CHROOT"
                                ]
                        }
                },
                {
                        "names": [
                                "delete_module",
                                "init_module",
                                "finit_module"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_MODULE"
                                ]
                        }
                },
                {
                        "names": [
                                "acct"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_PACCT"
                                ]
                        }
                },
                {
                        "names": [
                                "kcmp",
                                "pidfd_getfd",
                                "process_madvise",
                                "process_vm_readv",
                                "process_vm_writev",
                                "ptrace"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_PTRACE"
                                ]
                        }
                },
                {
                        "names": [
                                "iopl",
                                "ioperm"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_RAWIO"
                                ]
                        }
                },
                {
                        "names": [
                                "settimeofday",
                                "stime",
                                "clock_settime"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_TIME"
                                ]
                        }
                },
                {
                        "names": [
                                "vhangup"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_TTY_CONFIG"
                                ]
                        }
                },
                {
                        "names": [
                                "get_mempolicy",
                                "mbind",
                                "set_mempolicy"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYS_NICE"
                                ]
                        }
                },
                {
                        "names": [
                                "syslog"
                        ],
                        "action": "SCMP_ACT_ALLOW",
                        "includes": {
                                "caps": [
                                        "CAP_SYSLOG"
                                ]
                        }
                }
        ]
}

How fast is it?

We tested multiple applications to show how startup time is reduced with InstantOn.

  • Pingperf is a very simple ping-type application involve a single REST endpoint.

  • Rest crud is a bit more complicated, and involves JPA and a remote database.

  • AcmeAir Microservice Main makes use of the MicroProfile features.

These experiments were run on a 24 core system. I used taskset -c to allocate 4 CPUs to the Liberty process running in container. The InstantOn times were taken using the applications checkpoint phase. Startup time is measured from the time the Liberty server startup is initiated to the time the server is ready to accept requests, as denoted by the message "The <server name> server is ready to run a smarter planet." in the messages.log. The time it takes to start the container itself up has been filtered out. InstantOn versus normal startup times for these applications are shown here in relative terms, with the baseline times normalized to 100 for each application. Lower is better:

Startup Performance

InstantOn offers a large startup savings of up to 90% depending on the application. All applications are not the same, so you might see different results.

What is next?

This post described the details of using Open Liberty InstantOn beta to produce an application container image with InstantOn startup times. This support currently allows for only Open Liberty features that are included as part of the Liberty webProfile-8.0, webProfile-9.1, microProfile-4.1 and microProfile-5.0 umbrella features. We hope to expand that to include future versions of webProfile and microProfile, as well as to expand support to the Jakarta full profile features (e.g. jakarta-8.0, jakarta-9.1, jakarta-10.0).

With InstantOn, you can build very fast startup application containers that can be deployed with scale-to-zero as an option. We look forward to a future blog post that describes how to deploy Open Liberty InstantOn in cloud environments such as Red Hat OpenShift Container Platform (OCP) and Kubernetes (k8s) with technologies that can auto-scale applications to zero, such as Knative.


September 29, 2022 12:00 AM

InstantOn with checkpoint/restore in Open Liberty 22.0.0.11-beta!

September 29, 2022 12:00 AM

Open Liberty 22.0.0.11-beta provides an exciting new capability called InstantOn, which provides incredibly fast startup times and can help reduce the overall cloud costs for cloud-native applications.

Since the 22.0.0.9-beta release, which included the Jakarta EE 10 Core Profile, Open Liberty has continued to beta more and more Jakarta EE 10 features. This beta release introduces various developer experience and performance enhancements available through the following new Jakarta EE 10 features: Servlet 6.0, Mail 2.1, Connectors 2.1 and Persistance 3.1.

The Open Liberty 22.0.0.11-beta includes the following new beta features (along with all GA features):

InstantOn with checkpoint/restore

Traditionally, starting an application can take several seconds, and sometimes minutes, before the application can service its first request. Longer startup times inhibit an application’s ability to scale to zero when deployed in a cloud environment such as Kubernetes, which in turn can drive up costs.

Liberty’s InstantOn capability is an innovative way to drastically reduce that startup time by using checkpoint/restore. Restoring an application from a checkpoint process can be up to 10 times faster than starting the Liberty application from the beginning.

For more information, see the Liberty InstantOn startup for cloud native Java applications blog post.

Jakarta EE 10 Updates

With the 22.0.0.11-beta release, Open Liberty adds four more Jakarta EE 10 features: Mail 2.1, Servlet 6.0, Connectors 2.1 and Persistance 3.1. These four features join the Jakarta EE 10 features from previous beta releases, including those that make up the Jakarta EE 10 Core Profile. To review all the previous beta content, take a look at the recent beta blog posts.

Set any cookie attribute (Jakarta Servlet 6.0)

The Open Liberty Jakarta Servlet 6.0 (servlet-6.0) feature is an implementation of the Jakarta EE 10 Servlet 6.0 specification. It includes a number of new features, specification clarifications, and deprecation features.

Before Jakarta Servlet 6.0, only a few specific methods could be set for an application’s cookie attributes. This meant that an application could not easily set a new attribute, such as the recent browser security SameSite attribute.

One of the new features in Jakarta Servlet 6.0 is the ability to set any attribute using a cookie’s setAttribute method. In addition, Jakarta Servlet 6.0 also introduces some new request APIs to aid the application’s debugging. Application developers can track or refer to a request using the ServletRequest() getRequestId() method or obtain details of the network connection that is being used by the request by calling ServletRequest() getServletConnection() method.

You can enable the feature by adding servlet-6.0 to your server.xml:

  <featureManager>
    <feature>servlet-6.0</feature>
  </featureManager>

For more information, refer to the Jakarta Servlet 6.0 Specification and Javadocs.

Simpler Jakarta Mail code compilation (Jakarta Mail 2.1)

Jakarta Mail 2.1 support allows your Jakarta EE 10 applications to send, read, and edit E-Mail from mail servers via the Jakarta Mail APIs.

The biggest change to the Jakarta Mail 2.1 specification is the removal of the direct dependency of the specification APIs on the reference implementation. This means that, in certain cases, there is no longer a need to compile your Jakarta Mail code against both the specification and the reference implementation (provided you aren’t making any direct calls to the reference implementation in your code).

To facilitate this improvement, Jakarta Mail 2.1 also introduces the jakarta.mail.util.StreamProvider utility interface, which can be easily obtained with the jakarta.mail.Session.getStreamProvider() method. You can then use the StreamProviders instance to obtain encoded/decoded streams for any of the encoding/decoding methods that Jakarta Mail 2.1 supports.

You can enable the feature by adding mail-2.1 to your server.xml:

  <featureManager>
    <feature>mail-2.1</feature>
  </featureManager>

For more information about the Jakarta Mail 2.1 specification, check out the Jakarta Mail project website.

Ensure correctness of data types (Jakarta Connectors 2.1)

Jakarta Connectors standardizes how connectors to various enterprise information systems interact with the container and applications. Jakarta Connectors 2.1 enables you to use the latest release of the Jakarta resource specification in your application.

The main update to Jakarta Connectors in this minor feature version update is the addition of Java generics support to the jakarta.resource.cci.ResourceFactory, jakarta.resource.cci.IndexedRecord, and jakarta.resource.cci.MappedRecord classes. This helps avoid compiler warnings and also helps ensure correctness of data types during development time.

You can enable the feature by adding connectors-2.1 to your server.xml:

  <featureManager>
    <feature>connectors-2.1</feature>
  </featureManager>

All other resourceAdapter configurations within server.xml can remain unchanged for current applications.

You can find out more about this specific update with the following links:

JPQL and Criteria API enhancements (Jakarta Persistence 3.1)

Jakarta Persistence API (JPA) is a richly featured API that provides an object-model approach to persisting, fetching, and modifying data stored on a relational database system. Prior to the introduction of JPA in Java EE 5, in order to interact with database storage, you had to use EJB bean or container managed entities, or raw JDBC.

Jakarta Persistence 3.1 is a minor version update but introduces some great new capabilities. You can now take advantage of the AutoClosable interface, introduced in Java 7, which allows for resources declared in a try-with-resources block to be automatically closed upon the completion of that try block. Other new features include the ability to use fields of type java.lang.UUID as @Id types and enhancements to Java Persistence Query Language (JPQL) and Criteria API.

You can enable the feature by adding persistence-3.1 to your server.xml:

  <featureManager>
    <feature>persistence-3.1</feature>
  </featureManager>

Try it now

To try out these features, just update your build tools to pull the Open Liberty All Beta Features package instead of the main release. The beta works with Java SE 19, Java SE 18, Java SE 17, Java SE 11, and Java SE 8.

If you’re using Maven, here are the coordinates:

<dependency>
  <groupId>io.openliberty.beta</groupId>
  <artifactId>openliberty-runtime</artifactId>
  <version>22.0.0.11-beta</version>
  <type>pom</type>
</dependency>

Or for Gradle:

dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[22.0.0.11-beta,)'
}

Or take a look at our Downloads page.

We welcome your feedback

Let us know what you think on our mailing list. If you hit a problem, post a question on StackOverflow. If you hit a bug, please raise an issue.


September 29, 2022 12:00 AM

Jakarta Persistence 3.1 new features

by F.Marchioni at September 27, 2022 10:12 AM

This tutorial introduces Jakarta Persistence API 3.1 as a standard for management of persistence and O/R mapping in Java environments. We will discuss the headlines with a simple example that you can test on a Jakarta EE 10 runtime. New features added in Jakarta Persistence 3.1 There are several new features available in Jakarta Persistence ... Read more

The post Jakarta Persistence 3.1 new features appeared first on Mastertheboss.


by F.Marchioni at September 27, 2022 10:12 AM

Survey Says: Confidence Continues to Grow in the Jakarta EE Ecosystem

by Mike Milinkovich at September 26, 2022 01:00 PM

The results of the 2022 Jakarta EE Developer Survey are very telling about the current state of the enterprise Java developer community. They point to increased confidence about Jakarta EE and highlight how far Jakarta EE has grown over the past few years.

Strong Turnout Helps Drive Future of Jakarta EE

The fifth annual survey is one of the longest running and best-respected surveys of its kind in the industry. This year’s turnout was fantastic: From March 9 to May 6, a total of 1,439 developers responded. 

This is great for two reasons. First, obviously, these results help inform the Java ecosystem stakeholders about the requirements, priorities and perceptions of enterprise developer communities. The more people we hear from, the better picture we get of what the community wants and needs. That makes it much easier for us to make sure the work we’re doing is aligned with what our community is looking for. 

The other reason is that it helps us better understand how the cloud native Java world is progressing. By looking at what community members are using and adopting, what their top goals are and what their plans are for adoption, we can better understand not only what we should be working on today, but tomorrow and for the future of Jakarta EE. 

Findings Indicate Growing Adoption and Rising Expectations

Some of the survey’s key findings include:

  • Jakarta EE is the basis for the top frameworks used for building cloud native applications.
  • The top three frameworks for building cloud native applications, respectively, are Spring/Spring Boot, Jakarta EE and MicroProfile, though Spring/Spring Boot lost ground this past year. It’s important to note that Spring/SpringBoot relies on Jakarta EE developments for its operation and is not competitive with Jakarta EE. Both are critical ingredients to the healthy enterprise Java ecosystem. 
  • Jakarta EE 9/9.1 usage increased year-over-year by 5%.
  • Java EE 8, Jakarta EE 8, and Jakarta EE 9/9.1 hit the mainstream with 81% adoption. 
  • While over a third of respondents planned to adopt, or already had adopted Jakarta EE 9/9.1, nearly a fifth of respondents plan to skip Jakarta EE 9/9.1 altogether and adopt Jakarta EE 10 once it becomes available. 
  • Most respondents said they have migrated to Jakarta EE already or planned to do so within the next 6-24 months.
  • The top three community priorities for Jakarta EE are:
    • Native integration with Kubernetes (same as last year)
    • Better support for microservices (same as last year)
    • Faster support from existing Java EE/Jakarta EE or cloud vendors (new this year)

Two of the results, when combined, highlight something interesting:

  • 19% of respondents planned to skip Jakarta EE 9/9.1 and go straight to 10 once it’s available 
  • The new community priority — faster support from existing Java EE/Jakarta EE or cloud vendors — really shows the growing confidence the community has in the ecosystem

After all, you wouldn’t wait for a later version and skip the one that’s already available, unless you were confident that the newer version was not only going to be coming out on a relatively reliable timeline, but that it was going to be an improvement. 

And this growing hunger from the community for faster support really speaks to how far the ecosystem has come. When we release a new version, like when we released Jakarta EE 9, it takes some time for the technology implementers to build the product based on those standards or specifications. The community is becoming more vocal in requesting those implementers to be more agile and quickly pick up the new versions. That’s definitely an indication that developer demand for Jakarta EE products is growing in a healthy way. 

Learn More

If you’d like to learn more about the project, there are several Jakarta EE mailing lists to sign up for. You can also join the conversation on Slack. And if you want to get involved, start by choosing a project, sign up for its mailing list and start communicating with the team.


by Mike Milinkovich at September 26, 2022 01:00 PM

From Punched Cards to Java 11--airhacks.fm podcast

by admin at September 25, 2022 05:42 PM

Subscribe to airhacks.fm podcast via: spotify| iTunes| RSS

The #209 airhacks.fm episode with Glenn Holmer (@gholmer) about:
the transition from punched cards over assembly, servlets, enterprise java to Java 11+.
is available for download.

by admin at September 25, 2022 05:42 PM

Hashtag Jakarta EE #143

by Ivar Grimstad at September 25, 2022 09:59 AM

Welcome to issue number one hundred and forty-three of Hashtag Jakarta EE!

What a week for the Java community! Java SE 19 on Tuesday and Jakarta EE 10 on Thursday!

There are already several options available for Java SE 19. For those of you waiting for Eclipse Temurin, I can assure you that is on the way. Check the build status to be the first to know when you can get it.

The other thing happening this week, besides the release of Java SE 19, was the release of the long-anticipated Jakarta EE 10.

In the announcement The Eclipse Foundation’s Jakarta EE Working Group Releases Jakarta EE 10 to Usher in the Era of Cloud Native Java, you can among other things read quotes from 10 of the Jakarta EE Working Group members. You can also check out my Jakarta EE 10 post for some pointers on where to get started with Jakarta EE 10.

Next week, I’ll be in Chicago for JCONF.DEV, or DEEP.DISH.JAVA. if you like. My talk titled Jakarta EE 10 – Simplicity for Modern and Lightweight Cloud Applications is scheduled for Wednesday, September 28 at 10:00. I’m bringing T-shirts, stickers, and other Jakarta EE 10 swag. Don’t be shy, come and say hi!


by Ivar Grimstad at September 25, 2022 09:59 AM

Debugging Incoming Headers with jwebserver

by admin at September 23, 2022 05:50 PM

jwebserver introduced with JEP 408 can be used for incoming header / user agent debugging.

Launching the web server in verbose mode with: jwebserver -o verbose, outputs the incoming headers after executing: curl http://localhost:8000:


> Accept: */*
> Host: localhost:8000
> User-agent: curl/7.79.1

The following Java HttpClient:


import java.net.http.HttpResponse.BodyHandlers;
import java.net.http.*;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("http://localhost:8000"))
                .GET()
                .build();
var response = client.send(request,BodyHandlers.ofString())

generates these headers:


> Connection: Upgrade, HTTP2-Settings
> Http2-settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
> Host: localhost:8000
> User-agent: Java-http-client/19
> Upgrade: h2c

See it in action and in less than 1 min:


by admin at September 23, 2022 05:50 PM

Jakarta EE 10 Brings Java Development Into the Modern Cloud Native Era

by Mike Milinkovich at September 22, 2022 04:00 PM

Jakarta EE, a Working Group hosted by the Eclipse Foundation, released Jakarta EE 10 today. 

This achievement was only possible because of a global community of contributors. Congratulations and thank you to everyone who played a part in this release. 

There are many new and innovative features added by the Jakarta EE community.

Jakarta EE 10 Enables Modern, Lightweight Java Applications and Microservices

Let’s start with some of the key updates in Jakarta EE 10 — updates that plant Jakarta EE firmly in the modern era of open source microservices and containers. 

Most prominently, Jakarta EE 10 includes a new profile specification: Jakarta EE Core Profile. The Core Profile includes a subset of Jakarta EE specifications that target the smaller, lightweight runtimes needed for microservices development. This is the first new Profile added to the enterprise Java specifications in over a decade.

In addition, new functionality has been added to more than 20 component specifications. For example:

Jakarta EE 10 also broadens support for annotations so it’s easier to build modularized applications and there’s better integration across component APIs.

Finally, I want to point out that Jakarta EE 10 gives enterprises the flexibility to leverage Java in the way that’s best for their organization. They can:

  • Develop and deploy Jakarta EE 10 applications on Java SE 11 as well as Java SE 17, the most current long-term support (LTS) release of Java SE
  • Take advantage of new features, including the modular system, that were introduced in Java SE 9 and supported in Java SE 11

The Jakarta EE Gamble Is Paying Off

This is all great news for Jakarta EE. But to understand how significant this release is, we need to go back to the Java EE days.

Java EE was the bedrock of application development for the Fortune 1000 for 20 years before it moved to the Eclipse Foundation as Jakarta EE. But the first Jakarta EE releases didn’t add new functionality. Then, Jakarta EE 9 introduced a major breaking change: the move to the jakarta.* namespace.

It’s hard to overstate what a gamble that was. Java EE had been basically backwards-compatible for more than two decades. We asked enterprises to change the fundamentals of applications they’d been relying on for a long time. We asked the enterprise Java ecosystem to re-align their products and opens source projects on a new namespace. Oftentimes, when you try to make such a radical change, your ecosystem says no, it’s too much work. And quite a few people thought the Jakarta EE gamble could fail for exactly that reason. 

But it didn’t. IBM, Red Hat, Payara, Spring, the Apache Tomcat and TomEE projects, and Eclipse Jetty, to name a few, all moved to the new namespace with us. 

Now, with new support for modern microservices architectures and containers, Jakarta EE 10 paves the way for Jakarta EE to drive the innovative, multi-vendor standards needed for the future of our industry. 

Get Involved in the Future of Jakarta EE

The momentum around Jakarta EE 10 is well underway. Eclipse GlassFish has released a compatible implementation, and other enterprises and project teams — including Fujitsu, IBM, Oracle, Payara, Red Hat and Tomitribe — are already working towards certifying Jakarta EE 10 compatible products 

Jakarta EE has an exciting future ahead, and we want everyone to participate and contribute. To learn more, connect with the global community. If enterprise Java is important to your business strategy, join the Jakarta EE Working Group. Learn more about the benefits and advantages of membership here.


by Mike Milinkovich at September 22, 2022 04:00 PM

Jakarta EE 10 has Landed!

by javaeeguardian at September 22, 2022 03:48 PM

The Jakarta EE Ambassadors are thrilled to see Jakarta EE 10 being released! This is a milestone release that bears great significance to the Java ecosystem. Jakarta EE 8 and Jakarta EE 9.x were important releases in their own right in the process of transitioning Java EE to a truly open environment in the Eclipse Foundation. However, these releases did not deliver new features. Jakarta EE 10 changes all that and begins the vital process of delivering long pending new features into the ecosystem at a regular cadence.

There are quite a few changes that were delivered – here are some key themes and highlights:

  • CDI Alignment
    • @Asynchronous in Concurrency
    • Better CDI support in Batch
  • Java SE Alignment
    • Support for Java SE 11, Java SE 17
    • CompletionStage, ForkJoinPool, parallel streams in Concurrency
    • Bootstrap APIs for REST
  • Closing standardization gaps
    • OpenID Connect support in Security, @ManagedExecutorDefinition, UUID as entity keys, more SQL support in Persistence queries, multipart/form-data support in REST, @ClientWindowScoped in Faces, pure Java Faces views
    • CDI Lite/Core Profile to enable next generation cloud native runtimes – MicroProfile will likely align with CDI Lite/Jakarta EE Core
  • Deprecation/removal
    • @Context annotation in REST, EJB Entity Beans, embeddable EJB container, deprecated Servlet/Faces/CDI features

While there are many features that we identified in our Jakarta EE 10 Contribution Guide that did not make it yet, this is still a very solid release that everyone in the Java ecosystem will benefit from, including Spring, MicroProfile and Quarkus. You can see here what was delivered, what’s on the way and what gaps still remain. You can try Jakarta EE 10 out now using compatible implementations like GlassFish, Payara, WildFly and Open Liberty. Jakarta EE 10 is proof in the pudding that the community, including major stakeholders, has not only made it through the transition to the Eclipse Foundation but now is beginning to thrive once again.

Many Ambassadors helped make this release a reality such as Arjan Tijms, Werner Keil, Markus Karg, Otavio Santana, Ondro Mihalyi and many more. The Ambassadors will now focus on enabling the community to evangelize Jakarta EE 10 including speaking, blogging, trying out implementations, and advocating for real world adoption. We will also work to enable the community to continue to contribute to Jakarta EE by producing an EE 11 Contribution Guide in the coming months. Please stay tuned and join us.

Jakarta EE is truly moving forward – the next phase of the platform’s evolution is here!


by javaeeguardian at September 22, 2022 03:48 PM

Jakarta EE 10

by Ivar Grimstad at September 22, 2022 01:11 PM

The Jakarta EE 10 Release is now officially out!

This release contains updates to most of the specifications. We have also made an effort to highlight changes in all specifications on the individual specification pages. Note that the features, deprecations, etc. listed there are some highlights. For a complete list, refer to the changelogs of the specification documents.

Some of you may have noticed that the artifacts have been available in Maven Central since last week, but here they are again.

Jakarta EE 10 Platform

<dependency>
  <groupId>jakarta.platform</groupId>
  <artifactId>jakarta.jakartaee-api</artifactId>
  <version>10.0.0</version>
  <scope>provided</scope>
</dependency>

Jakarta EE 10 Web Profile

<dependency>
  <groupId>jakarta.platform</groupId>
  <artifactId>jakarta.jakartaee-web-api</artifactId>
  <version>10.0.0</version>
  <scope>provided</scope>
</dependency>

Jakarta EE 10 Core Profile

<dependency>
  <groupId>jakarta.platform</groupId>
  <artifactId>jakarta.jakartaee-core-api</artifactId>
  <version>10.0.0</version>
  <scope>provided</scope>
</dependency>

As you can see, the scope in the maven dependency definitions above is set to provided. This is the beauty of Jakarta EE. You don’t need to clutter your application’s pom.xml with lots of dependencies. They are provided for you by the runtime of your choosing. Check out the compatible runtimes already available that implements Jakarta EE 10 on the Jakarta EE Compatible Products page. New products are added to the list continuously, so make sure you revisit the page once in a while to check out the various options. Jakarta EE is all about flexibility!


by Ivar Grimstad at September 22, 2022 01:11 PM

Payara Celebrates Jakarta EE 10 With Support in Community!

by Priya Khaira-Hanks at September 22, 2022 11:18 AM

Jakarta EE 10 launches today! At Payara, we are celebrating this major next step for enterprise Java, and support Jakarta EE 10 with Payara 6 Community.


by Priya Khaira-Hanks at September 22, 2022 11:18 AM

The differences between Spring Data JPA’s save, saveAndFlush and saveAll methods

by Thorben Janssen at September 22, 2022 09:01 AM

The post The differences between Spring Data JPA’s save, saveAndFlush and saveAll methods appeared first on Thorben Janssen.

Spring Data JPA’s standard repositories provide a set of methods that handle common operations used by most persistence layers. That saves us a lot of…

The post The differences between Spring Data JPA’s save, saveAndFlush and saveAll methods appeared first on Thorben Janssen.


by Thorben Janssen at September 22, 2022 09:01 AM

SCARY Performance! – record.hashCode() | Head Crashing Informatics 61

by Markus Karg at September 17, 2022 03:00 PM

`record` is a cool and comfortable keyword in #Java, as it does a lot of things for you. But is the resulting code really FAST? This video reveals SCARY performance!

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! 🙂


by Markus Karg at September 17, 2022 03:00 PM

Jersey 2.37, 3.0.8, and 3.1.0-M8

by Jan at September 08, 2022 08:01 AM

Jersey project continues to develop three branches, Java EE / Jakarta EE 8 – Jersey 2.x, Jakarta EE 9 – 3.0.x, and the new Jakarta EE 10 – 3.1.x. Recently, Jersey 2.37, and 3.0.8 were released. Jersey 3.1.0-M8 is still … Continue reading

by Jan at September 08, 2022 08:01 AM

Jakarta EE 10: The countdown can start!

by Tanja Obradovic at September 06, 2022 05:37 PM

 

At this point it is a question of days, not weeks! The expectation is that the Release Reviews will be completed the week of September 12th, 2022. Even though it took us longer than anticipated, the release review ballots are either completed or in progress.

Quick reminder of the Jakarta EE Specification Process we are using for releasing the specifications.

Compatible Product used WildFly 27.0.0.Alpha1 (SE 17) for ratification of the Jakarta EE Core Profile 10, and we already have another certification for Payara Server Community 6.2022.1.Alpha3! For the ratification of Jakarta EE Web Profile and Platform it was Eclipse GlassFish 7.0 M8. 


by Tanja Obradovic at September 06, 2022 05:37 PM

OpenJDK-Insider packt aus! | Mein Erfahrungsbericht als Contributor | Head Crashing Informatics 60

by Markus Karg at September 03, 2022 03:00 PM

Schockierend! In diesem exklusiven #Undercover-Tatsachenbericht packe ich schonungslos aus, wie unglaublich schlimm es mir als #JRE-Contributor im #OpenJDK-Team ergangen ist. Die nackte Wahrheit, ungeschminkt und unverblümt! Das definitive MUST-SEE für jeden, der Contributor bei OpenJDK werden möchte! 😉

Bitte nehmt den reißerischen Aufmacher nicht allzu ernst: Ich nehme damit natürlich nur den allgemeinen Trend vieler Youtube-Autoren auf die Schippe, Videos maßlos übertrieben zu betiteln, um mehr Klicks zu erhaschen (“Clickbait”). Bitte gesteht mir diesen Seitenhieb auf die Social-Media-Community zu und nehmt es mit Humor! 😉

Nichtsdestotrotz: Die Mitarbeit an #OpenJDK hat meine Nerven und meine Geduld tatsächlich in bislang noch nicht gekanntem Maße belastet. Nach 20 Jahren als Committer und Contributor in vielen #OpenSource-Projekten war es eine ganz neue Erfahrung, und hat mich doch sehr überrascht. Mehr sei nicht verraten, schaut es Euch einfach an, und bildet Euch Euere eigene Meinung.

Mein Fazit sei schon verraten: Trotz allem Streit und allen Widrigkeiten macht Open Source Spaß und Sinn, und ich kann nur jedem Java-Profi raten, sich an OpenJDK zu beteiligen, denn nur durch die Mitarbeit von uns allen kommt Java voran und kann seine technologische Überlegenheit langfristig bewahren!

Mein besonderer Dank an geht Alan Bateman, Brian Burkhalter und Lance Andersen von Oracle, dass ich diese unschätzbar wertvolle Erfahrung machen durfte, mit wirklich hochkarätigen Java-Insidern in diesem Projekt professionell zusammenzuarbeiten, und dass sie meine Contribution unterstützt und nach mehr als sechs Monaten nervenaufreißender Diskussion in OpenJDK aufgenommen haben. Danke auch an die vielen anderen, die ich an dieser Stelle leider nicht nennen darf, die mir mit Rat und Tat durch diese schwere Zeit geholfen und mich regelmäßig vor dem Aufgeben bewahrt haben! Dank Euerer Unterstützung ist die File I/O in Java nun deutlich schneller!

Wenn Dir dieses Video gefällt, dann gib ihm bitte einen Daumen hoch, empfehle es weiter, abonniere meinen Kanal, oder werden mein Unterstützer https://www.patreon.com/mkarg. Danke! 🙂


by Markus Karg at September 03, 2022 03:00 PM

Welcome OmniFish to Jakarta EE Working Group!

by Tanja Obradovic at August 19, 2022 12:51 PM

We are super happy to announce that OmniFish is a member of the Jakarta EE WG! Our Working Group is continuously growing and seeing new companies being created around runtimes like GlassFish. This is very exciting, and is a testament to the importance of this technology. 

We are certainly familiar with the OmniFish team, so we can welcome them personally as well. A warm welcome and all the best to the OmniFish team: Arjan, David, Ondro, and Bauke!

You can find more about OmniFish here: https://omnifish.ee/about-us/


by Tanja Obradovic at August 19, 2022 12:51 PM

Getting started with JSF 4.0 on WildFly 27

by F.Marchioni at August 14, 2022 04:40 PM

This article contains a preview of Jakarta Faces 4.0 which is an MVC framework for building user interface with Jakarta EE 10. To get started with Jakarta EE 10, you need to download the latest release of WildFly 27 which you can use to preview Jakarta EE 10 features. At the time of writing, the ... Read more

The post Getting started with JSF 4.0 on WildFly 27 appeared first on Mastertheboss.


by F.Marchioni at August 14, 2022 04:40 PM

Jersey 3.1.0 – Incompatibilities and changes

by Jan at July 22, 2022 05:35 PM

This article discusses backward-incompatible changes in Jersey 3.1.0. While Jersey tries to minimize these incompatible changes, the changes are forced by the Platform Specification Project, API project, security reasons, or an unstoppable evolution. Jersey 3.1.0 drops compatibility with JDK 8. … Continue reading

by Jan at July 22, 2022 05:35 PM

Java Reflections unit-testing

by Vladimir Bychkov at July 13, 2022 09:06 PM

How make java code with reflections more stable? Unit tests can help with this problem. This article introduces annotations @CheckConstructor, @CheckField, @CheckMethod to create so unit tests automatically

by Vladimir Bychkov at July 13, 2022 09:06 PM

The Power of Enum – Take advantage of it to make your code more readable and efficient

by otaviojava at July 06, 2022 06:51 AM

Like any other language, Java has the enum feature that allows us to enumerate items. It is helpful to list delimited items in your code, such as the seasons. And we can go beyond it with Java! It permits clean code design. Indeed, we can apply several patterns such as VO from DDD, Singleton, and […]

by otaviojava at July 06, 2022 06:51 AM

Java EE - Jakarta EE Initializr

May 05, 2022 02:23 PM

Getting started with Jakarta EE just became even easier!

Get started

Hot new Update!

Moved from the Apache 2 license to the Eclipse Public License v2 for the newest version of the archetype as described below.
As a start for a possible collaboration with the Eclipse start project.

New Archetype with JakartaEE 9

JakartaEE 9 + Payara 5.2022.2 + MicroProfile 4.1 running on Java 17

  • And the docker image is also ready for x86_64 (amd64) AND aarch64 (arm64/v8) architectures!

May 05, 2022 02:23 PM

JavaEE 8 + Payara 5 + Microprofile 2.1 + Docker In about a minute

March 19, 2022 08:17 AM

Thin Wars to the rescue

It can be really easy to start on your JavaEE / JakartaEE application. It’ll take you about a minute…

In this minute you will get a project with:

  • JavaEE 8
  • MicroProfile 2.1
  • Preconfigured Payara 5 Full server docker container - ivonet/payara:5.184
  • Maven essential setup
  • Run and build scripts for all of this

The minute has started…

Enter the code below in a terminal were you want to create your project and press enter

1
2
3
4
mvn archetype:generate \
-DarchetypeGroupId=nl.ivonet \
-DarchetypeArtifactId=jakartaee8-payara-microprofile-archetype \
-DarchetypeVersion=1.0 -U

The first time you run this command, it will take just a bit more time as it will
download everything needed from the maven central repository.

you will be asked these questions:

1
2
3
4
5
Define value for property 'groupId': com.example
Define value for property 'artifactId': helloworld
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.example: :
Define value for property 'docker-hub-name': example

Just follow the instructions and your project will be created:

1
2
cd helloworld
./run

This will start the project in a docker container.
The docker container will be downloaded the first time and that might take more than the minute depending
on the speed of your internet connection.
After the first time it will only take seconds.

Now go to http://localhost:8080//rest/example and you will have a working
example HelloWorld application.

Done 😄

After burner

Now you can load it into your favorite IDE and start building your own stuff.
Don’t forget to read the README.md of the project to learn more about the available commands.

Have fun.

Links


March 19, 2022 08:17 AM

FOSDEM 2022 Conference Report

by Reza Rahman at February 21, 2022 12:24 AM

FOSDEM took place February 5-6. The European based event is one of the most significant gatherings worldwide focused on all things Open Source. Named the “Friends of OpenJDK”, in recent years the event has added a devroom/track dedicated to Java. The effort is lead by my friend and former colleague Geertjan Wielenga. Due to the pandemic, the 2022 event was virtual once again. I delivered a couple of talks on Jakarta EE as well as Diversity & Inclusion.

Fundamentals of Diversity & Inclusion for Technologists

I opened the second day of the conference with my newest talk titled “Fundamentals of Diversity and Inclusion for Technologists”. I believe this is an overdue and critically important subject. I am very grateful to FOSDEM for accepting the talk. The reality for our industry remains that many people either have not yet started or are at the very beginning of their Diversity & Inclusion journey. This talk aims to start the conversation in earnest by explaining the basics. Concepts covered include unconscious bias, privilege, equity, allyship, covering and microaggressions. I punctuate the topic with experiences from my own life and examples relevant to technologists. The slides for the talk are available on SpeakerDeck. The video for the talk is now posted on YouTube.

Jakarta EE – Present and Future

Later the same day, I delivered my fairly popular talk – “Jakarta EE – Present and Future”. The talk is essentially a state of the union for Jakarta EE. It covers a little bit of history, context, Jakarta EE 8, Jakarta EE 9/9.1 as well as what’s ahead for Jakarta EE 10. One key component of the talk is the importance and ways of direct developer contributions into Jakarta EE, if needed with help from the Jakarta EE Ambassadors. Jakarta EE 10 and the Jakarta Core Profile should bring an important set of changes including to CDI, Jakarta REST, Concurrency, Security, Faces, Batch and Configuration. The slides for the talk are available on SpeakerDeck. The video for the talk is now posted on YouTube.

I am very happy to have had the opportunity to speak at FOSDEM. I hope to contribute again in the future.


by Reza Rahman at February 21, 2022 12:24 AM

Making Readable Code With Dependency Injection and Jakarta CDI

by otaviojava at January 18, 2022 03:53 PM

Learn more about dependency injection with Jakarta CDI and enhance the effectiveness and readability of your code. Link: https://dzone.com/articles/making-readable-code-with-dependency-injection-and-jakarta-cdi

by otaviojava at January 18, 2022 03:53 PM

JConf Peru 2021 Conference Report

by Reza Rahman at January 01, 2022 09:31 PM

JConf Peru 2021 took place November 27th. This was the third time the event was held and due to the pandemic, the 2021 event was virtual and free. I am very proud to have participated as an invited speaker – the JConf series is an admirable effort by the Spanish speaking Java community to hold world-class events. My friend and Peru JUG leader Jose Diaz and his wife Miryan Ramirez have worked hard to make JConf Peru a reality. Jakarta EE had a strong presence at the event including talks on Quarkus and TomEE. I delivered three talks at the conference focused on Jakarta EE and Azure.

Powering Java on Azure with Open Liberty and OpenShift

Early in the morning I delivered my slide free talk titled “Powering Java on Azure with Open Liberty and OpenShift”. The material covers the key work Microsoft and IBM is doing to enable Jakarta EE, MicroProfile, Open Liberty and OpenShift on Azure. I demo in real time how to stand up an OpenShift cluster on Azure quickly and deploy a realistic Java EE/Jakarta EE/MicroProfile application that integrates with some services on the cloud such as a database. The essential material for the talk is available on the Microsoft documentation site as a how-to guide. A recording of the talk is now available on YouTube.

Effective Kubernetes for Jakarta EE and MicroProfile Developers

Towards mid-day, I delivered another entirely slide-free talk – “Effective Kubernetes for Jakarta EE and MicroProfile Developers”. The talk covers some of the key things Jakarta EE and MicroProfile developers need to know while using Kubernetes. This includes:

  • How Kubernetes primitives (such as deployments, services and ingress controllers) align with application server administration, clustering, auto-scaling, auto-discovery, and load-balancing.
  • How to add self-healing capabilities using Kubernetes probes and monitoring with open source tools like Prometheus/Grafana.
  • How Kubernetes can be extended using Operators to effectively manage application server clusters.
  • How the CI/CD pipeline of your application can be adapted to Kubernetes.

A recording of the talk is now available on YouTube.

All the material for the talk is available in self-paced workshop format on GitHub. The material will take you about a day to complete end-to-end (please reach out if you need any help).

Why Jakarta EE Developers are First-Class Citizens on Azure

I wrapped up the conference by delivering my talk titled “Why Jakarta EE Developers are First-Class Citizens on Azure”. This talk covers all the work Microsoft is doing by partnering with companies like Oracle, IBM and Red Hat to support Jakarta EE developers on Azure. This includes fully enabling runtimes such as WebLogic, WebSphere Traditional, WebSphere Liberty, Open Liberty and JBoss EAP on virtual machines, the Azure Kubernetes Service (AKS) and App Service (the premier PaaS platform for Azure). I also cover important work such as supporting JMS in Azure Service Bus as a well as the Jakarta EE on Azure roadmap.

There is a brief end-to-end demo that is part of the talk. You can run the demo yourself using step-by-step instructions available on GitHub to get a feel for how the Jakarta EE on Azure experience looks like (please reach out if you need help). The slides for the talk are available on Speaker Deck. The video for the talk is now posted on YouTube.

It is worth reminding that myself and my team are always ready to work closely with Java/Jakarta EE developers on Azure migrations – completely for free. To take advantage of this, you simply need to fill this survey out or reach out to me directly.

Beautiful Peru

Peru is a country rich in heritage and natural beauty. It is one of the six cradles of civilization and the center of the mighty Inca entire. I am proud to say I got to see a bit of this amazing country as part of my brief trip for the first JConf Peru. Just check out the album below of photos I took (click this link to view the album if the embedded slideshow is not working)!

All in all, I am happy to have had the opportunity to speak at JConf Peru again. I am very glad the event continued in virtual format despite the pandemic. I hope to speak there again and hopefully visit beautiful Peru again in the future.


by Reza Rahman at January 01, 2022 09:31 PM

Infinispan Apache Log4j 2 CVE-2021-44228 vulnerability

December 12, 2021 10:00 PM

Infinispan 10+ uses Log4j version 2.0+ and can be affected by vulnerability CVE-2021-44228, which has a 10.0 CVSS score. The first fixed Log4j version is 2.15.0.
So, until official patch is coming, - you can update used logger version to the latest in few simple steps

wget https://downloads.apache.org/logging/log4j/2.15.0/apache-log4j-2.15.0-bin.zip
unzip apache-log4j-2.15.0-bin.zip

cd /opt/infinispan-server-10.1.8.Final/lib/

rm log4j-*.jar
cp ~/Downloads/apache-log4j-2.15.0-bin/log4j-api-2.15.0.jar ./
cp ~/Downloads/apache-log4j-2.15.0-bin/log4j-core-2.15.0.jar ./
cp ~/Downloads/apache-log4j-2.15.0-bin/log4j-jul-2.15.0.jar ./
cp ~/Downloads/apache-log4j-2.15.0-bin/log4j-slf4j-impl-2.15.0.jar ./

Please, note - patch above is not official, but according to initial tests it works with no issues


December 12, 2021 10:00 PM

JPA query methods: influence on performance

by Vladimir Bychkov at November 18, 2021 07:22 AM

Specification JPA 2.2/Jakarta JPA 3.0 provides for several methods to select data from database. In this article we research how these methods affect on performance

by Vladimir Bychkov at November 18, 2021 07:22 AM

Eclipse Jetty Servlet Survey

by jesse at October 27, 2021 01:25 PM

This short 5-minute survey is being presented to the Eclipse Jetty user community to validate conjecture the Jetty developers have for how users will leverage JakartaEE servlets and the Jetty project. We have some features we are gauging interest in

by jesse at October 27, 2021 01:25 PM

Custom Identity Store with Jakarta Security in TomEE

by Jean-Louis Monteiro at September 30, 2021 11:42 AM

In the previous post, we saw how to use the built-in ‘tomcat-users.xml’ identity store with Apache TomEE. While this identity store is inherited from Tomcat and integrated into Jakarta Security implementation in TomEE, this is usually good for development or simple deployments, but may appear too simple or restrictive for production environments. 

This blog will focus on how to implement your own identity store. TomEE can use LDAP or JDBC identity stores out of the box. We will try them out next time.

Let’s say you have your own file store or your own data store like an in-memory data grid, then you will need to implement your own identity store.

What is an identity store?

An identity store is a database or a directory (store) of identity information about a population of users that includes an application’s callers.

In essence, an identity store contains all information such as caller name, groups or roles, and required information to validate a caller’s credentials.

How to implement my own identity store?

This is actually fairly simple with Jakarta Security. The only thing you need to do is create an implementation of `jakarta.security.enterprise.identitystore.IdentityStore`. All methods in the interface have default implementations. So you only have to implement what you need.

public interface IdentityStore {
   Set DEFAULT_VALIDATION_TYPES = EnumSet.of(VALIDATE, PROVIDE_GROUPS);

   default CredentialValidationResult validate(Credential credential) {
   }

   default Set getCallerGroups(CredentialValidationResult validationResult) {
   }

   default int priority() {
   }

   default Set validationTypes() {
   }

   enum ValidationType {
       VALIDATE, PROVIDE_GROUPS
   }
}

By default, an identity store is used for both validating user credentials and providing groups/roles for the authenticated user. Depending on what #validationTypes() will return, you will have to implement #validate(…) and/or #getCallerGroups(…)

#getCallerGroups(…) will receive the result of #valide(…). Let’s look at a very simple example:

@ApplicationScoped
public class TestIdentityStore implements IdentityStore {

   public CredentialValidationResult validate(Credential credential) {

       if (!(credential instanceof UsernamePasswordCredential)) {
           return INVALID_RESULT;
       }

       final UsernamePasswordCredential usernamePasswordCredential = (UsernamePasswordCredential) credential;
       if (usernamePasswordCredential.compareTo("jon", "doe")) {
           return new CredentialValidationResult("jon", new HashSet<>(asList("foo", "bar")));
       }

       if (usernamePasswordCredential.compareTo("iron", "man")) {
           return new CredentialValidationResult("iron", new HashSet<>(Collections.singletonList("avengers")));
       }

       return INVALID_RESULT;
   }

}

In this simple example, the identity store is hardcoded. Basically, it knows only 2 users, one of them has some roles, while the other has another set of roles.

You can easily extend this example and query a local file, or an in-memory data grid if you need. Or use JPA to access your relational database.

IMPORTANT: for TomEE to pick it up and use it in your application, the identity store must be a CDI bean.

The complete and runnable example is available under https://github.com/apache/tomee/tree/master/examples/security-custom-identitystore

The post Custom Identity Store with Jakarta Security in TomEE appeared first on Tomitribe.


by Jean-Louis Monteiro at September 30, 2021 11:42 AM

Book Review: Practical Cloud-Native Java Development with MicroProfile

September 24, 2021 12:00 AM

Practical Cloud-Native Java Development with MicroProfile cover

General information

  • Pages: 403
  • Published by: Packt
  • Release date: Aug 2021

Disclaimer: I received this book as a collaboration with Packt and one of the authors (Thanks Emily!)

A book about Microservices for the Java Enterprise-shops

Year after year many enterprise companies are struggling to embrace Cloud Native practices that we tend to denominate as Microservices, however Microservices is a metapattern that needs to follow a well defined approach, like:

  • (We aim for) reactive systems
  • (Hence we need a methodology like) 12 Cloud Native factors
  • (Implementing) well-known design patterns
  • (Dividing the system by using) Domain Driven Design
  • (Implementing microservices via) Microservices chassis and/or service mesh
  • (Achieving deployments by) Containers orchestration

Many of these concepts require a considerable amount of context, but some books, tutorials, conferences and YouTube videos tend to focus on specific niche information, making difficult to have a "cold start" in the microservices space if you have been developing regular/monolithic software. For me, that's the best thing about this book, it provides a holistic view to understand microservices with Java and MicroProfile for "cold starter developers".

About the book

Using a software architect perspective, MicroProfile could be defined as a set of specifications (APIs) that many microservices chassis implement in order to solve common microservices problems through patterns, lessons learned from well known Java libraries, and proposals for collaboration between Java Enterprise vendors.

Subsequently if you think that it sounds a lot like Java EE, that's right, it's the same spirit but on the microservices space with participation for many vendors, including vendors from the Java EE space -e.g. Red Hat, IBM, Apache, Payara-.

The main value of this book is the willingness to go beyond the APIs, providing four structured sections that have different writing styles, for instance:

  1. Section 1: Cloud Native Applications - Written as a didactical resource to learn fundamentals of distributed systems with Cloud Native approach
  2. Section 2: MicroProfile Deep Dive - Written as a reference book with code snippets to understand the motivation, functionality and specific details in MicroProfile APIs and the relation between these APIs and common Microservices patterns -e.g. Remote procedure invocation, Health Check APIs, Externalized configuration-
  3. Section 3: End-to-End Project Using MicroProfile - Written as a narrative workshop with source code already available, to understand the development and deployment process of Cloud Native applications with MicroProfile
  4. Section 4: The standalone specifications - Written as a reference book with code snippets, it describes the development of newer specs that could be included in the future under MicroProfile's umbrella

First section

This was by far my favorite section. This section presents a well-balanced overview about Cloud Native practices like:

  • Cloud Native definition
  • The role of microservices and the differences with monoliths and FaaS
  • Data consistency with event sourcing
  • Best practices
  • The role of MicroProfile

I enjoyed this section because my current role is to coach or act as a software architect at different companies, hence this is good material to explain the whole panorama to my coworkers and/or use this book as a quick reference.

My only concern with this section is about the final chapter, this chapter presents an application called IBM Stock Trader that (as you probably guess) IBM uses to demonstrate these concepts using MicroProfile with OpenLiberty. The chapter by itself presents an application that combines data sources, front/ends, Kubernetes; however the application would be useful only on Section 3 (at least that was my perception). Hence you will be going back to this section once you're executing the workshop.

Second section

This section divides the MicroProfile APIs in three levels, the division actually makes a lot of sense but was evident to me only during this review:

  1. The base APIs to create microservices (JAX-RS, CDI, JSON-P, JSON-B, Rest Client)
  2. Enhancing microservices (Config, Fault Tolerance, OpenAPI, JWT)
  3. Observing microservices (Health, Metrics, Tracing)

Additionally, section also describes the need for Docker and Kubernetes and how other common approaches -e.g. Service mesh- overlap with Microservice Chassis functionality.

Currently I'm a MicroProfile user, hence I knew most of the APIs, however I liked the actual description of the pattern/need that motivated the inclusion of the APIs, and the description could be useful for newcomers, along with the code snippets also available on GitHub.

If you're a Java/Jakarta EE developer you will find the CDI section a little bit superficial, indeed CDI by itself deserves a whole book/fascicle but this chapter gives the basics to start the development process.

Third section

This section switches the writing style to a workshop style. The first chapter is entirely focused on how to compile the sample microservices, how to fulfill the technical requirements and which MicroProfile APIs are used on every microservice.

You must notice that this is not a Java programming workshop, it's a Cloud Native workshop with ready to deploy microservices, hence the step by step guide is about compilation with Maven, Docker containers, scaling with Kubernetes, operators in Openshift, etc.

You could explore and change the source code if you wish, but the section is written in a "descriptive" way assuming the samples existence.

Fourth section

This section is pretty similar to the second section in the reference book style, hence it also describes the pattern/need that motivated the discussion of the API and code snippets. The main focus of this section is GraphQL, Reactive Approaches and distributed transactions with LRA.

This section will probably change in future editions of the book because at the time of publishing the Cloud Native Container Foundation revealed that some initiatives about observability will be integrated in the OpenTelemetry project and MicroProfile it's discussing their future approach.

Things that could be improved

As any review this is the most difficult section to write, but I think that a second edition should:

  • Extend the CDI section due its foundational status
  • Switch the order of the Stock Tracer presentation
  • Extend the data consistency discussión -e.g. CQRS, Event Sourcing-, hopefully with advances from LRA

The last item is mostly a wish since I'm always in the need for better ways to integrate this common practices with buses like Kafka or Camel using MicroProfile. I know that some implementations -e.g. Helidon, Quarkus- already have extensions for Kafka or Camel, but the data consistency is an entire discussion about patterns, tools and best practices.

Who should read this book?

  • Java developers with strong SE foundations and familiarity with the enterprise space (Spring/Java EE)

September 24, 2021 12:00 AM

GlassFish & Payara Auto-Clustering: Running Jakarta EE Highly-Available Applications in the Cloud

by Tetiana Fydorenchyk at September 21, 2021 11:19 AM

Explore automatic clusterization of Glassfish and Payara in one click with no manual configurations required. The main advantage of this solution is in automatic interconnection of multiple application server instances upon the application topology change, which implements the commonly used clustering configuration. Find out how to get auto-clustered highly available Java servers up and running in the cloud in a matter of minutes.

by Tetiana Fydorenchyk at September 21, 2021 11:19 AM

#156 Bash, Apple and EJB, TomEE, Geronimo and Jakarta EE

by David Blevins at September 14, 2021 02:07 PM

New podcast episode with Adam Bien & David Blevins.  Apple and EJB, @ApacheTomEE, @tomitribe, @JakartaEE, the benefits of code generation with bash, and over-engineering”–the 156th http://airhacks.fm

The post #156 Bash, Apple and EJB, TomEE, Geronimo and Jakarta EE appeared first on Tomitribe.


by David Blevins at September 14, 2021 02:07 PM

Tomcat and TomEE Clustering Automation

by Tetiana Fydorenchyk at August 18, 2021 11:29 AM

Explore the tips on how to install automatically clustered Tomcat and TomEE servers to get a highly available solution that can efficiently serve a large number of users, process a lot of traffic, and be reliable.
Tomcat TomEE Automatic Clustering

by Tetiana Fydorenchyk at August 18, 2021 11:29 AM

Jakarta Community Acceptance Testing (JCAT)

by javaeeguardian at July 28, 2021 05:41 AM

Today the Jakarta EE Ambassadors are announcing the start of the Jakarta EE Community Acceptance (JCAT) Testing initiative. The purpose of this initiative is to test Jakarta EE 9/9.1 implementations testing using your code and/or applications. Although Jakarta EE is extensively tested by the TCK, container specific tests, and QA, the purpose of JCAT is for developers to test the implementations.

Jakarta EE 9/9.1 did not introduce any new features. In Jakarta EE 9 the APIs changed from javax to jakarta. Jakarta EE 9.1 raised the supported floor to Java 11 for compatible implementations. So what are we testing?

  • Testing individual spec implementations standalone with the new namespace. 
  • Deploying existing Java EE/Jakarta EE applications to EE 9/9.1.
  • Converting Java EE/Jakarta EE applications to the new namespace.
  • Running applications on Java 11 (Jakarta EE 9.1)

Participating in this initiative is easy:

  1. Download a Jakarta EE implementation:
    1. Java 8 / Jakarta EE 9 Containers
    2. Java 11+ / Jakarta EE 9.1 Containers
  2. Deploy code:
    1. Port or run your existing Jakarta EE application
    2. Test out a feature using a starter template

To join this initiative, please take a moment to fill-out the form:

 Sign-up Form 

To submit results or feedback on your experiences with Jakarta EE 9/9.1:

  Jakarta EE 9 / 9.1 Feedback Form

Resources:

Start Date: July 28, 2021

End Date: December 31st, 2021


by javaeeguardian at July 28, 2021 05:41 AM

Your Voice Matters: Take the Jakarta EE Developer Survey

by dmitrykornilov at April 17, 2021 11:36 AM

The Jakarta EE Developer Survey is in its fourth year and is the industry’s largest open source developer survey. It’s open until April 30, 2021. I am encouraging you to add your voice. Why should you do it? Because Jakarta EE Working Group needs your feedback. We need to know the challenges you facing and suggestions you have about how to make Jakarta EE better.

Last year’s edition surveyed developers to gain on-the-ground understanding and insights into how Jakarta solutions are being built, as well as identifying developers’ top choices for architectures, technologies, and tools. The 2021 Jakarta EE Developer Survey is your chance to influence the direction of the Jakarta EE Working Group’s approach to cloud native enterprise Java.

The results from the 2021 survey will give software vendors, service providers, enterprises, and individual developers in the Jakarta ecosystem updated information about Jakarta solutions and service development trends and what they mean for their strategies and businesses. Additionally, the survey results also help the Jakarta community at the Eclipse Foundation better understand the top industry focus areas and priorities for future project releases.

A full report from based on the survey results will be made available to all participants.

The survey takes less than 10 minutes to complete. We look forward to your input. Take the survey now!


by dmitrykornilov at April 17, 2021 11:36 AM

Less is More? Evolving the Servlet API!

by gregw at April 13, 2021 06:19 AM

With the release of the Servlet API 5.0 as part of Eclipse Jakarta EE 9.0 the standardization process has completed its move from the now-defunct Java Community Process (JCP) to being fully open source at the Eclipse Foundation, including the

by gregw at April 13, 2021 06:19 AM

Undertow AJP balancer. UT005028: Proxy request failed: java.nio.BufferOverflowException

April 02, 2021 09:00 PM

Wildfly provides great out of the box load balancing support by Undertow and modcluster subsystems
Unfortunately, in case HTTP headers size is huge enough (close to 16K), which is so actual in JWT era - pity error happened:

ERROR [io.undertow.proxy] (default I/O-10) UT005028: Proxy request to /ee-jax-rs-examples/clusterdemo/serverinfo failed: java.io.IOException: java.nio.BufferOverflowException
 at io.undertow.server.handlers.proxy.ProxyHandler$HTTPTrailerChannelListener.handleEvent(ProxyHandler.java:771)
 at io.undertow.server.handlers.proxy.ProxyHandler$ProxyAction$1.completed(ProxyHandler.java:646)
 at io.undertow.server.handlers.proxy.ProxyHandler$ProxyAction$1.completed(ProxyHandler.java:561)
 at io.undertow.client.ajp.AjpClientExchange.invokeReadReadyCallback(AjpClientExchange.java:203)
 at io.undertow.client.ajp.AjpClientConnection.initiateRequest(AjpClientConnection.java:288)
 at io.undertow.client.ajp.AjpClientConnection.sendRequest(AjpClientConnection.java:242)
 at io.undertow.server.handlers.proxy.ProxyHandler$ProxyAction.run(ProxyHandler.java:561)
 at io.undertow.util.SameThreadExecutor.execute(SameThreadExecutor.java:35)
 at io.undertow.server.HttpServerExchange.dispatch(HttpServerExchange.java:815)
...
Caused by: java.nio.BufferOverflowException
 at java.nio.Buffer.nextPutIndex(Buffer.java:521)
 at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:297)
 at io.undertow.protocols.ajp.AjpUtils.putString(AjpUtils.java:52)
 at io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel.createFrameHeaderImpl(AjpClientRequestClientStreamSinkChannel.java:176)
 at io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel.generateSendFrameHeader(AjpClientRequestClientStreamSinkChannel.java:290)
 at io.undertow.protocols.ajp.AjpClientFramePriority.insertFrame(AjpClientFramePriority.java:39)
 at io.undertow.protocols.ajp.AjpClientFramePriority.insertFrame(AjpClientFramePriority.java:32)
 at io.undertow.server.protocol.framed.AbstractFramedChannel.flushSenders(AbstractFramedChannel.java:603)
 at io.undertow.server.protocol.framed.AbstractFramedChannel.flush(AbstractFramedChannel.java:742)
 at io.undertow.server.protocol.framed.AbstractFramedChannel.queueFrame(AbstractFramedChannel.java:735)
 at io.undertow.server.protocol.framed.AbstractFramedStreamSinkChannel.queueFinalFrame(AbstractFramedStreamSinkChannel.java:267)
 at io.undertow.server.protocol.framed.AbstractFramedStreamSinkChannel.shutdownWrites(AbstractFramedStreamSinkChannel.java:244)
 at io.undertow.channels.DetachableStreamSinkChannel.shutdownWrites(DetachableStreamSinkChannel.java:79)
 at io.undertow.server.handlers.proxy.ProxyHandler$HTTPTrailerChannelListener.handleEvent(ProxyHandler.java:754)

The same request directly to backend server works well. Tried to play with ajp-listener and mod-cluster filter "max-*" parameters, but have no luck.

Possible solution here is switch protocol from AJP to HTTP which can be bit less effective, but works well with big headers:

/profile=full-ha/subsystem=modcluster/proxy=default:write-attribute(name=listener, value=default)

April 02, 2021 09:00 PM

Oracle Joins MicroProfile Working Group

by dmitrykornilov at January 08, 2021 06:02 PM

I am very pleased to announce that since the beginning of 2021 Oracle is officially a part of MicroProfile Working Group. 

In Oracle we believe in standards and supporting them in our products. Standards are born in blood, toil, tears, and sweat. Standards are a result of collaboration of experts, vendors, customers and users. Standards bring the advantages of portability between different implementations that make standard-based solutions vendor-neutral.

We created Java EE which was the first enterprise Java standard. We opened it and moved it to the Eclipse Foundation to make its development truly open source and vendor neutral. Now we are joining MicroProfile which in the last few years has become a leading standard for cloud-native solutions.

We’ve been supporting MicroProfile for years before officially joining the Working Group. We created project Helidon which has supported MicroProfile APIs since MicroProfile version 1.1. Contributing to the evolution and supporting new versions of MicroProfile is one of our strategic goals.

I like the community driven and enjoyable approach of creating cloud-native APIs invented by MicroProfile. I believe that our collaboration will be effective and together we will push MicroProfile forward to a higher level.


by dmitrykornilov at January 08, 2021 06:02 PM

A fishing day with Jakarta EE and MicroProfile

by Edwin Derks at December 24, 2020 09:23 AM

Over the years, several implementations of the Jakarta EE and MicroProfile platforms have been developed by vendors. Some implementations are fully compatible with these platforms, others support a subset of specifications from the platforms, or are building on top of these. Implementations are often built as an open-source project and shipped by a vendor as a product for their customers. One of the things I noticed over the years, is that these projects are often named after animals. More particularly, there are currently three Jakarta EE / MicroProfile supporting runtimes available that refer to… fish. The members of this trio in question are:

Product Name Link
Eclipse GlassFish https://glassfish.org
Payara https://www.payara.fish
Piranha https://piranha.cloud

Since they share a common aspect in their product name, does that mean that they have something other in common, or is this just a coincidence? Let’s go over the high-level purpose and product definitions to find that out.

Eclipse GlassFish

If we look at the Jakarta EE compatible products page, Eclipse GlassFish shows up as both a Jakarta EE 8 and Jakarta EE 9 compatible application server. Looking at the history of Eclipse GlassFish, this is not a surprise. Until this project was moved from Oracle to the Eclipse Foundation in 2017, it was the reference implementation application server for Java EE. After moving Java EE to the Eclipse Foundation and rebranding the platform as Jakarta EE, the official concept of a reference implementation has been dropped. Although, technically speaking, Eclipse GlassFish remains the “unofficial” reference implementation of new versions of Jakarta EE. This means that for future versions of Jakarta EE, Eclipse GlassFish can be used to test-drive updates to, or implementation of, new specifications that are going to be supported by Jakarta EE. In addition, speaking hypothetically, if no other vendors would be around to implement Jakarta EE, the Eclipse Foundation would still have its own implementation of Jakarta EE under their own roof. This is important because, without any implementations, the Jakarta EE platform is just a set of specifications that be used to build enterprise applications, but not run them. As a developer, you can easily download Eclipse GlassFish and use this application server to start a project in order to build enterprise applications. However, there are two things noteworthy that you should know:

  • This application server only implements the Jakarta EE platform. It lacks the cloud-native capabilities that the MicroProfile specifications add when compared to other application servers that implement both Jakarta EE and MicroProfile;
  • There is currently no commercial support available for Eclipse GlassFish. If you want to use this application server for your projects in production, that is perfectly fine. However, without such a support contract, in case you run into problems and are in need of a patch or fix, you are at the mercy of the community. You can file an issue in the open-source project or provide a patch there yourself in order to eventually release a new version of Eclipse GlassFish containing the fix.

Payara

Simply put, Payara is a commercially supported project that builds on Eclipse GlassFish while building their own commercial features on top of it. When we look at the Jakarta EE compatible products page, Payara shows up as a Jakarta EE 8 compatible application server. However, since Jakarta EE 9 has been released this month, and having a compatible Eclipse GlassFish application server around the corner, we can expect a Jakarta EE 9 compatible version of Payara shortly. Over the years, Payara has built an ever-growing set of commercial features in their product. These features often aim at cloud-native development. This makes Payara a good fit for running instances in microservices architectures deployed on cloud environments. In addition, the company aims to support the latest LTS releases of Java, even providing support for various JVMs that you can use to run Payara. Speaking of running Payara, you also have the option of using the full-blown application server, or a slimmed down runtime in the form of Payara Micro. In case you are a fan of Uber/Fat JAR’s, you even have the option of generating such artifacts with Payara Micro. In short, as a developer, you can use Payara for building and deploying enterprise applications in modern, cloud-native environments using some of your favorite flavors for packaging and running your applications. A few things noteworthy to mention for Payara are:

  • Payara provides support for migration from another application server to Payara in case you are interested in such a migration;
  • Payara supports both Jakarta EE and MicroProfile in order to make it a fit for running in cloud-native environments;
  • Payara provides several features for optimizing resource consumption of running Payara instances.

Piranha

Although this product references a fish, it is a new kid on the block and doesn’t share any particular existing base for Jakarta EE or MicroProfile. Piranha is not compatible with Jakarta EE or MicroProfile (yet) but supports a large part of the specifications in enterprise applications that you can build and run on Piranha. Like some other newer runtimes on the market that support Jakarta EE and/or MicroProfile specifications, it uses the best breeds of implementations or provides its own. Having that said, what are Piranha’s goals? The product definition states that you can use Piranha to build Jakarta EE and MicroProfile based applications (among other frameworks or libraries), aiming for the smallest runtime possible in order to run them. Ship less, consume less, spend less seems to be the goal, which makes sense in cloud-native environments where spending resources cost money and spending less can be beneficial. When you are interested in using Piranha as a developer, you should know these things:

  • Piranha is brand new and, as far as I know, doesn’t provide commercial support yet. However, if you are in the situation of building a non-mission-critical application from the ground up with cost efficiency in mind, starting off with Piranha should not hurt. With your feedback, you can help shape and mature the product, which can benefit you in the long run;
  • Piranha supports or integrates with other frameworks and libraries that might be a good fit for your project. This even includes GUI’s and testing, so be sure to check these out!

Conclusion

Next to these “fishy” runtimes from the Jakarta EE and MicroProfile ecosystems, there are of course several other runtimes available that you can check and try out in order to see if these are a fit for your project. I’m curious if there will be any future implementations referring to a fish, and what the idea or vision behind the name would be. How would you name your “fishy” runtime? Please reach out to me on my Twitter when you have an idea, and who knows we can start a trend or project that makes it happen.


by Edwin Derks at December 24, 2020 09:23 AM

An introduction to MicroProfile GraphQL

by Jean-François James at November 14, 2020 05:05 PM

If you’re interested in MicroProfile and APIs, please checkout my presentation Boost your APIs with GraphQL. I did it at EclipseCon 2020. Thanks to the organizers for the invitation! The slide deck is on Slideshare. I’ve tried to be high-level and explain how GraphQL differentiates from REST and how easy it is to implement a […]

by Jean-François James at November 14, 2020 05:05 PM

General considerations on updating Enterprise Java projects from Java 8 to Java 11

September 23, 2020 12:00 AM

shell11

The purpose of this article is to consolidate all difficulties and solutions that I've encountered while updating Java EE projects from Java 8 to Java 11 (and beyond). It's a known fact that Java 11 has a lot of new characteristics that are revolutionizing how Java is used to create applications, despite being problematic under certain conditions.

This article is focused on Java/Jakarta EE but it could be used as basis for other enterprise Java frameworks and libraries migrations.

Is it possible to update Java EE/MicroProfile projects from Java 8 to Java 11?

Yes, absolutely. My team has been able to bump at least two mature enterprise applications with more than three years in development, being:

A Management Information System (MIS)

Nabenik MIS

  • Time for migration: 1 week
  • Modules: 9 EJB, 1 WAR, 1 EAR
  • Classes: 671 and counting
  • Code lines: 39480
  • Project's beginning: 2014
  • Original platform: Java 7, Wildfly 8, Java EE 7
  • Current platform: Java 11, Wildfly 17, Jakarta EE 8, MicroProfile 3.0
  • Web client: Angular

Mobile POS and Geo-fence

Medmigo REP

  • Time for migration: 3 week
  • Modules: 5 WAR/MicroServices
  • Classes: 348 and counting
  • Code lines: 17160
  • Project's beginning: 2017
  • Original platform: Java 8, Glassfish 4, Java EE 7
  • Current platform: Java 11, Payara (Micro) 5, Jakarta EE 8, MicroProfile 3.2
  • Web client: Angular

Why should I ever consider migrating to Java 11?

As everything in IT the answer is "It depends . . .". However there are a couple of good reasons to do it:

  1. Reduce attack surface by updating project dependencies proactively
  2. Reduce technical debt and most importantly, prepare your project for the new and dynamic Java world
  3. Take advantage of performance improvements on new JVM versions
  4. Take advantage from improvements of Java as programming language
  5. Sleep better by having a more secure, efficient and quality product

Why Java updates from Java 8 to Java 11 are considered difficult?

From my experience with many teams, because of this:

Changes in Java release cadence

Java Release Cadence

Currently, there are two big branches in JVMs release model:

  • Java LTS: With a fixed lifetime (3 years) for long term support, being Java 11 the latest one
  • Java current: A fast-paced Java version that is available every 6 months over a predictable calendar, being Java 15 the latest (at least at the time of publishing for this article)

The rationale behind this decision is that Java needed dynamism in providing new characteristics to the language, API and JVM, which I really agree.

Nevertheless, it is a know fact that most enterprise frameworks seek and use Java for stability. Consequently, most of these frameworks target Java 11 as "certified" Java Virtual Machine for deployments.

Usage of internal APIs

Java 9

Errata: I fixed and simplified this section following an interesting discussion on reddit :)

Java 9 introduced changes in internal classes that weren't meant for usage outside JVM, preventing/breaking the functionality of popular libraries that made use of these internals -e.g. Hibernate, ASM, Hazelcast- to gain performance.

Hence to avoid it, internal APIs in JDK 9 are inaccessible at compile time (but accesible with --add-exports), remaining accessible if they were in JDK 8 but in a future release they will become inaccessible, in the long run this change will reduce the costs borne by the maintainers of the JDK itself and by the maintainers of libraries and applications that, knowingly or not, make use of these internal APIs.

Finally, during the introduction of JEP-260 internal APIs were classified as critical and non-critical, consequently critical internal APIs for which replacements are introduced in JDK 9 are deprecated in JDK 9 and will be either encapsulated or removed in a future release.

However, you are inside the danger zone if:

  1. Your project compiles against dependencies pre-Java 9 depending on critical internals
  2. You bundle dependencies pre-Java 9 depending on critical internals
  3. You run your applications over a runtime -e.g. Application Servers- that include pre Java 9 transitive dependencies

Any of these situations means that your application has a probability of not being compatible with JVMs above Java 8. At least not without updating your dependencies, which also could uncover breaking changes in library APIs creating mandatory refactors.

Removal of CORBA and Java EE modules from OpenJDK

JEP230

Also during Java 9 release, many Java EE and CORBA modules were marked as deprecated, being effectively removed at Java 11, specifically:

  • java.xml.ws (JAX-WS, plus the related technologies SAAJ and Web Services Metadata)
  • java.xml.bind (JAXB)
  • java.activation (JAF)
  • java.xml.ws.annotation (Common Annotations)
  • java.corba (CORBA)
  • java.transaction (JTA)
  • java.se.ee (Aggregator module for the six modules above)
  • jdk.xml.ws (Tools for JAX-WS)
  • jdk.xml.bind (Tools for JAXB)

As JEP-320 states, many of these modules were included in Java 6 as a convenience to generate/support SOAP Web Services. But these modules eventually took off as independent projects already available at Maven Central. Therefore it is necessary to include these as dependencies if our project implements services with JAX-WS and/or depends on any library/utility that was included previously.

IDEs and application servers

Eclipse

In the same way as libraries, Java IDEs had to catch-up with the introduction of Java 9 at least in three levels:

  1. IDEs as Java programs should be compatible with Java Modules
  2. IDEs should support new Java versions as programming language -i.e. Incremental compilation, linting, text analysis, modules-
  3. IDEs are also basis for an ecosystem of plugins that are developed independently. Hence if plugins have any transitive dependency with issues over JPMS, these also have to be updated

Overall, none of the Java IDEs guaranteed that plugins will work in JVMs above Java 8. Therefore you could possibly run your IDE over Java 11 but a legacy/deprecated plugin could prevent you to run your application.

How do I update?

You must notice that Java 9 launched three years ago, hence the situations previously described are mostly covered. However you should do the following verifications and actions to prevent failures in the process:

  1. Verify server compatibility
  2. Verify if you need a specific JVM due support contracts and conditions
  3. Configure your development environment to support multiple JVMs during the migration process
  4. Verify your IDE compatibility and update
  5. Update Maven and Maven projects
  6. Update dependencies
  7. Include Java/Jakarta EE dependencies
  8. Execute multiple JVMs in production

Verify server compatibility

Tomcat

Mike Luikides from O'Reilly affirms that there are two types of programmers. In one hand we have the low level programmers that create tools as libraries or frameworks, and on the other hand we have developers that use these tools to create experience, products and services.

Java Enterprise is mostly on the second hand, the "productive world" resting in giant's shoulders. That's why you should check first if your runtime or framework already has a version compatible with Java 11, and also if you have the time/decision power to proceed with an update. If not, any other action from this point is useless.

The good news is that most of the popular servers in enterprise Java world are already compatible, like:

If you happen to depend on non compatible runtimes, this is where the road ends unless you support the maintainer to update it.

Verify if you need an specific JVM

FixesJDK15

On a non-technical side, under support contract conditions you could be obligated to use an specific JVM version.

OpenJDK by itself is an open source project receiving contributions from many companies (being Oracle the most active contributor), but nothing prevents any other company to compile, pack and TCK other JVM distribution as demonstrated by Amazon Correto, Azul Zulu, Liberica JDK, etc.

In short, there is software that technically could run over any JVM distribution and version, but the support contract will ask you for a particular version. For instance:

Configure your development environment to support multiple JDKs

Since the jump from Java 8 to Java 11 is mostly an experimentation process, it is a good idea to install multiple JVMs on the development computer, being SDKMan and jEnv the common options:

SDKMan

sdkman

SDKMan is available for Unix-Like environments (Linux, Mac OS, Cygwin, BSD) and as the name suggests, acts as a Java tools package manager.

It helps to install and manage JVM ecosystem tools -e.g. Maven, Gradle, Leiningen- and also multiple JDK installations from different providers.

jEnv

jenv

Also available for Unix-Like environments (Linux, Mac OS, Cygwin, BSD), jEnv is basically a script to manage and switch multiple JVM installations per system, user and shell.

If you happen to install JDKs from different sources -e.g Homebrew, Linux Repo, Oracle Technology Network- it is a good choice.

Finally, if you use Windows the common alternative is to automate the switch using .bat files however I would appreciate any other suggestion since I don't use Windows so often.

Verify your IDE compatibility and update

Please remember that any IDE ecosystem is composed by three levels:

  1. The IDE acting as platform
  2. Programming language support
  3. Plugins to support tools and libraries

After updating your IDE, you should also verify if all of the plugins that make part of your development cycle work fine under Java 11.

Update Maven and Maven projects

maven

Probably the most common choice in Enterprise Java is Maven, and many IDEs use it under the hood or explicitly. Hence, you should update it.

Besides installation, please remember that Maven has a modular architecture and Maven modules version could be forced on any project definition. So, as rule of thumb you should also update these modules in your projects to the latest stable version.

To verify this quickly, you could use versions-maven-plugin:

<plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>versions-maven-plugin</artifactId>
      <version>2.8.1</version>
</plugin>

Which includes a specific goal to verify Maven plugins versions:

mvn versions:display-plugin-updates

mavenversions

After that, you also need to configure Java source and target compatibility, generally this is achieved in two points.

As properties:

<properties>
        ...
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

As configuration on Maven plugins, specially in maven-compiler-plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>11</release>
    </configuration>
</plugin>

Finally, some plugins need to "break" the barriers imposed by Java Modules and Java Platform Teams knows about it. Hence JVM has an argument called illegal-access to allow this, at least during Java 11.

This could be a good idea in plugins like surefire and failsafe which also invoke runtimes that depend on this flag (like Arquillian tests):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.0</version>
    <configuration>
        <argLine>
            --illegal-access=permit
        </argLine>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.22.0</version>
    <configuration>
        <argLine>
            --illegal-access=permit
        </argLine>
    </configuration>
</plugin>

Update project dependencies

As mentioned before, you need to check for compatible versions on your Java dependencies. Sometimes these libraries could introduce breaking changes on each major version -e.g. Flyway- and you should consider a time to refactor this changes.

Again, if you use Maven versions-maven-plugin has a goal to verify dependencies version. The plugin will inform you about available updates.:

mvn versions:display-dependency-updates

mavendependency

In the particular case of Java EE, you already have an advantage. If you depend only on APIs -e.g. Java EE, MicroProfile- and not particular implementations, many of these issues are already solved for you.

Include Java/Jakarta EE dependencies

jakarta

Probably modern REST based services won't need this, however in projects with heavy usage of SOAP and XML marshalling is mandatory to include the Java EE modules removed on Java 11. Otherwise your project won't compile and run.

You must include as dependency:

  • API definition
  • Reference Implementation (if needed)

At this point is also a good idea to evaluate if you could move to Jakarta EE, the evolution of Java EE under Eclipse Foundation.

Jakarta EE 8 is practically Java EE 8 with another name, but it retains package and features compatibility, most of application servers are in the process or already have Jakarta EE certified implementations:

We could swap the Java EE API:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>8.0.1</version>
    <scope>provided</scope>
</dependency>

For Jakarta EE API:

<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version>8.0.0</version>
    <scope>provided</scope>
</dependency>

After that, please include any of these dependencies (if needed):

Java Beans Activation

Java EE

<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>javax.activation-api</artifactId>
    <version>1.2.0</version>
</dependency>

Jakarta EE

<dependency>
    <groupId>jakarta.activation</groupId>
    <artifactId>jakarta.activation-api</artifactId>
    <version>1.2.2</version>
</dependency>

JAXB (Java XML Binding)

Java EE

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>

Jakarta EE

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.3</version>
</dependency>

Implementation

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

JAX-WS

Java EE

<dependency>
    <groupId>javax.xml.ws</groupId>
    <artifactId>jaxws-api</artifactId>
    <version>2.3.1</version>
</dependency>

Jakarta EE

<dependency>
    <groupId>jakarta.xml.ws</groupId>
    <artifactId>jakarta.xml.ws-api</artifactId>
    <version>2.3.3</version>
</dependency>

Implementation (runtime)

<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.3.3</version>
</dependency>

Implementation (standalone)

<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>2.3.2-1</version>
    <type>pom</type>
</dependency>

Java Annotation

Java EE

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

Jakarta EE

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>1.3.5</version>
</dependency>

Java Transaction

Java EE

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.3</version>
</dependency>

Jakarta EE

<dependency>
    <groupId>jakarta.transaction</groupId>
    <artifactId>jakarta.transaction-api</artifactId>
    <version>1.3.3</version>
</dependency>

CORBA

In the particular case of CORBA, I'm aware of its adoption. There is an independent project in eclipse to support CORBA, based on Glassfish CORBA, but this should be investigated further.

Multiple JVMs in production

If everything compiles, tests and executes. You did a successful migration.

Some deployments/environments run multiple application servers over the same Linux installation. If this is your case it is a good idea to install multiple JVMs to allow stepped migrations instead of big bang.

For instance, RHEL based distributions like CentOS, Oracle Linux or Fedora include various JVM versions:

olinux

Most importantly, If you install JVMs outside directly from RPMs(like Oracle HotSpot), Java alternatives will give you support:

hotspot

However on modern deployments probably would be better to use Docker, specially on Windows which also needs .bat script to automate this task. Most of the JVM distributions are also available on Docker Hub:

dockerjava


September 23, 2020 12:00 AM

Setting Up a Jakarta EE Development Environment with SDKMAN, Eclipse IDE and TomEE MicroProfile

July 29, 2020 12:00 AM

What’s up, folks?! So, in this post, I want to show you how to set up a Jakarta EE development in a clean Linux (Ubuntu) installation. We will set up Java and Maven from a version manager tool called SDKMAN, the Eclipse IDE and the TomEE Application Server. SDKMAN First of all, we need to download the Java Development Kit (JDK). Because Java and the Java Virtual Machine (JVM) are specifications we have some implementations for it, like Amazon Correto, OpenJDK, OracleJDK and many others, for this tutorial, we will use the AdoptOpenJDK.

July 29, 2020 12:00 AM

Secure your JAX-RS APIs with MicroProfile JWT

by Jean-François James at July 13, 2020 03:55 PM

In this article, I want to illustrate in a practical way how to secure your JAX-RS APIs with MicroProfile JWT (JSON Web Token). It is illustrated by a GitHub project using Quarkus, Wildfly, Open Liberty and JWTenizr. A basic knowledge of MP JWT is needed and, if you don’t feel comfortable with that, I invite […]

by Jean-François James at July 13, 2020 03:55 PM

Jakarta EE: Multitenancy with JPA on WildFly, Part 1

by Rhuan Henrique Rocha at July 12, 2020 10:49 PM

In this two-part series, I demonstrate two approaches to multitenancy with the Jakarta Persistence API (JPA) running on WildFly. In the first half of this series, you will learn how to implement multitenancy using a database. In the second half, I will introduce you to multitenancy using a schema. I based both examples on JPA and Hibernate.

Because I have focused on implementation examples, I won’t go deeply into the details of multitenancy, though I will start with a brief overview. Note, too, that I assume you are familiar with Java persistence using JPA and Hibernate.

Multitenancy architecture

Multitenancy is an architecture that permits a single application to serve multiple tenants, also known as clients. Although tenants in a multitenancy architecture access the same application, they are securely isolated from each other. Furthermore, each tenant only has access to its own resources. Multitenancy is a common architectural approach for software-as-a-service (SaaS) and cloud computing applications. In general, clients (or tenants) accessing a SaaS are accessing the same application, but each one is isolated from the others and has its own resources.

A multitenant architecture must isolate the data available to each tenant. If there is a problem with one tenant’s data set, it won’t impact the other tenants. In a relational database, we use a database or a schema to isolate each tenant’s data. One way to separate data is to give each tenant access to its own database or schema. Another option, which is available if you are using a relational database with JPA and Hibernate, is to partition a single database for multiple tenants. In this article, I focus on the standalone database and schema options. I won’t demonstrate how to set up a partition.

In a server-based application like WildFly, multitenancy is different from the conventional approach. In this case, the server application works directly with the data source by initiating a connection and preparing the database to be used. The client application does not spend time opening the connection, which improves performance. On the other hand, using Enterprise JavaBeans (EJBs) for container-managed transactions can lead to problems. As an example, the server-based application could do something to generate an error to commit or roll the application back.

Implementation code

Two interfaces are crucial to implementing multitenancy in JPA and Hibernate:

  • MultiTenantConnectionProvider is responsible for connecting tenants to their respective databases and services. We will use this interface and a tenant identifier to switch between databases for different tenants.
  • CurrentTenantIdentifierResolver is responsible for identifying the tenant. We will use this interface to define what is considered a tenant (more about this later). We will also use this interface to provide the correct tenant identifier to MultiTenantConnectionProvider.

In JPA, we configure these interfaces using the persistence.xml file. In the next sections, I’ll show you how to use these two interfaces to create the first three classes we need for our multitenancy architecture: DatabaseMultiTenantProvider, MultiTenantResolver, and DatabaseTenantResolver.

DatabaseMultiTenantProvider

DatabaseMultiTenantProvider is an implementation of the MultiTenantConnectionProvider interface. This class contains logic to switch to the database that matches the given tenant identifier. In WildFly, this means switching to different data sources. The DatabaseMultiTenantProvider class also implements the ServiceRegistryAwareService, which allows us to inject a service during the configuration phase.

Here’s the code for the DatabaseMultiTenantProvider class:

public class DatabaseMultiTenantProvider implements MultiTenantConnectionProvider, ServiceRegistryAwareService{
    private static final long serialVersionUID = 1L;
    private static final String TENANT_SUPPORTED = "DATABASE";
    private DataSource dataSource;
    private String typeTenancy ;

    @Override
    public boolean supportsAggressiveRelease() {
        return false;
    }
    @Override
    public void injectServices(ServiceRegistryImplementor serviceRegistry) {

        typeTenancy = (String) ((ConfigurationService)serviceRegistry
                .getService(ConfigurationService.class))
                .getSettings().get("hibernate.multiTenancy");

        dataSource = (DataSource) ((ConfigurationService)serviceRegistry
                .getService(ConfigurationService.class))
                .getSettings().get("hibernate.connection.datasource");


    }
    @SuppressWarnings("rawtypes")
    @Override
    public boolean isUnwrappableAs(Class clazz) {
        return false;
    }
    @Override
    public <T> T unwrap(Class<T> clazz) {
        return null;
    }
    @Override
    public Connection getAnyConnection() throws SQLException {
        final Connection connection = dataSource.getConnection();
        return connection;

    }
    @Override
    public Connection getConnection(String tenantIdentifier) throws SQLException {

        final Context init;
        //Just use the multi-tenancy if the hibernate.multiTenancy == DATABASE
        if(TENANT_SUPPORTED.equals(typeTenancy)) {
            try {
                init = new InitialContext();
                dataSource = (DataSource) init.lookup("java:/jdbc/" + tenantIdentifier);
            } catch (NamingException e) {
                throw new HibernateException("Error trying to get datasource ['java:/jdbc/" + tenantIdentifier + "']", e);
            }
        }

        return dataSource.getConnection();
    }

    @Override
    public void releaseAnyConnection(Connection connection) throws SQLException {
        connection.close();
    }
    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
        releaseAnyConnection(connection);
    }
}

As you can see, we call the injectServices method to populate the datasource and typeTenancy attributes. We use the datasource attribute to get a connection from the data source, and we use the typeTenancy attribute to find out if the class supports the multiTenancy type. We call the getConnection method to get a data source connection. This method uses the tenant identifier to locate and switch to the correct data source.

MultiTenantResolver

MultiTenantResolver is an abstract class that implements the CurrentTenantIdentifierResolver interface. This class aims to provide a setTenantIdentifier method to all CurrentTenantIdentifierResolver implementations:

public abstract class MultiTenantResolver implements CurrentTenantIdentifierResolver {

    protected String tenantIdentifier;

    public void setTenantIdentifier(String tenantIdentifier) {
        this.tenantIdentifier = tenantIdentifier;
    }
}

This abstract class is simple. We only use it to provide the setTenantIdentifier method.

DatabaseTenantResolver

DatabaseTenantResolver also implements the CurrentTenantIdentifierResolver interface. This class is the concrete class of MultiTenantResolver:

public class DatabaseTenantResolver extends MuiltiTenantResolver {

    private Map<String, String> regionDatasourceMap;

    public DatabaseTenantResolver(){
        regionDatasourceMap = new HashMap();
        regionDatasourceMap.put("default", "MyDataSource");
        regionDatasourceMap.put("america", "AmericaDB");
        regionDatasourceMap.put("europa", "EuropaDB");
        regionDatasourceMap.put("asia", "AsiaDB");
    }

    @Override
    public String resolveCurrentTenantIdentifier() {


        if(this.tenantIdentifier != null
                && regionDatasourceMap.containsKey(this.tenantIdentifier)){
            return regionDatasourceMap.get(this.tenantIdentifier);
        }

        return regionDatasourceMap.get("default");

    }

    @Override
    public boolean validateExistingCurrentSessions() {
        return false;
    }

}

Notice that DatabaseTenantResolver uses a Map to define the correct data source for a given tenant. The tenant, in this case, is a region. Note, too, that this example assumes we have the data sources java:/jdbc/MyDataSource, java:/jdbc/AmericaDB, java:/jdbc/EuropaDB, and java:/jdbc/AsiaDB configured in WildFly.

Configure and define the tenant

Now we need to use the persistence.xml file to configure the tenant:

<persistence>
    <persistence-unit name="jakartaee8">

        <jta-data-source>jdbc/MyDataSource</jta-data-source>
        <properties>
            <property name="javax.persistence.schema-generation.database.action" value="none" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgresPlusDialect"/>
            <property name="hibernate.multiTenancy" value="DATABASE"/>
            <property name="hibernate.tenant_identifier_resolver" value="net.rhuanrocha.dao.multitenancy.DatabaseTenantResolver"/>
            <property name="hibernate.multi_tenant_connection_provider" value="net.rhuanrocha.dao.multitenancy.DatabaseMultiTenantProvider"/>
        </properties>

    </persistence-unit>
</persistence>

Next, we define the tenant in the EntityManagerFactory:

@PersistenceUnit
protected EntityManagerFactory emf;


protected EntityManager getEntityManager(String multitenancyIdentifier){

    final MuiltiTenantResolver tenantResolver = (MuiltiTenantResolver) ((SessionFactoryImplementor) emf).getCurrentTenantIdentifierResolver();
    tenantResolver.setTenantIdentifier(multitenancyIdentifier);

    return emf.createEntityManager();
}

Note that we call the setTenantIdentifier before creating a new instance of EntityManager.

Conclusion

I have presented a simple example of multitenancy in a database using JPA with Hibernate and WildFly. There are many ways to use a database for multitenancy. My main point has been to show you how to implement the CurrentTenantIdentifierResolver and MultiTenantConnectionProvider interfaces. I’ve shown you how to use JPA’s persistence.xml file to configure the required classes based on these interfaces.

Keep in mind that for this example, I have assumed that WildFly manages the data source and connection pool and that EJB handles the container-managed transactions. In the second half of this series, I will provide a similar introduction to multitenancy, but using a schema rather than a database. If you want to go deeper with this example, you can find the complete application code and further instructions on my GitHub repository.


by Rhuan Henrique Rocha at July 12, 2020 10:49 PM

Jakarta EE Cookbook

by Elder Moraes at July 06, 2020 07:19 PM

About one month ago I had the pleasure to announce the release of the second edition of my book, now…

The post Jakarta EE Cookbook appeared first on Elder Moraes.


by Elder Moraes at July 06, 2020 07:19 PM

Workshops: Reactive Apps with Quarkus and OpenShift

by Niklas Heidloff at May 11, 2020 01:19 PM

In the context of cloud-native applications the topic ‘reactive’ becomes more and more important, since more efficient applications can be built and user experiences can be improved. If you want to learn more about reactive functionality in Java applications, read on and try out the sample application and the two new workshops.

Benefits of reactive Applications

In order to demonstrate benefits of reactive applications, I’ve developed a sample application with a web interface that is updated automatically when new data is received rather than pulling for updates. This is more efficient and improves the user experience.

The animation shows how articles can be created via curl commands in the terminal at the bottom. The web application receives a notification and adds the new article to the page.

Another benefit of reactive systems and reactive REST endpoints is efficiency. This scenario describes how to use reactive systems and reactive programming to achieve faster response times. Especially in public clouds where costs depend on CPU, RAM and compute durations this model saves money.

The project contains a sample endpoint which reads data from a database in two different versions, one uses imperative code, the other one reactive code. The reactive stack of this sample provides response times that take less than half of the time compared to the imperative stack: Reactive: 793 ms – Imperative: 1956 ms.

Workshops

I’ve written two workshops which demonstrate and explain how to build reactive functionality with Quarkus and MicroProfile and how to deploy and run it on OpenShift. You can use Red Hat OpenShift on IBM Cloud or you can run OpenShift locally via Code Ready Containers.

The sample used in the workshops leverages heavily Quarkus which is “a Kubernetes Native Java stack […] crafted from the best of breed Java libraries and standards”. Additionally Eclipse MicroProfile, Eclipse Vert.x, Apache Kafka, PostgreSQL, Eclipse OpenJ9 and Kubernetes are used.

Workshop: Reactive Endpoints with Quarkus on OpenShift

This workshop focusses on how to provide reactive REST APIs and how to invoke services reactively. After you have completed this workshop, you’ll understand the following reactive functionality:

  • Reactive REST endpoints via CompletionStage
  • Exception handling in chained reactive invocations
  • Timeouts via CompletableFuture
  • Reactive REST invocations via MicroProfile REST Client

Open Workshop

Workshop: Reactive Messaging with Quarkus on OpenShift

This workshop focusses on how to do messaging with Kafka and MicroProfile. After you have completed this workshop, you’ll understand the following reactive functionality:

  • Sending and receiving Kafka messages via MicroProfile
  • Sending events from microservices to web applications via Server Sent Events
  • Sending in-memory messages via MicroProfile and Vert.x Event Bus

Open Workshop

Next Steps

To learn more, check out the other articles of this blog series:

The post Workshops: Reactive Apps with Quarkus and OpenShift appeared first on Niklas Heidloff.


by Niklas Heidloff at May 11, 2020 01:19 PM

Monitoring REST APIs with Custom JDK Flight Recorder Events

January 29, 2020 02:30 PM

The JDK Flight Recorder (JFR) is an invaluable tool for gaining deep insights into the performance characteristics of Java applications. Open-sourced in JDK 11, JFR provides a low-overhead framework for collecting events from Java applications, the JVM and the operating system.

In this blog post we’re going to explore how custom, application-specific JFR events can be used to monitor a REST API, allowing to track request counts, identify long-running requests and more. We’ll also discuss how the JFR Event Streaming API new in Java 14 can be used to export live events, making them available for monitoring and alerting via tools such as Prometheus and Grafana.


January 29, 2020 02:30 PM

Enforcing Java Record Invariants With Bean Validation

January 20, 2020 04:30 PM

Record types are one of the most awaited features in Java 14; they promise to "provide a compact syntax for declaring classes which are transparent holders for shallowly immutable data". One example where records should be beneficial are data transfer objects (DTOs), as e.g. found in the remoting layer of enterprise applications. Typically, certain rules should be applied to the attributes of such DTO, e.g. in terms of allowed values. The goal of this blog post is to explore how such invariants can be enforced on record types, using annotation-based constraints as provided by the Bean Validation API.

January 20, 2020 04:30 PM

Jakarta EE 8 CRUD API Tutorial using Java 11

by Philip Riecks at January 19, 2020 03:07 PM

As part of the Jakarta EE Quickstart Tutorials on YouTube, I've now created a five-part series to create a Jakarta EE CRUD API. Within the videos, I'm demonstrating how to start using Jakarta EE for your next application. Given the Liberty Maven Plugin and MicroShed Testing, the endpoints are developed using the TDD (Test Driven Development) technique.

The following technologies are used within this short series: Java 11, Jakarta EE 8, Open Liberty, Derby, Flyway, MicroShed Testing & JUnit 5

Part I: Introduction to the application setup

This part covers the following topics:

  • Introduction to the Maven project skeleton
  • Flyway setup for Open Liberty
  • Derby JDBC connection configuration
  • Basic MicroShed Testing setup for TDD

Part II: Developing the endpoint to create entities

This part covers the following topics:

  • First JAX-RS endpoint to create Person entities
  • TDD approach using MicroShed Testing and the Liberty Maven Plugin
  • Store the entities using the EntityManager

Part III: Developing the endpoints to read entities

This part covers the following topics:

  • Develop two JAX-RS endpoints to read entities
  • Read all entities and by its id
  • Handle non-present entities with a different HTTP status code

Part IV: Developing the endpoint to update entities

This part covers the following topics:

  • Develop the JAX-RS endpoint to update entities
  • Update existing entities using HTTP PUT
  • Validate the client payload using Bean Validation

Part V: Developing the endpoint to delete entities

This part covers the following topics:

  • Develop the JAX-RS endpoint to delete entities
  • Enhance the test setup for deterministic and repeatable integration tests
  • Remove the deleted entity from the database

The source code for the Maven CRUD API application is available on GitHub.

For more quickstart tutorials on Jakarta EE, have a look at the overview page on my blog.

Have fun developing Jakarta EE CRUD API applications,

Phil

 

The post Jakarta EE 8 CRUD API Tutorial using Java 11 appeared first on rieckpil.


by Philip Riecks at January 19, 2020 03:07 PM

Deploy a Jakarta EE application to the root context

by Philip Riecks at January 07, 2020 06:24 AM

With the presence of Docker, Kubernetes and cheaper hardware, the deployment model of multiple applications inside one application server has passed. Now, you deploy one Jakarta EE application to one application server. This eliminates the need for different context paths.  You can use the root context / for your Jakarta EE application. With this blog post, you'll learn how to achieve this for each Jakarta EE application server.

The default behavior for Jakarta EE application server

Without any further configuration, most of the Jakarta EE application servers deploy the application to a context path based on the filename of your .war. If you e.g. deploy your my-banking-app.war application, the server will use the context prefix /my-banking-app for your application. All you JAX-RS endpoints, Servlets, .jsp, .xhtml content is then available below this context, e.g /my-banking-app/resources/customers.

This was important in the past, where you deployed multiple applications to one application server. Without the context prefix, the application server wouldn't be able to route the traffic to the correct application.

As of today, the deployment model changed with Docker, Kubernetes and cheaper infrastructure. You usually deploy one .war within one application server running as a Docker container. Given this deployment model, the context prefix is irrelevant. Mapping the application to the root context / is more convenient.

If you configure a reverse proxy or an Ingress controller (in the Kubernetes world), you are happy if you can just route to / instead of remembering the actual context path (error-prone).

Deploying to root context: Payara & Glassfish

As Payara is a fork of Glassfish, the configuration for both is quite similar. The most convenient way for Glassfish is to place a glassfish-web.xml file in the src/main/webapp/WEB-INF folder of your application:

<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN"
  "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
  <context-root>/</context-root>
</glassfish-web-app>

For Payara the filename is payara-web.xml:

<!DOCTYPE payara-web-app PUBLIC "-//Payara.fish//DTD Payara Server 4 Servlet 3.0//EN" "https://raw.githubusercontent.com/payara/Payara-Server-Documentation/master/schemas/payara-web-app_4.dtd">
<payara-web-app>
	<context-root>/</context-root>
</payara-web-app>

Both also support configuring the context path of the application within their admin console. IMHO this less convenient than the .xml file solution.

Deploying to root context: Open Liberty

Open Liberty also parses a proprietary web.xml file within src/main/webapp/WEB-INF: ibm-web-ext.xml

<web-ext
  xmlns="http://websphere.ibm.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
  version="1.0">
  <context-root uri="/"/>
</web-ext>

Furthermore, you can also configure the context of your application within your server.xml:

<server>
  <featureManager>
    <feature>servlet-4.0</feature>
  </featureManager>

  <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

  <webApplication location="app.war" contextRoot="/" name="app"/>
</server>

Deploying to root context: WildFly

WildFly also has two simple ways of configuring the root context for your application. First, you can place a jboss-web.xml within src/main/webapp/WEB-INF:

<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd">
<jboss-web>
  <context-root>/</context-root>
</jboss-web>

Second, while copying your .war file to your Docker container, you can name it ROOT.war:

FROM jboss/wildfly
 ADD target/app.war /opt/jboss/wildfly/standalone/deployments/ROOT.war

For more tips & tricks for each application server, have a look at my cheat sheet.

Have fun deploying your Jakarta EE applications to the root context,

Phil

The post Deploy a Jakarta EE application to the root context appeared first on rieckpil.


by Philip Riecks at January 07, 2020 06:24 AM

Jakarta EE: Creating an Enterprise JavaBeans Timer

by Rhuan Henrique Rocha at December 17, 2019 03:33 AM

Enterprise JavaBeans (EJB) has many interesting and useful features, some of which I will be highlighting in this and upcoming articles. In this article, I’ll show you how to create an EJB timer programmatically and with annotation. Let’s go!

The EJB timer feature allows us to schedule tasks to be executed according a calendar configuration. It is very useful because we can execute scheduled tasks using the power of Jakarta context. When we run tasks based on a timer, we need to answer some questions about concurrency, which node the task was scheduled on (in case of an application in a cluster), what is the action if the task does not execute, and others. When we use the EJB timer we can delegate many of these concerns to Jakarta context and care more about business logic. It is interesting, isn’t it?

Creating an EJB timer programmatically

We can schedule an EJB timer to runs according to a business logic using a programmatic approach. This method can be used when we want a dynamic behavior, according to the parameter values passed to the process. Let’s look at an example of an EJB timer:

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import java.util.logging.Logger;

@Stateless
public class MyTimer {

    private Logger logger = Logger.getLogger(MyTimer.class.getName());
    @Resource
    private SessionContext context;

    public void initTimer(String message){
        context.getTimerService().createTimer(10000, message);
    }

    @Timeout
    public void execute(){
        logger.info("Starting");

        context.getTimerService().getAllTimers().stream().forEach(timer -> logger.info(String.valueOf(timer.getInfo())));
        

        logger.info("Ending");
    }    
}

To schedule this EJB timer, call this method:

@Inject
private MyTimer myTimer;
....
myTimer.initTimer(message);

After passing 10000 milliseconds, the method annotated with @Timeout will be called.

Scheduling an EJB timer using annotation

We can also create an EJB timer that is automatically scheduled to run according to an annotation configuration. Look at this example:

@Singleton
public class MyTimerAutomatic {

    private Logger logger = Logger.getLogger(MyTimerAutomatic.class.getName());

    @Schedule(hour = "*", minute = "*",second = "0,10,20,30,40,50",persistent = false)
    public void execute(){

        logger.info("Automatic timer executing");

    }
}

As you can see, to configure an automatic EJB timer schedule, you can annotate the method using @Schedule and configure the calendar attributes. For example:

@Schedule(hour = "*", minute = "*",second = "0,10,20,30,40,50",persistent = false)

As you can see, the method execute is configured to be called every 10 seconds. You can configure whether the timer is persistent as well.

Conclusion

EJB timer is a good EJB feature that is helpful in solving many problems. Using the EJB timer feature, we can schedule tasks to be executed, thereby delegating some responsibilities to Jakarta context to solve for us. Furthermore, we can create persistent timers, control the concurrent execution, and work with it in a clustered environment.  If you want to see the complete example, visit this repository on GitHub.

This post was released at Developer Red Hat blog and you can see here.

 


by Rhuan Henrique Rocha at December 17, 2019 03:33 AM

Modernizing our GitHub Sync Toolset

November 19, 2019 08:10 PM

I am happy to announce that my team is ready to deploy a new version of our GitHub Sync Toolset on November 26, 2019 from 10:00 to 11:00 am EST.

We are not expecting any disruption of service but it’s possible that some committers may lose write access to their Eclipse project GitHub repositories during this 1 hour maintenance window.

This toolset is responsible for syncronizing Eclipse committers accross all our GitHub repositories and on top of that, this new release will start syncronizing contributors.

In this context, a contributor is a GitHub user with read access to the project GitHub repositories. This new feature will allow committers to assign issues to contributors who currently don’t have write access to the repository. This feature was requested in 2015 via Bug 483563 - Allow assignment of GitHub issues to contributors.

Eclipse Committers are reponsible for maintaining a list of GitHub contributors from their project page on the Eclipse Project Management Infrastructure (PMI).

To become an Eclipse contributor on a GitHub for a project, please make sure to tell us your GitHub Username in your Eclipse account.


November 19, 2019 08:10 PM

Building Microservices with Jakarta EE and MicroProfile @ EclipseCon 2019

by Edwin Derks at November 01, 2019 09:02 AM

This year’s EclipseCon was my second time visiting, and simultaneously speaking at this conference. Aside from all the amazing projects that are active within the Eclipse Foundation, this year’s edition contained a long anticipated present: the release of Jakarta EE 8. Reason enough for me and two colleagues to provide a workshop where attendees could actually get hands-on with Jakarta EE 8 and it’s microservices-enabling cousin: Eclipse MicroProfile.

This workshop focusses not only on the various API’s that are provided by Jakarta EE and MicroProfile, but also on development with the Payara application server and how this all fits in a containerised environment.

The slides of the workshop can be found here:

Of course, we hope to evolve this workshop in order to get hands on with new Jakarta EE and MicroProfile features in the near future. Stay tuned!


by Edwin Derks at November 01, 2019 09:02 AM

A Tool for Jakarta EE Package Renaming in Binaries

by BJ Hargrave (noreply@blogger.com) at October 17, 2019 09:26 PM

In a previous post, I laid out my thinking on how to approach the package renaming problem which the Jakarta EE community now faces. Regardless of whether the community chooses big bang or incremental, there are still existing artifacts in the world using the Java EE package names that the community will need to use together with the new Jakarta EE package names.

Tools are always important to take the drudgery away from developers. So I have put together a tool prototype which can be used to transform binaries such as individual class files and complete JARs and WARs to rename uses of the Java EE package names to their new Jakarta EE package names.

The tools is rule driven which is nice since the Jakarta EE community still needs to define the actual package renames for Jakarta EE 9. The rules also allow the users to control which class files in a JAR/WAR are transformed. Different users may want different rules depending upon their specific needs. And the tool can be used for any package renaming challenge, not just the specific Jakarta EE package renames.

The tools provides an API allowing it to be embedded in a runtime to dynamically transform class files during the class loader definition process. The API also supports transforming JAR files. A CLI is also provided to allow use from the command line. Ultimately, the tool can be packaged as Gradle and Maven plugins to incorporate in a broader tool chain.

Given that the tool is prototype, and there is much work to be done in the Jakarta EE community regarding the package renames, I have started a list of TODOs in the project' issues for known work items.

Please try out the tool and let me know what you think. I am hoping that tooling such as this will ease the community cost of dealing with the package renames in Jakarta EE.

PS. Package renaming in source code is also something the community will need to deal with. But most IDEs are pretty good at this sort of thing, so I think there is probably sufficient tooling in existence for handling the package renames in source code.

by BJ Hargrave (noreply@blogger.com) at October 17, 2019 09:26 PM

Deploying MicroProfile Microservices with Tekton

by Niklas Heidloff at August 08, 2019 02:48 PM

This article describes Tekton, an open-source framework for creating CI/CD systems, and explains how to deploy microservices built with Eclipse MicroProfile on Kubernetes and OpenShift.

What is Tekton?

Kubernetes is the de-facto standard for running cloud-native applications. While Kubernetes is very flexible and powerful, deploying applications is sometimes challenging for developers. That’s why several platforms and tools have evolved that aim to make deployments of applications easier, for example Cloud Foundry’s ‘cf push’ experience, OpenShift’s source to image (S2I), various Maven plugins and different CI/CD systems.

Similarly as Kubernetes has evolved to be the standard for running containers and similarly as Knative is evolving to become the standard for serverless platforms, the goal of Tekton is to become the standard for continuous integration and delivery (CI/CD) platforms.

The biggest companies that are engaged in this project are at this point Google, CloudBees, IBM and Red Hat. Because of its importance the project has been split from Knative which is focussed on scale to zero capabilities.

Tekton comes with a set of custom resources to define and run pipelines:

  • Pipeline: Pipelines can contain several tasks and can be triggered by events or manually
  • Task: Tasks can contain multiple steps. Typical tasks are 1. source to image and 2. deploy via kubectl
  • PipelineRun: This resource is used to trigger pipelines and to pass parameters like location of Dockerfiles to pipelines
  • PipelineResource: This resource is used, for example, to pass links to GitHub repos

MicroProfile Microservice Implementation

I’ve created a simple microservice which is available as open source as part of the cloud-native-starter repo.

The microservice contains the following functionality:

If you want to use this code for your own microservice, remove the three Java files for the REST GET endpoint and rename the service in the pom.xml file and the yaml files.

Setup of the Tekton Pipeline

I’ve created five yaml files that define the pipeline to deploy the sample authors microservice.

1) The file task-source-to-image.yaml defines how to 1. build the image within the Kubernetes cluster and 2. how to push it to a registry.

For building the image kaniko is used, rather than Docker. For application developers this is almost transparent though. As usual images are defined via Dockerfiles. The only difference I ran into is how access rights are handled. For some reason I couldn’t write the ‘server.xml’ file into the ‘/config’ directory. To fix this, I had to manually assign access rights in the Dockerfile first: ‘RUN chmod 777 /config/’.

The source to image task is the first task in the pipeline and has only one step. The screenshot shows a representation of the task in the Tekton dashboard.

2) The file task-deploy-via-kubectl.yaml contains the second task of the pipeline which essentially only runs kubectl commands to deploy the service. Before this can be done, the template yaml file is changed to contain the full image name for the current user and environment.

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: deploy-via-kubectl
spec:
  inputs:
    resources:
      - name: git-source
        type: git
    params:
      - name: pathToDeploymentYamlFile
        description: The path to the yaml file with Deployment resource to deploy within the git source
      ...
  steps:
    - name: update-yaml
      image: alpine
      command: ["sed"]
      args:
        - "-i"
        - "-e"
        - "s;authors:1;${inputs.params.imageUrl}:${inputs.params.imageTag};g"
        - "/workspace/git-source/${inputs.params.pathToContext}/${inputs.params.pathToDeploymentYamlFile}"
    - name: run-kubectl-deployment
      image: lachlanevenson/k8s-kubectl
      command: ["kubectl"]
      args:
        - "apply"
        - "-f"
        - "/workspace/git-source/${inputs.params.pathToContext}/${inputs.params.pathToDeploymentYamlFile}"

3) The file pipeline.yaml basically only defines the order of the two tasks as well as how to pass parameters between the different tasks.

The screenshot shows the pipeline after it has been run. The output of the third and last steps of the second task ‘deploy to cluster’ is displayed.

4) The file resource-git-cloud-native-starter.yaml only contains the address of the GitHub repo.

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: resource-git-cloud-native-starter
spec:
  type: git
  params:
    - name: revision
      value: master
    - name: url
      value: https://github.com/IBM/cloud-native-starter

5) The file pipeline-account.yaml is necessary to define access rights from Tekton to the container registry.

Here are the complete steps to set up the pipeline on the IBM Cloud Kubernetes service. Except of the login capabilities the same instructions should work as well for Kubernetes services on other clouds and the Kubernetes distribution OpenShift.

First get an IBM lite account. It’s free and there is no time restriction. In order to use the Kubernetes service you need to enter your credit card information, but there is a free Kubernetes cluster. After this create a new Kubernetes cluster.

To create the pipeline, invoke these commands:

$ git clone https://github.com/ibm/cloud-native-starter.git
$ cd cloud-native-starter
$ ROOT_FOLDER=$(pwd)
$ REGISTRY_NAMESPACE=<your-namespace>
$ CLUSTER_NAME=<your-cluster-name>
$ cd ${ROOT_FOLDER}/authors-java-jee
$ ibmcloud login -a cloud.ibm.com -r us-south -g default
$ ibmcloud ks cluster-config --cluster $CLUSTER_NAME
$ export <output-from-previous-command>
$ REGISTRY=$(ibmcloud cr info | awk '/Container Registry  /  {print $3}')
$ ibmcloud cr namespace-add $REGISTRY_NAMESPACE
$ kubectl apply -f deployment/tekton/resource-git-cloud-native-starter.yaml 
$ kubectl apply -f deployment/tekton/task-source-to-image.yaml 
$ kubectl apply -f deployment/tekton/task-deploy-via-kubectl.yaml 
$ kubectl apply -f deployment/tekton/pipeline.yaml
$ ibmcloud iam api-key-create tekton -d "tekton" --file tekton.json
$ cat tekton.json | grep apikey 
$ kubectl create secret generic ibm-cr-push-secret --type="kubernetes.io/basic-auth" --from-literal=username=iamapikey --from-literal=password=<your-apikey>
$ kubectl annotate secret ibm-cr-push-secret tekton.dev/docker-0=us.icr.io
$ kubectl apply -f deployment/tekton/pipeline-account.yaml

Execute the Tekton Pipeline

In order to invoke the pipeline, a sixth yaml file pipeline-run-template.yaml is used. As stated above, this file needs to be modified first to contain the exact image name.

The pipeline-run resource is used to define input parameters like the Git repository, location of the Dockerfile, name of the image, etc.

apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
  generateName: pipeline-run-cns-authors-
spec:
  pipelineRef:
    name: pipeline
  resources:
    - name: git-source
      resourceRef:
        name: resource-git-cloud-native-starter
  params:
    - name: pathToContext
      value: "authors-java-jee"
    - name: pathToDeploymentYamlFile
      value: "deployment/deployment.yaml"
    - name: pathToServiceYamlFile
      value: "deployment/service.yaml"
    - name: imageUrl
      value: <ip:port>/<namespace>/authors
    - name: imageTag
      value: "1"
    - name: pathToDockerFile
      value: "DockerfileTekton"
  trigger:
    type: manual
  serviceAccount: pipeline-account

Invoke the following commands to trigger the pipeline and to test the authors service:

$ cd ${ROOT_FOLDER}/authors-java-jee/deployment/tekton
$ REGISTRY=$(ibmcloud cr info | awk '/Container Registry  /  {print $3}')
$ sed "s+<namespace>+$REGISTRY_NAMESPACE+g" pipeline-run-template.yaml > pipeline-run-template.yaml.1
$ sed "s+<ip:port>+$REGISTRY+g" pipeline-run-template.yaml.1 > pipeline-run-template.yaml.2
$ sed "s+<tag>+1+g" pipeline-run-template.yaml.2 > pipeline-run.yaml
$ cd ${ROOT_FOLDER}/authors-java-jee
$ kubectl create -f deployment/tekton/pipeline-run.yaml
$ kubectl describe pipelinerun pipeline-run-cns-authors-<output-from-previous-command>
$ clusterip=$(ibmcloud ks workers --cluster $CLUSTER_NAME | awk '/Ready/ {print $2;exit;}')
$ nodeport=$(kubectl get svc authors --output 'jsonpath={.spec.ports[*].nodePort}')
$ open http://${clusterip}:${nodeport}/openapi/ui/
$ curl -X GET "http://${clusterip}:${nodeport}/api/v1/getauthor?name=Niklas%20Heidloff" -H "accept: application/json"

After running the pipeline you’ll see two Tekton pods and one authors pod in the Kubernetes dashboard.

Try out this sample yourself!

The post Deploying MicroProfile Microservices with Tekton appeared first on Niklas Heidloff.


by Niklas Heidloff at August 08, 2019 02:48 PM

Jakarta EE, A de facto standard in the making

by David R. Heffelfinger at May 28, 2019 10:06 PM

I’ve been involved in Java EE since the very beginning, Having written one of the first ever books on Java EE. My involvement in Java EE / Jakarta EE has been on an education / advocacy role. Having written books, articles, blog posts and given talks in conferences about the technology. I advocate Jakarta EE not because I’m paid to do so, but because I really believe it is a great technology. I’m a firm believer that the fact that Jakarta EE is a standard, with multiple competing implementations, results in very high quality implementations, since Jakarta EE avoids vendor lock-in and encourages competition, benefiting developers.


Oracle’s donation of Java EE to the Eclipse Foundation was well received and celebrated by the Java EE community. Many prominent community members had been advocating for a more open process for Java EE, which is exactly what Jakarta EE, under the stewardship from the Eclipse Foundation provides.


There are some fundamental changes on how Jakarta EE is managed, that differ from Java EE, that benefit the Jakarta EE community greatly.

Fundamental differences between Java EE and Jakarta EE Management


Some of the differences in the way Jakarta EE is managed as opposed to Java EE are that there is no single vendor controlling the technology, there is free access to the TCK and there is no reference implementation.

No single company controls the standard

First and foremost, we no longer have a single company as a steward of Jakarta EE. Instead, we have several companies who have a vested interest in the success of the technology working together to develop the standard. This has the benefit that the technology is not subject to the whims of any one vendor, and, if any of the vendors loses interest in Jakarta EE, others can easily pick up the slack. The fact that there is no single vendor behind the technology makes Jakarta EE very resilient, it is here to stay.

TCK freely accessible

Something those of us involved heavily in Jakarta EE (and Java EE before), take for granted, but that may not be clear to others, is that Jakarta EE is a set of specifications with multiple implementations. Since the APIs are defined in a specification, they don’t change across Jakarta EE implementations, making Jakarta EE compliant code portable across implementations. For example, a Jakarta EE compliant application should run with minimal or no modifications on popular Jakarta EE implementations such as Apache Tomee, Payara, IBM’s OpenLiberty or Red Hat’s Thorntail


One major change that Jakarta EE has against Java EE is the fact that the Technology Compatibility Kit (TCK) is open source and free. The TCK is a set of test to verify that a Jakarta EE implementation is 100% compliant with all Jakarta EE specifications. With Java EE, organizations wanting to create a Java EE implementation, had to pay large sums of money to gain access to the TCK, once their implementation passed all the tests, their implementation was certified as Java EE compatible. The fact that the TCK was not freely accessible became a barrier to innovation, as smaller organizations and open source developers not always had the funds to get access to the TCK. Now that the TCK is freely accessible, the floodgates will open, and we should see a lot more quality implementations of Jakarta EE.

No reference implementation

Another major change between Java EE and Jakarta EE is that Java EE had the concept of a reference implementation. The idea behind having a Java EE reference implementation was to prove that suggested API specifications were actually feasible to implement. Having a reference implementation, however, had a side effect. If the reference implementation implemented something that wasn’t properly defined in the specification, then many developers expected all Java EE implementations to behave the same way, making the reference implementation a de-facto Java EE specification of sorts. Jakarta EE does away with the concept of a reference implementation, and will have multiple compatible implementations instead. The fact that there isn’t a reference implementation in Jakarta EE will result in more complete specifications, as differences in behavior between implementations will bring to light deficiencies in the specifications, these deficiencies can then be addressed by the community.

Conclusion

With multiple organizations with a vested interest in Jakarta EE’s success, a lowered barrier of entry for new Jakarta EE implementations, and better specifications Jakarta EE will become the de-facto standard in server-side Java development.



by David R. Heffelfinger at May 28, 2019 10:06 PM

I am an Incrementalist: Jakarta EE and package renaming

by BJ Hargrave (noreply@blogger.com) at May 17, 2019 05:11 PM


Eclipse Jakarta EE has been placed in the position that it may not evolve the enterprise APIs under their existing package names. That is, the package names starting with java or javax. See Update on Jakarta EE Rights to Java Trademarksfor the background on how we arrived at this state.

So this means that after Jakarta EE 8 (which is API identical to Java EE 8 from which it descends), whenever an API in Jakarta EE is to be updated for a new specification version, the package names used by the API must be renamed away from java or javax. (Note: some other things will also need to be renamed such as system property names, property file names, and XML schema namespaces if those things start with java or javax. For example, the property file META-INF/services/javax.persistence.PersistenceProvider.) But this also means that if an API does not need to be changed, then it is free to remain in its current package names. Only a change to the signature of a package, that is, adding or removing types in the package or adding or removing members in the existing types in the package, will require a name change to the package.

There has been much discussion on the Jakarta EE mail lists and in blogs about what to do given the above constraint and David Blevins has kindly summed up the two main choices being discussed by the Jakarta EE Specification Committee: https://www.eclipse.org/lists/jakartaee-platform-dev/msg00029.html.

In a nutshell, the two main choices are (1) “Big Bang” and (2) Incremental. Big Bang says: Let’s rename all the packages in all the Jakarta EE specifications all at once for the Jakarta EE release after Jakarta EE 8. Incremental says: Let’s rename packages only when necessary such as when, in the normal course of specification innovation, a Jakarta EE specification project wants to update its API.

I would like to argue that Jakarta EE should chose the Incremental option.

Big Bang has no technical value and large, up-front community costs.

The names of the packages are of little technical value in and of themselves. They just need to be unique and descriptive to programmers. In source code, developers almost never see the package names. They are generally in import statements at the top of the source file and most IDEs kindly collapse the view of the import statements so they are not “in the way” of the developer. So, a developer will generally not really know or care if the Jakarta EE API being used in the source code is a mix of package names starting with java or javax, unchanged since Jakarta EE 8, and updated API with package names starting with jakarta. That is, there is little mental cost to such a mixture. The Jakarta EE 8 API are already spread across many, many package names and developers can easily deal with this. That some will start with java or javax and some with jakarta is largely irrelevant to a developer. The developer mostly works with type and member names which are not subject to the package rename problem.

But once source code is compiled into class files, packaged into artifacts, and distributed to repositories, the package names are baked in to the artifacts and play an important role in interoperation between artifacts: binary compatibility. Modern Java applications generally include many 3rdparty open source artifacts from public repositories such as Maven Central and there are many such artifacts in Maven Central which use the current package names. If Jakarta EE 9 were to rename all packages, then the corpus of existing artifacts is no longer usable in Jakarta EE 9 and later. At least not without some technical “magic” in builds, deployments, and/or runtimes to attempt to rename package references on-the-fly. Such magic may be incomplete and will break jar signatures and will complicate builds and tool chains. It will not be transparent.

Jakarta EE must minimize the inflection point/blast radius on the Java community caused by the undesired constraint to rename packages if they are changed. The larger the inflection point, the more reason you give to developers to consider alternatives to Jakarta EE and to Java in general. The Incremental approach minimizes the inflection point providing an evolutionary approach to the package naming changes rather than the revolutionary approach of the Big Bang.

Some Jakarta EE specification may never be updated. They have long been stable in the Java EE world and will likely remain so in Jakarta EE. So why rename their packages? The Big Bang proposal even recognizes this by indicating that some specification will be “frozen” in their current package names. But, of course, there is the possibility that one day, Jakarta EE will want to update a frozen specification. And then the package names will need to be changed. The Incremental approach takes this approach to all Jakarta EE specifications. Only rename packages when absolutely necessary to minimize the impact on the Java community.

Renaming packages incrementally, as needed, does not reduce the freedom of action for Jakarta EE to innovate. It is just a necessary part of the first innovation of a Jakarta EE specification.

A Big Bang approach does not remove the need to run existing applications on earlier platform versions.  It increases the burden on customers since they must update all parts of their application for the complete package renaming when the need to access a new innovation in a single updated Jakarta EE specification when none of the other Jakarta EE specifications they use have any new innovations. Just package renames for no technical reason.  It also puts a large burden on all application server vendors. Rather than having to update parts of their implementations to support the package name changes of a Jakarta EE specification when the specification is updated for some new innovation, they must spend a lot of resources to support both old and new packages name for the implementations of all Jakarta EE specifications.

There are some arguments in favor of a Big Bang approach. It “gets the job done” once and for all and for new specifications and implementations the old java or javax package names will fade from collective memories. In addition, the requirement to use a certified Java SE implementation licensed by Oracle to claim compliance with Eclipse Jakarta EE evaporates once there are no longer any java or javax package names in a Jakarta EE specification. However, these arguments do not seem sufficient motivation to disrupt the ability of all existing applications to run on a future Jakarta EE 9 platform.

In general, lazy evaluation is a good strategy in programming. Don’t do a thing until the thing needs to be done. We should apply that strategy in Jakarta EE to package renaming and take the Incremental approach. Finally, I am reminded of Æsop’s fable, The Tortoise & the Hare. “The race is not always to the swift.”


by BJ Hargrave (noreply@blogger.com) at May 17, 2019 05:11 PM

Back to the top