How Quarkus Integrates MicroProfile and Spring

Hello everyone, and with you the third post from the Quarkus series! (By the way, register and go to our webinar “ This is Quarkus - Kubernetes native Java framework ”, which will be held on May 27. We will show how to start from scratch or transfer ready-made solutions)



When developing Java microservices, it is often believed that Eclipse MicroProfile and Spring Boot are separate and independent APIs. By default, programmers typically use the APIs they are used to, since learning new frameworks and runtime components takes a lot of time. Today we’ll try to simplify the development of some popular MicroProfile APIs for Spring developers.and show how to use the Spring API and the new useful features of Quarkus at the same time .

If a little more detailed, we will first look at the scope and details of how Quarkus supports Spring APIs to show Spring developers how to use the MicroProfile API in their daily work. Then we will talk about the MicroProfile API, which will be useful for Spring developers when creating microservices.

Why Quarkus? Firstly, this is live coding, that is, automatic reloading of any changes to the MicroProfile API, Spring API and other Java APIs, which is performed with just one command: mvn quarkus: dev. Secondly, considered in our examplethe Person service (it is compiled from the Spring, MicroProfile, and JPA APIs into a binary file using the native GraalVM image) starts in just 0.055 seconds and takes about 90 MB of RAM (RSS) at the endpoint of the RESTful application. Moreover, its compilation itself is performed with just one command: mvn package -Pnative.

We will not go into the details of MicroProfile, but will only try to help Spring developers understand how in Quarkus you can use Spring APIs along with MicroProfile APIs.

Containers and Kubernetes


In order not to overload this article, we will only look at the high-level aspects of Kubernetes support here , as this is important to understand. Quarkus is positioned as a Java stack for Kubernetes, it is designed to minimize memory consumption and startup time of Java applications and services, and, as a result, increase the density of their placement on the host and reduce overall costs.

Quarkus also supports Kubernetes auto- generation of resources and offers deployment guides on Kubernetes and Red Hat OpenShift platforms. In addition, Quarkus automatically generates the Dockerfile.jvm (JVM packaging) and Dockerfile.native (native binary packaging) files needed to create containers.

Finally, focusing on Kubernetes as the target deployment environment, Quarkus does not use Java frameworks in cases where similar functionality is implemented at the level of the Kubernetes platform itself. Table 1 shows a map of the functional correspondence of Kubernetes and the typical Java frameworks used by Spring developers.

Table 1. Functional mapping map for Java frameworks and Kubernetes.
FunctionalTraditional Spring BootKubernetes
Service discoveryEurekaDNS
ConfigurationSpring cloud configConfig Maps / Secrets
Load balancingRibbon (client side)Service, Replication Controller (server side)

Compiling and running the code from the example


In this article, we refer to an example project where the Spring and MicroProfile APIs and even the same Java class are shared. The code from this example can be compiled and run from the command line, see the README.md file for more details.

Spring Framework APIs


Dependency injection


Quarkus supports a variety of Contexts and Dependency Injection (CDI) APIs and Spring Dependency Injection (Spring DI) APIs. If you work with MicroProfile, Java EE and Jakarta EE , then you are already familiar with CDI. On the other hand, Spring developers can use the Quarkus Extension for Spring DI API to ensure compatibility with Spring DI. Examples of the use of the supported Spring DI APIs are given in Table 2.

The project from our example uses both CDI and Spring Dependency Injection. For more information and examples on this topic, see the Quarkus Guide, called the Spring DI Guide .

Table 2. Examples of using the supported Spring DI APIs.
Supported Spring DI Features
Constructor Injection
public PersonSpringController(
   PersonSpringRepository personRepository,  // injected      
   PersonSpringMPService personService) {    // injected
      this.personRepository = personRepository;
      this.personService = personService;
}
Field Injection
Autowired
Value
@Autowired
@RestClient
SalutationRestClient salutationRestClient;

@Value("${fallbackSalutation}")
String fallbackSalutation;
Bean
@Configuration
@Configuration
public class AppConfiguration {
   @Bean(name = "capitalizeFunction")
   public StringFunction capitalizer() {
      return String::toUpperCase;
   }
}
Component
@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
   @Override
   public String apply(String s) {
      return s;
   }
}
Service
@Service
public class MessageProducer {
   @Value("${greeting.message}")
   String message;

   public String getPrefix() {
      return message;
   }
}

-


MicroProfile users will enjoy Quarkus supporting JAX-RS, MicroProfile Rest Client, JSON-P and JSON-B as their primary web programming model. Spring developers will be pleased with the recent support of the Spring Web API in Quarkus, in particular, the REST interfaces. Similar to Spring DI, the main goal of supporting the Spring Web API is for Spring developers to use the Spring Web APIs along with the MicroProfile APIs. Examples of use of the supported Spring Web APIs are given in Table 3, and more information and examples on this topic can be found in the Quarkus Guide, called the Spring Web Guide .

Table 3. Examples of use of the supported Spring Web APIs.
Supported Spring Web FeaturesExamples
@RestController
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
   ...
   ...
   ...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (partial)
@GetMapping(path = "/greet/{id}",
   produces = "text/plain")
   public String greetPerson(
   @PathVariable(name = "id") long id) {
   ...
   ...
   ...
}

Spring Data JPA


MicroProfile users will also like Quarkus to support JPA using Hibernate ORM. There is good news for Spring developers too: Quarkus supports the common annotations and Spring Data JPA types. Examples of the use of the supported Spring Data JPA APIs are given in table 4.
In the project from our example , the Spring Data JPA APIs are used, and additional information is available in the Quarkus guide called Spring Data JPA Guide .

Table 4. Examples of using the supported Spring Data JPA APIs.
Supported Spring Data JPA FeaturesExamples
Crudrepository
public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}
Repository
JpaRepository
PagingAndSortingRepository
public class PersonRepository extends 

    Repository {

    Person save(Person entity);

    Optional findById(Person entity);
}
Repository Fragments
public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}
Derived query methods
public interface PersonRepository extends CrudRepository {

    List findByName(String name);
    
    Person findByNameBySsn(String ssn);
    
    Optional 
       findByNameBySsnIgnoreCase(String ssn);

    Boolean existsBookByYearOfBirthBetween(
            Integer start, Integer end);
}
User-defined queries
public interface MovieRepository
         extends CrudRepository {

    Movie findFirstByOrderByDurationDesc();

    @Query("select m from Movie m where m.rating = ?1")
    Iterator findByRating(String rating);

    @Query("from Movie where title = ?1")
    Movie findByTitle(String title);
}

API- MicroProfile


(Fault tolerance)


Fault tolerance designs are critical to preventing cascading failures and building robust microservice architectures. Spring developers have been using Hystrix circuit breakers for fault tolerance for years . However, Hystrix has not been updated for a long time, but MicroProfile's Fault Tolerance is now actively developing and has already had several years of production use. Therefore, to increase the reliability of services in Quarkus, it is recommended to use MicroProfile Fault Tolerance APIs, examples of which are given in Table 5. For more information about this, see the Quarkus Fault Tolerance Guide .

Table 5. Examples of using the supported MicroProfile Fault Tolerance APIs.
MicroProfile Fault Tolerance FeaturesDescriptionExamples
@Asynchronous

@Asynchronous
@Retry
public Future<String> getSalutation() {
   ...
   return future;
}
@Bulkhead

@Bulkhead(5)
public void fiveConcurrent() {
   makeRemoteCall(); //...
}
@CircuitBreaker

@CircuitBreaker(delay=500   // milliseconds
   failureRatio = .75,
   requestVolumeThreshold = 20,
   successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}
@Fallback

@Timeout(500) // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

public String fallback() {
   return "hello";
}
Retry

@Retry(maxRetries=3)
public String getSalutation() {
   makeRemoteCall(); //...
}
Timeout

@Timeout(value = 500 )   // milliseconds
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

(Service Health)


Kubernetes platforms monitor container health using special services. So that the underlying platform can monitor services, Spring developers usually use the custom HealthIndicator and Spring Boot Actuator. In Quarkus, this can be done using MicroProfile Health, which by default perform a liveness check, but can be configured to simultaneously check liveness and readiness. Examples of using the supported MicroProfile Health APIs are shown in Table 6, and more information is provided in the Quarkus Health Guide .

Table 6. Examples of use of the supported MicroProfile Health APIs.
MicroProfile Health FeaturesDescriptionExamples
@Liveness

Endpoint:
host:8080/health/live
@Liveness
public class MyHC implements HealthCheck {
  public HealthCheckResponse call() {

   ...
   return HealthCheckResponse
     .named("myHCProbe")
     .status(ready ? true:false)
     .withData("mydata", data)
     .build();  
}
@Readiness

Endpoint:
host:8080/health/ready
@Readiness
public class MyHC implements HealthCheck {
  public HealthCheckResponse call() {

   ...
   return HealthCheckResponse
     .named("myHCProbe")
     .status(live ? true:false)
     .withData("mydata", data)
     .build();  
}


Applications provide metrics either for operational purposes (to control SLA performance indicators) or non-operational (business SLA indicators). Spring developers provide metrics using the Spring Boot Actuator and Micrometer. In turn, Quarkus uses MicroProfile Metrics to provide basic metrics (JVM and operating system), vendor metrics (Quarkus), and application metrics. MicroProfile Metrics requires that the implementation support JSON and OpenMetrics (Prometheus) output formats. Examples of using the MicroProfile Metrics API are given in Table 7.

In the project from our example, MicroProfile Metrics are used to provide application metrics. For more information, see the Quarkus Metrics Guide .

7. API- MicroProfile Metrics.
MicroProfile Metrics
@Counted
counter-,
@Counted(name = "fallbackCounter", 
  displayName = "Fallback Counter", 
  description = "Fallback Counter")
public String salutationFallback() {
   return fallbackSalutation;
}
@ConcurrentGauge
gauge-,
@ConcurrentGuage(
  name = "fallbackConcurrentGauge", 
  displayName="Fallback Concurrent", 
  description="Fallback Concurrent")
public String salutationFallback() {
   return fallbackSalutation;
}
@Gauge
gauge-,
@Metered(name = "FallbackGauge",
   displayName="Fallback Gauge",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
@Metered
meter-,
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
Metric
, ,
@Metric
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}
Timed
,
@Timed(name = "TimedFallback",
   displayName="Timed Fallback",
   description="Fallback delay")
public String salutationFallback() {
   return fallbackSalutation;
}

Metrics Endpoints

Metrics for localhost applications : 8080 / metrics / application
Basic metrics for localhost : 8080 / metrics / base
Vendor metrics for localhost : 8080 / metrics / vendor
All metrics for localhost : 8080 / metrics

MicroProfile Rest Client


Microservices often provide RESTful endpoints that require appropriate client APIs. To use RESTful endpoints, Spring developers typically use a RestTemplate. Quarkus also offers MicroProfile Rest Client APIs for solving this problem, examples of their use are given in Table 8.

In the project from our example, the use of RESTful endpoints is performed using the MicroProfile Rest Client. For more information and examples on this topic, see the Quarkus Rest Client Guide .

Table 8. Examples of using the MicroProfile Rest Client APIs.
MicroProfile Rest Client FeaturesDescriptionExamples
@RegisterRestClient
Registers a typed Java interface as a REST client
@RegisterRestClient
@Path("/")
public interface MyRestClient {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getSalutation();
}
@RestClient
Marks the implementation of an instance of a typed REST client interface
@Autowired // or @Inject
@RestClient
MyRestClient restClient;
Invocation
Invokes a REST endpoint
System.out.println(
   restClient.getSalutation());
mp-rest / url
Specifies a REST endpoint
application.properties:
org.example.MyRestClient/mp-rest/url=
   http://localhost:8081/myendpoint

Summary


In this blog, which is primarily useful to Spring developers, we briefly looked at how to use Spring APIs in Quarkus together with MicroProfile APIs to develop Java microservices and then compile them into native binary code, which saves hundreds of megabytes of RAM and starts in a matter of milliseconds.

As you already understood, additional information about support for the Spring and MicroProfile APIs, as well as a host of other useful information, can be found in the Quarkus manuals .

All Articles