[Quarkus technology series] "cloud native architecture system" configuration reference guide related function mechanism configuration introduction and analysis

Review the introduction to Quarkus

Concept definition of Quarkus

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

Quarkus and framework integration

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

Quarkus dependency injection

Quarkus's dependency injection solution is based on CDI (context and dependency injection) and includes an extension framework to extend functionality and configure, boot and integrate it into your application. Adding extensions is as easy as adding dependencies; Alternatively, you can use quarkus tools.

Quarkus Multilingualism

  • GraalVM (a general-purpose virtual machine used to run applications written in multiple languages, including Java and JavaScript) provides the correct information for native compilation of applications.

  • Amazing fast start-up time and extremely low RSS memory (not just heap size!) provide near immediate upward expansion and high-density memory utilization in container orchestration platforms such as Kubernetes

Designed for developers

Quarkus was designed from the beginning to be simple and easy to use, and its functions can be used normally without configuration.

Developers can choose the required Java framework for their applications, which can run in JVM mode or compile and run in native mode.

Can bring the best joy to developers:

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

  • Simplified 80% of the commonly used code and flexible 20% of the usage

  • No trouble with native executable generation

Container priority
  • Whether the application is hosted on a public cloud or an internally hosted Kubernetes cluster, features such as fast startup and low memory consumption are crucial to reducing the overall host cost.

  • Quarkus's development follows the container first principle, which means that it has been optimized to reduce memory usage and accelerate startup time in the following ways

    • Support Graal/SubstrateVM

    • Build time metadata processing

    • Reduce the use of reflections

    • Native image pre boot

The memory consumption of applications built by Quarkus is only 1 / 10 of that of traditional Java, and the startup time is faster (300 times faster), which greatly reduces the cost of cloud resources.

Cloud primordial

The 12 element principle is adopted in Kubernetes and other environments.

Unified imperative and reactive

In terms of design, Quarkus can seamlessly combine familiar imperative code with non blocking and responsive styles when developing applications.

This is useful for Java developers who are used to using the imperative model without switching styles, as well as developers who use the cloud native / reactive approach.

Standards based

Quarkus provides a cohesive, easy-to-use, full stack framework by leveraging a growing list of more than 50 of the best libraries you like and use. All are connected to a standard backbone

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

Quarkus is an effective solution for running Java in a new serverless architecture, microservices, containers, Kubernetes, function as a service (FaaS) and cloud environment, because all these factors were fully considered when it was created.

Using DI injection

  • Dependency injection in Quarkus is based on ArC, which is a CDI based dependency injection solution tailored for Quarkus architecture. If you are not familiar with CDI, it is recommended that you read the CDI introduction guide.

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

  • As a dependency of ArC, quarkus resteasy is convenient for you.

Configuration reference guide

Quarkus applications and quarkus itself (core and extension) are configured through the same mechanism, which is implemented by SmallRye Config API and MicroProfile Config specification. Quarkus itself provides some additional functionality.

Configuration source

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

  • System properties
  • environment variable
  • A file named. env is placed in the current working directory
  • The application.properties file is placed in the $PWD/config / directory
  • The application configuration file is src/main/resources/application.properties

System properties

Run jar:
java -Dquarkus.datasource.password=youshallnotpass -jar target/quarkus-app/quarkus-run.jar
native executable:
./target/myapp-runner -Dquarkus.datasource.password=youshallnotpass

environment variable

Run jar:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ; 
java -jar target/quarkus-app/quarkus-run.jar
native executable:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ;
./target/myapp-runner

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

Example. env file

QUARKUS_DATASOURCE_PASSWORD=youshallnotpass
QUARKUS_DATASOURCE_PASSWORD Use the same rules as environment variables to convert names.

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

The environment variable. env file without a defined configuration file will overwrite the application.properties in all its related configuration files. For example,% test.application.value will be overwritten by APPLICATION_VALUE. env file.

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

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

  • In addition, any runtime properties added to the file that do not belong to the original application.properties file will also be taken into account. For running program jar s and native executables, they work the same way.

  • The config/application.properties function is also available in development mode.

  • To use it, config/application.properties needs to be placed in the output directory of the build tool. However, remember that any cleanup from the build tool (such as mvn clean or gradle clean) will also delete the config directory.

Application profile

The main application configuration file src/main/resources/application.properties located in.

application.properties file
greeting.message=hello 
quarkus.http.port=9090 

Quarkus supports the use of the property expression application.properties in files.

Embedding a configuration file into a dependency
  • The configuration file can be embedded by adding a configuration file to the META-INF/microprofile-config.properties configuration file (which is a standard feature of MicroProfile Config).

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

  • The properties that take precedence over it can be overridden from its property application.properties.

Injection configuration properties

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

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

have access to @Inject @ConfigProperty or @ ConfigProperty. Annotation is not a required @ ConfigProperty for members using @ Inject annotation. This behavior is different from MicroProfile Config.

If an application attempts to inject a configuration property that is not set, an error is raised, 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; 

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

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

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

This property is Optional - Optional. If you configure a value that is not provided, a null value of greeting.name will be injected.

Access configuration programmatically

The configuration can be accessed programmatically. It may be convenient to implement dynamic lookup or retrieve configured values from classes that are neither CDI bean s nor JAX-RS resources.

The configuration can be accessed programmatically using the following methods

org.eclipse.microprofile.config.ConfigProvider.getConfig(): 

String databaseName = ConfigProvider.getConfig().getValue("database.name", String.class);
Optional<String> maybeDatabaseName = ConfigProvider.getConfig().getOptionalValue("database.name", String.class);

Use @ ConfigProperties

As an alternative to injecting multiple related configuration values in the manner shown in the above example, users can also combine these properties together using the @ io.quarkus.arc.config.ConfigProperties annotation.

For the above Greeting attribute, GreetingConfiguration can create a class as follows:

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

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

    public String getMessage() {
        return message;
    }

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

    public String getSuffix() {
        return suffix;
    }

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

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

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

Then, GreetingResource can Inject this class into using CDI annotations like @ Inject, as shown below:

@Inject
GreetingConfiguration greetingConfiguration;

Another alternative style provided by Quarkus is greeningconfiguration, which creates an interface 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();

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

    Optional<String> getName(); 
}

When used on the @ ConfigProperties class or interface, if the value of one of its fields is not provided, the application startup will fail and javax.enterprise.inject.spi.DeploymentException will display information indicating the missing value. This does not apply to Optional fields and fields with default values.

Additional notes on @ ConfigProperties

When using a regular class with class annotations, @ ConfigProperties does not necessarily have to declare getter s and setter s. It is also valid to have a simple public non final field.

In addition, the configuration class supports nested object configuration. Suppose you need an additional greeting configuration layer, and the name content will contain some fields. This can be achieved:

@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;
        public List<String> recipients;
    }
}

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

Setting properties will be done in the normal way. For example, application.properties may have:

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

In addition, @ ConfigProperties can annotate annotated classes using the Bean Validation annotation, similar to the following example:

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

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

}

For validation to take effect, the quarkus hibernate validator needs to provide an extension

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

If the interface is annotated with @ ConfigProperties, it is allowed to extend other interfaces and bind properties using methods in the entire interface hierarchy.

Use the same ConfigProperty with different prefixes

Quarkus also supports the use of the annotation @ ConfigProperties to use the same object io.quarkus.arc.config with a different prefix for each injection point .@ConfigPrefix. For example, the above code is required for both prefix and prefix greeningconfiguration. In this case, the code is as follows: 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;

}

Use object list

In some cases, it may be necessary to support complex configuration structures utilizing 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;
        public String password;
    }
}

Such use cases are supported only when YAML configuration is used with the quarkus config YAML extension. The corresponding example YAML configuration can 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

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

Configuration profile

Quarkus supports the concept of 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

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

To use a configuration file in an. env file, follow a_ {PROFILE}_CONFIG_KEY=value mode The equivalent content of the above example in env file is:

QUARKUS_HTTP_PORT=9090
_DEV_QUARKUS_HTTP_PORT=8181

Tags: Java Kubernetes optional

Posted on Mon, 01 Nov 2021 00:07:02 -0400 by xxATOMxx