posts

Liberica JDK release accessibility convenience in developer and user scenarios

Sep 30, 2020
Dmitry Chuyko
21.3

We at BellSoft emphasize that Liberica JDK must be convenient and accessible to all users. Our development team makes sure the runtime is available as Docker container images, on package managers, clouds, and other distribution channels.

Working on various operating systems and cloud storage platforms suffers from JDK’s lengthy deployment and updating. We have designed a specialized API to deploy releases and update quickly and uniformly in different scenarios. Say, a server application v3.3.1 on Windows Server should always have JDK 8u242 installed while the client on any other operating system is running on the latest version. Another example is a slack bot informing of a recent Liberica update suitable for the project. Or configurators to choose JDKs or JREs — possibilities are endless here.

Here in this article, we will provide a unified approach to obtaining the newest Liberica JDK versions and working with them in even the most primitive environments on virtually any operating system.

The choice dilemma

We thought of making some steps towards the ease of distribution after analyzing user behavior on the product website and finding out that visitors parsed it for download links from scripts or their programs. The decision was then to create a public API for everyone’s convenience.

Determining the layout and form of the API took considerable time, even longer than actually designing it. Liberica JDK is a ‘broad’ product with several major versions, multiple supported architectures, installation options, and binary assemblies, all supported in parallel. Releases come out more often than four times a year, and the number of artifacts in each can be hundreds.

2020 has already seen five new releases. In January: versions 8u242, 11.0.6, and 13.0.2; in March: 14.0; in April: 8u252, 11.0.7, and 14.0.1; in July: 8u262, 8u265, 11.0.8, and 14.0.2; and in September: 15.0. A total of over 1,000 artifacts have been released. It is quite difficult to parse and analyze such a large amount of data fully; and if you selected a wrong binary, the consequences could be quite grave, from spending extra memory on functionality unused in the application to security problems.

Package managers do not solve the issue, as they simply install specific versions or builds and do not help make the right choice. A good API should be able to answer the following user questions:

  • I know what I want, would you please give me a download link and checksum?
  • I have version XYZ installed, does it contain the latest fixes?

Applications for the API

The main application for the API in light of the different updating mechanisms is its versatility and the convenience it grants users in streamlining their work with Java. The API provides structured, filtered, up-to-date build information over networks in a unified manner.

The API also assists in parsing HTML pages, a laborious process that takes up valuable development time. At its core, an API is a reliable contract that users can employ to build a stable software script with minimum time constraints and less hassle in searching for the needed JDK versions.

There are three ‘ideal’ use cases for the API:

  1. The team needs notifications only (a ‘get updates’ case). This case is for, more often, companies using modern CI/CD pipelines and containers. So when a new Liberica JDK version appears on their radar, it first goes to developers as a base container image. It spreads to test environments, then deploys on a few machines and, finally, covers the whole production. A helpful addition to the API here is writing a bot that will instantly ping you when a new version is released.

  2. The team prefers ruled updates (a ‘get updates’ case). Say, at some point, a company decides to upgrade servers or desktops. If it uses a Linux package manager, the standard system update is triggered—that is rather simple. If not, or if the team works on Windows, there may be an agent that can perform or skip an update by a centralized command or when some conditions become true. In such an instance, it is crucial to verify the checksum also provided by the API to ensure that the downloaded artifact is exactly what BellSoft has built and tested. When a particular version is installed, the API clears up which download links are used for every operating system.

  3. The team uses or develops a package manager (a ‘get versions’ case). A private artifactory system may perform extra checks and provide DMZ access. But again, it is essential first to compare checksum pulled in binaries. There may be no actual file storage (but a proxy), and original links could be provided by an internal company API online or offline.

A good example of the last one is how JetBrains use the API. Recently, IntelliJ IDEA has offered a possibility to install JDKs produced by numerous vendors, BellSoft included.

Project settings -> SDKs -> + -> Download JDK…

As illustrated, this dialog’s content comes from BellSoft’s API: IntelliJ IDEA is looking for the latest Liberica JDK (14.0.2 at the time of writing) and the latest LTS versions for JDK 8 and 11.

We offer the API to guarantee that its URL and protocol contain the latest information. More importantly, the approach is well documented and complies fully with industry standards. Our engineers are always looking for ways to make the products better and welcome feedback from users. Such an approach becomes ever more productive in the API case for allowing them to update the API and improve user experience.

Release

The most important implementation aspect is the download link to acquire or update the JDK. For convenience, our team has selected the file name to be a separate native ID, thus allowing the user to check that the artifact was downloaded correctly.

The next step is the Liberica JDK version. A version in the Java world is a rather capacious concept with an entire JEP 322 specification dedicated to it. But it only works from Java 10 onwards. For Java 9, you would refer to JEP 223.

API use convenience

This diversity leads to two main issues. The first is that the components of the versions in these specifications are named differently, leading to constant updates of Java 8, which has no such specifications. Besides, the notation in JEP 322 is less intuitive than in JEP 223: e.g., ‘feature’ instead of ‘major’, ‘interim’ instead of ‘minor’, etc. Based on the given facts, our development team always decided to use the new notation and decompose the Java 8 and 9 versions into new fields.

In total, six more fields are added to the original object:

"Version": "11.0.7+10",

"featureVersion": 8,

"interimVersion": 0,

"updateVersion": 7,

"patchVersion": 0,

"buildVersion": 10

Next, numerous fields for describing the current artifact:

  • operating system (os);
  • architecture;
  • bitness;
  • installation type — archive or package for automatic deployment (installationType);
  • package type — file extension in its essence (packageType);
  • bundle type (bundleType).

If the first five properties are obvious, the sixth requires some explanation. One version of Liberica JDK is released in three separate sub-versions (six in fact, because of JDK and JRE):

  • Standard — regular JDK or JRE;
  • Full — Standard, with JavaFX added;
  • Lite — Standard, with specific features optimized by jlink.

To ensure that all Liberica JDK’s users know which versions to choose, we introduced several assisting functions, namely:
The LTS (Long term support) field — set to true for versions 8 and 11.
The EOL (End of life) field — for Liberica JDK versions no longer updated (9, 10, 12, 13).
The latestInFeatureVersion flag — indicates whether the artifact is the latest among feature versions.
The latest flag — indicates whether the artifact is, in fact, the latest among all the existing versions.

Below you will encounter some more abbreviations, which mean the following:

  • GA — General Availability. Stable release.
  • EA — Early Access. Unstable release, not shown in the examples here.
  • FX — JavaFX is present.

Editions glossary:

  • jre — JRE, runtime.
  • jdk — JDK is also a classic. JRE + development features.
  • jdk-full — JDK + JavaFX; in fact, it also includes the Minimal VM for embedded solutions on platforms where relevant.
  • jdk-lite — TODO.
  • jre-full — JRE + JavaFX.

Framework

The Spring framework from Pivotal (BellSoft’s partner), running on Liberica JDK, was chosen for the API backend implementation. The server receives data for operation from the BellSoft GitHub repository.

During development, it was decided to add separate endpoints. The API supports filters and returning text responses if users do not want to parse JSON strings.

You can find detailed technical documentation on the Open API and try the API in action here.

Several examples of its use:

  1. Find a link to the required artifact. Or get the link as plain text.
    2.1. Check if a certain Liberica JDK version is the latest one available. The response should contain “latest”: true
    2.2. Check if a certain Liberica JDK version is the most recent LTS version. The response should contain “latestLTS”: true

Our developers plan to add all the company’s products, like Liberica Mission Control and others, to this API.

User end

Earlier, the article presented the three common use cases for the API. From this point forward, it features a case study of BellSoft’s API from a Liberica JDK user Vladimir Bogdanov, who works as a system administrator at Voronezh State Technical University.

The team has specific requirements (a ‘get versions’ case). It frequently provisions new machines with a toolset using helpers like Ansible. API is very flexible here, e.g., it selects the latest LTS versions, and configuration is controlled in platform-independent and ‘write once’ style. The team also works in a physical hardware lab for educational and scientific purposes. It has about a dozen x86_64 machines running Windows. Frequently, a machine might break, or the OS might stop responding, or a new host might require setup. There is a defined set of configuration steps with software like IDEs and research tools installed, including JDK.

BellSoft thanks Vladimir for his insights and an unusual application for the API.

I first felt the need for adequate software and proper installation guides a decade ago, in 2010, when the school I work at brought in computers. Over time, the number of machines increased, as did the requirements for educational tools. On top of some run of the mill Autocad and Word, informatics teachers asked for 7th Delphi, VisualStudio, MinGW, as well as NetBeans and Eclipse (for the ‘Java-related purposes’). We managed this menagerie of applications under our own steam, as there was no alternative.

Many different builds and incompatibility issues led to disarray and software’s improper functioning. Deployment was a mess; development times were staggering. These times bred vast numbers of add-ons and versions of the same programs. When after years of inconvenience, I stumbled upon BellSoft’s API, I was excited. It allowed working with the many JDK versions via a single access point.

Identifying the latest versions of compatible software

Given the added deb-based and rpm-based distributions, the main question ensuing from the short introduction is: How could I find out the latest stable LTS version for 64-bit Windows with an MSI installer on an ordinary (Intel or AMD) computer, containing JDK, JRE and JavaFX? The following is one of the methods:

curl https://api.bell-sw.com/v1/liberica/releases?version-modifier=latest&bitness=64&release-type=lts&package-type=msi&bundle-type=jdk-full

At the time of writing, this request returned “11.0.8”.

The same is applicable for Windows PowerShell. Type in Invoke-RestMethod and insert the same link as above in the command line.

{

    "bitness": 64,

    "buildVersion": 10,

    "EOL": false,

    "latestLTS": true,

    "os": "windows",

    "updateVersion": 8,

    "downloadUrl": "https://github.com/bell-sw/Liberica/releases/download/11.0.8+10/bellsoft-jdk11.0.8+10-windows-amd64-full.msi",

    "interimVersion": 0,

    "latestInFeatureVersion": true,

    "LTS": true,

    "bundleType": "jdk-full",

    "version": "11.0.8 + 10",

    "featureVersion": 11,

    "packageType": "msi",

    "sha1": "",

    "FX": true,

    "filename": "bellsoft-jdk11.0.8+10-windows-amd64-full.msi",

    "installationType": "installer",

    "size": 266248192,

    "patchVersion": 0,

    "GA": true,

    "architecture": "x86",

    "latest": false

}

curl --silent https://api.bell-sw.com/v1/liberica/releases downloads JSON without unnecessary details about speed, time and file size, and then uploads what was downloaded onto the console. Windows 10 has it out of the box on its official website. On Linux, you need to type in sudo apt \ yum \ dnf \ zypper \ apk -y and install curl depending on the distribution.

"os": "windows" and "bitness": 64 are clear from looking at the one-liner and comparing it with the example above.

To get a download link, perform the same operation but change featureVersion to downloadUrl:

curl --silent "https://api.bell-sw.com/v1/liberica/releases?package-type=msi&version-modifier=latest&release-type=lts&bundle-type=jdk-full&bitness=64&fields=downloadUrl&output=text"

Note that "featureVersion": 11 is the same as sudo apt-get install bellsoft-java11 from the Linux installation example. Thus, the string to install the latest LTS version on Ubuntu will look like this, after adding the repository, key and updating the indexes:

LATEST_LTS_LIBERICA=$(curl "https://api.bell-sw.com/v1/liberica/releases?package-type=deb&version-modifier=latest&release-type=lts&bundle-type=jdk-full&bitness=64&arch=x86&fields=featureVersion&output=text")

sudo apt -y install bellsoft-java"$LATEST_LTS_LIBERICA_JAVA"

Ansible approach to installing JDK

I have also published an Ansible role to install the necessary versions of JDK/JRE. As mentioned before, our lab has specific requirements for the API—a broad spectrum toolset, IDEs, and unstable hardware—so it is quite natural to use Ansible for this task.

Repeat the same but adopting the syntax of your configuration management system (to obtain the release name):

Variables:

liberica_common_architecture: x86

liberica_common_bundletype: jdk-full

liberica_common_eol: 'false'

liberica_common_lts: 'true'

liberica_common_ga: 'true'

liberica_common_latestlts: 'true'

Extract the link with information and write it to the liberica_releases variable.



    - name: Get releases info from API

    block:

        - uri:

            url: https://api.bell-sw.com/v1/liberica/releases

            method: GET

            return_content: yes

        delegate_to: localhost

        register: liberica_releases

    set_fact:

        liberica_version_number_fact: "{{liberica_java_version | default (liberica_releases.json | json_query (query_feature_version))}}"

        vars:

            query_feature_version: "[? architecture ==` {{liberica_common_architecture}} `]

            | [? bundleType == `{{liberica_common_bundletype}}`]

            | [? EOL == `{{liberica_common_eol}}`]

            | [? LTS == `{{liberica_common_lts}}`]

            | [? GA == `{{liberica_common_ga}}`]

            | [? latestLTS == `{{liberica_common_latestlts}}`] .featureVersion | [0] "

Some more explanations:

liberica_version_number_fact is the name of the variable that will contain the “11” mentioned before.
liberica_java_version is the version that, in theory, the user should set if they need a particular one. If nothing is specified, the default, or everything inside default(), is executed.
liberica_releases.json is the proprietary register: liberica_releases variable. Ansible understands if it is given JSON as a reference and puts it in a separate json key.
json_query is a standard Ansible function. It is an overlay for jmespath. Note that it is not a regular BellSoft API query, but a query string for the jq tool used in this role as an alternative way of extracting information.

Everything below query_feature_version: is the same as the preceding code, only split into several lines, because ansible-lint was not compatible. The double parentheses are part of jinja2’s templating and contain the variable name. Same as $VAR in bash. I should also mention the quotes. This bracing is specific only to jmespath.

Conclusion

User convenience is at the core of the API release from BellSoft, as multiple distributions are connected with issues related to their updating. Our development team aims to push its product this year and works hard to implement new even more user-friendly features.

Liberica Download API is a universal solution that works for all the cases described in even the most primitive operating environment. It is available in IntelliJ IDEA or on our website. The many problems faced on different systems can be negated by installing a safe and unified Liberica software package to work with the JDK.

Subcribe to our newsletter

figure

Read the industry news, receive solutions to your problems, and find the ways to save money.

Further reading