Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Review the Quarkus introduction

Quarkus concept definition

Quarkus is a full-stack Kubernetes native Java framework designed for Java Virtual Machine (JVM) and native compilation to optimize Java specifically for containers and make it an efficient platform for serverless, cloud, and Kubernetes environments.

Quarkus is integrated with the framework

Quarkus works with common Java standards, frameworks, and libraries, such as: Eclipse MicroProfile, Spring, Apache Kafka, RESTEasy (JAX-RS), Hibernate ORM (JPA), Spring, Infinispan, Camel, etc.

Dependency injection for Quarkus

Quarkus’s dependency injection solution is based on CDI (Context and dependency injection) and includes an extension framework to extend functionality and configure, bootstrap, and integrate it into your application. Adding extensions is as easy as adding dependencies; Alternatively, you can use the Quarkus tool.

Quarkus is multilingual

  • GraalVM (a general-purpose virtual machine for running applications written in multiple languages, including Java and JavaScript) provides the right information to compile applications natively.

  • Surprisingly fast startup time, extremely low RSS memory (not just heap size!) Provides near-instant upscaling and high memory utilization in container choreography platforms such as Kubernetes

Designed for developers

Quarkus has been designed from the start to be easy to use, with features that require little configuration to work.

Developers can choose the Java framework they want for their applications, which can be run in JVM mode or compiled and run in native mode.

Can bring the best joy to the developer:

Unified configuration
  • Zero configuration, instant reloading real-time reloading

  • 80% simplified code for common usage and 20% more flexible usage

  • No-hassle native executable file generation

The container is preferred
  • Features such as fast startup and low memory consumption are critical to reducing overall hosting costs, whether your application is hosted on a public cloud or in an internally hosted Kubernetes cluster.

  • Quarkus’s development follows the container first principle, which means it has been optimized for lower memory usage and faster startup time in the following ways

    • Strong support for Graal/SubstrateVM

    • Metadata processing at build time

    • Reduce the use of reflection

    • The native image is prebooted

Quarkus builds applications that consume 1/10 of the memory of traditional Java and start up faster (up to 300 times faster), all of which significantly reduces the cost of cloud resources.

Cloud native

Use the 12-factor principle in Kubernetes and other environments.

Unify the imperative and the reaction

Quarkus is designed to seamlessly combine familiar imperative code with non-blocking, responsive styles when developing applications.

This is useful for Java developers who are used to using an imperative model and don’t want to switch styles, as well as developers who use a cloud native/responsive approach.

Based on the standard

Quarkus provides a cohesive, easy-to-use, full-stack framework by leveraging a growing list of over fifty of the best libraries you like and use. All connected to the standard trunk

The Quarkus development model can be adapted to any application you are developing

Quarkus is an effective solution for running Java in new serverless architectures, microservices, containers, Kubernetes, function-as-a-Service (FaaS), and cloud environments because it was created with all of these factors in mind.

Using DI injection

  • Dependency injection in Quarkus is based on ArC, a CDI based dependency injection solution tailored for Quarkus architecture. If you are not familiar with CDI, you are advised to read the CDI Introduction guide.

  • Quarkus only implements a subset of CDI functionality and has non-standard features and specific APIS. You can learn more about it in the Contexts and Dependency Injection guide.

  • ArC as a dependency, Quarkus-Resteasy so you’re already handy.

Configuration Reference Guide

Both the Quarkus application and Quarkus itself (core and extension) are configured through the same mechanism, which leverages the SmallRye Config API and the MicroProfile Config specification implementation. Quarkus itself offers some additional features.

Configuration source

By default, Quarkus reads configuration properties from multiple sources (with decreasing priority) :

  • System property
  • The environment variable
  • Env is placed in the current working directory
  • The application.properties file is placed in the $PWD/config/ directory
  • Application configuration files, that is, SRC/main/resources/application. The properties

System property

Run the jar:
java -Dquarkus.datasource.password=youshallnotpass -jar target/quarkus-app/quarkus-run.jar
Copy the code
Native executables:
./target/myapp-runner -Dquarkus.datasource.password=youshallnotpass
Copy the code

The environment variable

Run the jar:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ; 
java -jar target/quarkus-app/quarkus-run.jar
Copy the code
Native executable file:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ;
./target/myapp-runner
Copy the code

The file name. Env is placed in the current working directory

Example. Env file

QUARKUS_DATASOURCE_PASSWORD= YoushallNotPass QUARKUS_DATASOURCE_PASSWORD uses the same rules as environment variables to convert names.Copy the code

For developer mode, this file can be placed in the root of the project, but it is not recommended to check it into version control.

The. Env file of an environment variable that is not defined in a configuration file will override all of its associated application.properties profiles, for example, %test.application.value will override APPLICATION_VALUE.

The application.properties file is placed at $PWD/config/

  • Place the application.properties file in a directory called config, which is in the directory where the application runs, and all the runtime properties defined in this file will override the default configuration.

  • In addition, any runtime properties added to the file that were not part of the original application.properties file will also be taken into account. It works the same way for the running program JAR and the native executable.

  • The config/application. The function of the properties can also be used in the development mode.

  • To use it, the config/application. The properties need to be placed in the output directory of the build tools. Keep in mind, however, that any cleanup from the build tool (such as MVN clean or) gradle Clean will also remove the config directory.

Application configuration files

Is located in the main application configuration files in the SRC/main/resources/application properties.

Application. The properties file
greeting.message=hello 
quarkus.http.port=9090 
Copy the code

Quarkus supports the use of attribute expressions application.properties in files.

Embed configuration files in dependencies
  • You can embed the profile by adding a profile to the meta-INF /microprofile-config.properties profile (this is a standard feature of Microprofile Config).

  • When this dependency is added to the application, its configuration properties are merged.

  • You can override attributes that precede it from its property application.properties.

Inject configuration properties

Quarkus uses MicroProfile Config annotations to inject configuration properties into the application.

@ConfigProperty(name = "greeting.message") 
String message;
Copy the code

You can use @inject @configProperty or @configProperty. For members annotated with @inject, annotations are not required by @configProperty. This behavior differs from MicroProfile Config.

If the application tries to inject configuration properties that are not set, an error is thrown, allowing you to quickly know when the configuration is complete.

@ ConfigProperty example
@ConfigProperty(name = "greeting.message") 
String message;

@ConfigProperty(name = "greeting.suffix", defaultValue="!" ) 
String suffix;

@ConfigProperty(name = "greeting.name")
Optional<String> name; 
Copy the code

If you do not provide a value for this property, the application will fail to start

javax.enterprise.inject.spi.DeploymentException: No config value of type [class java.lang.String] exists for: The greeting message.Copy the code

If you configure a value that is not provided, the default greeting.suffix is injected.

This property is Optional. If no value is provided, a null value greeting.name is injected.

Programmatically access the configuration

Configuration can be accessed programmatically. It can be convenient to implement dynamic lookup or retrieval of configured values from classes that are neither CDI beans nor JAX-RS resources.

Configuration can be accessed programmatically in the following ways

Org. Eclipse. Microprofile. Config. ConfigProvider. GetConfig () : String databaseName = ConfigProvider. GetConfig (). The getValue ("database.name", String.class);
Optional<String> maybeDatabaseName = ConfigProvider.getConfig().getOptionalValue("database.name", String.class);
Copy the code

Using the @ ConfigProperties

As shown in the above a sample way into multiple related configuration values of alternative, the user can also use the @ IO. Quarkus. Arc. Config. ConfigProperties comments to these attributes together.

For the Greeting property above, GreetingConfiguration creates a class like this:

@ConfigProperties(prefix = "greeting") 
public class GreetingConfiguration {

    private String message;
    private String suffix = "!";
    private Optional<String> name;

    public String getMessage(a) {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getSuffix(a) {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public Optional<String> getName(a) {
        return name;
    }

    public void setName(Optional<String> name) {
        this.name = name; }}Copy the code

GreetingResource can then Inject this class into the CDI annotation @Inject, as shown below:

@Inject
GreetingConfiguration greetingConfiguration;
Copy the code

Another alternative style provided by Quarkus is that GreetingConfiguration creates interfaces like this:

package org.acme.config;

import io.quarkus.arc.config.ConfigProperties;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.Optional;

@ConfigProperties(prefix = "greeting")
public interface GreetingConfiguration {

    @ConfigProperty(name = "message") 
    String message(a);

    @ConfigProperty(defaultValue = "!" )
    String getSuffix(a); 

    Optional<String> getName(a); 
}
Copy the code

When used in @ ConfigProperties class or interface, if you do not provide the value of one of the fields, then the application startup will fail, and the javax.mail. Enterprise. Inject. Spi. DeploymentException display indicating a lack of information. This does not apply to Optional fields and fields with default values.

Additional instructions for @configProperties

When using regular classes with class annotations, @ConfigProperties does not necessarily have to declare getters and setters. It is also valid to have simple common non-final fields.

In addition, the configuration class supports nested object configuration. Assuming an additional greeting configuration layer is required, the name Content will contain some fields. This can be done like this:

@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {

    public String message;
    public String suffix = "!";
    public Optional<String> name;
    public ContentConfig content; 

    public static class ContentConfig {
        public Integer prizeAmount;
        publicList<String> recipients; }}Copy the code

The field name (not the class name) determines the name of the property bound to the object.

Setting the properties would be done in the normal way, for example, application.properties might have:

greeting.message = hello
greeting.name = quarkus
greeting.content.prize-amount=10
greeting.content.recipients=Jane,John
Copy the code

In addition, @ConfigProperties can annotate classes that use annotations using Bean Validation annotations, similar to the following example:

@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {

    @Size(min = 20)
    public String message;
    public String suffix = "!";

}
Copy the code

For validation to work, Quarkus-Hibernate-Validator needs to provide an extension

If validation fails with the given configuration, the application will not start and the corresponding validation error will be indicated in the log.

If an interface has the @configProperties annotation, it is allowed to extend other interfaces and bind properties using methods in the entire interface hierarchy.

Use the same ConfigProperty with a different prefix

Quarkus also supports using the @ConfigProperties annotation to use the same object with a different prefix io.quarkus.arc.config.@ConfigPrefix for each injection point. For example, both the prefix and the GreetingConfiguration prefix require the above code. In this case, the code looks like this: greetingother

GreetingConfiguration.java @ConfigProperties(prefix = "greeting") public class GreetingConfiguration { @Size(min = 20) public String message; public String suffix = "!" ; } SomeBean.java @ApplicationScoped public class SomeBean { @Inject GreetingConfiguration greetingConfiguration; @ConfigPrefix("other") GreetingConfiguration otherConfiguration; }Copy the code

Using object lists

In some cases, it may be necessary to support complex configuration structures that leverage object lists, as shown in the following example:

ComplexConfiguration.java

@ConfigProperties(prefix = "complex")
public class ComplexConfiguration {
    public String name;
    public String user;
    public String password;
    public List<Nested> inputs;
    public List<Nested> outputs;
    public static class Nested {
        public String user;
        publicString password; }}Copy the code

This type of use case is supported only if the YAML configuration is used with the Quarkus-config-YAMl extension. The corresponding sample YAML configuration could be:

application.yaml

complex:
  name: defaultName
  user: defaultUser
  password: defaultPassword
  inputs:
    - user: user
      password: secret
    - user: otheruser
      password: secret2
  outputs:
    - user: someuser
      password: asecret
    - user: someotheruser
      password: anothersecret
Copy the code

The limitation of this configuration is that the type used as a generic type for a list must be a class, not an interface

Configuration Configuration file

Quarkus supports the concept of configuring profiles. These allow you to have multiple configurations in the same file and choose between them by profile name.

The syntax is %{profile}.config.key=value. For example, if I have the following:

quarkus.http.port=9090
%dev.quarkus.http.port=8181
Copy the code

Unless the dev profile is active, the Quarkus HTTP port will be 9090, in which case it will be 8181.

To use profiles in. Env files, you can follow the _{PROFILE}_CONFIG_KEY=value pattern. The equivalent of the above example in the.env file is:

QUARKUS_HTTP_PORT=9090
_DEV_QUARKUS_HTTP_PORT=8181
Copy the code