1. Building a full stack API with
DevOps integrated
or how to build a complete u-service from scratch in an hour
Sergio Gutierrez
EMEA Senior Solution Architect
Luca Ferrari
EMEA Senior Solution Architect
2. Agenda
➔ APIs in Microservice Architecture patterns
➔ Quarkus as a runtime engine (advantages)
➔ Development approach: API Contract first / Code first
➔ Demos
1. building your first quarkus api
2. adding fault tolerance
3. observing your u-service
4. adding logging to your service
5. adding persistence
6. adding security (developer friendly way)
3. APIs in Microservice Architecture patterns
● Synchronous Communication
● Asynchronous Message-based Communication
3
4. MicroProfile and Microservice Basics
● Java for microservices-based architecture
● Portability across multiple runtimes
The following components are fundamental for developers creating microservices:
● Contexts and Dependency Injection for Java (CDI) specification
● Jakarta RESTful Web Services (JAX-RS)
● JSON processing
Using all three components, you can build basic RESTful web services in a straightforward and declarative
manner.
4
5. Quarkus advantage
Advantages compared to other Java-based cloud-native frameworks, Quarkus
offers the following benefits:
● Faster response times, in general.
● Lower memory usage.
● Higher throughout in reactive routes.
● Full container image support.
● Compliance to MicroProfile conformance tests.
5
7. Reviewing the JAX-RS Specification
JAX-RS, formerly known as Java API for RESTful Web Services, is a specification that provides support for creating web
services following the Representational State Transfer (REST) architectural pattern.
Annotation Description
@Path The relative path for a class or method.
@GET, @PUT,@POST, @DELETE,
@HEAD
The HTTP request type of a method.
@Produces, @Consumes The Internet media types for the content consumed as the request parameters or
produced as the response. The javax.ws.rs.core.MediaType class specifies the
allowed values.
Table 2.1. JAX-RS Class and Method-Level Annotations Summary
7
8. Demo #1
How do you get started with this??
Solution: https://quarkus.io/guides/getting-started and git clone https://github.com/quarkusio/quarkus-quickstarts.git
● Bootstrapping an application
● Creating a JAX-RS endpoint
● Injecting beans
● Functional tests
● Packaging of the application
How to create a Hello World API with Quarkus app
8
9. Demo #1
Bootstrapping the project
quarkus create app org.acme:getting-started
--extension='resteasy-reactive'
Different options to create your project:
● Maven
● https://code.quarkus.io/
● Quarkus CLI
mvn io.quarkus.platform:quarkus-maven-plugin:2.14.1.Final:create
-DprojectGroupId=org.acme
-DprojectArtifactId=getting-started
-Dextensions='resteasy-reactive'
Quarkus CLI installation https://quarkus.io/guides/cli-tooling
9
10. Demo #1
Quarkus scaffold project generated
It generates the following in ./getting-started:
● the Maven structure
● an org.acme.GreetingResource resource exposed on /hello
● an associated unit test
● a landing page that is accessible on http://localhost:8080 after starting the application
● example Dockerfile files for both native and jvm modes in src/main/docker
● the application configuration file
10
11. Demo #2
What if my backend fails?!
The recovery procedures defined by the fault tolerance specification include the following:
● Bulkhead (@org.eclipse.microprofile.faulttolerance.Bulkhead) Limits the workload for a microservice to
avoid failures caused by concurrency or service overload.
● Retry policy(@org.eclipse.microprofile.faulttolerance.Retry) Defines the conditions for retrying a failing
execution.
● Timeout(@org.eclipse.microprofile.faulttolerance.Timeout) Defines the maximum execution time
before interrupting a request.
● Circuit breaker (@org.eclipse.microprofile.faulttolerance.CircuitBreaker)Supports a fail-fast approach
if the system is suffering from an overload or is unavailable.
● Fallback(@org.eclipse.microprofile.faulttolerance.Fallback) Executes an alternative method if the
execution fails for the annotated method.
Source: https://quarkus.io/guides/smallrye-fault-tolerance 11
12. Demo #2
Fault tolerance - Fallback
@Fallback(fallbackMethod = "fallbackRecommendations")
public List<Coffee> recommendations(int id) {
...
}
public List<Coffee> fallbackRecommendations(int id) {
LOGGER.info("Falling back to
RecommendationResource#fallbackRecommendations()");
// safe bet, return something that everybody likes
return
Collections.singletonList(coffeeRepository.getCoffeeById(1));}
@Fallback(fallbackMethod = "fallbackRecommendations")
> quarkus dev
http://localhost:8080/coffee/2/recommendations
quarkus create app org.acme:microprofile-fault-tolerance-quickstart
--extension='smallrye-fault-tolerance,resteasy-reactive-jackson
--no-code
12
The application built in this guide simulates a simple
backend for a gourmet coffee e-shop. It
implements a REST endpoint providing information
about coffee samples we have on store.
In case of a timeout, the page will display a single
recommendation that we hardcoded in our fallback
method fallbackRecommendations(), rather than
two recommendations returned by the original
method.
13. Demo #3
I want to observe my u-services!
quarkus create app org.acme:opentelemetry-quickstart
--extension='resteasy-reactive,quarkus-opentelemetry'
--no-code
Source: https://quarkus.io/guides/opentelemetry
REST application to demonstrate distributed tracing.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry</artifactId>
</dependency>
13
14. Demo #3
Open Telemetry
The OpenTelemetry Collector offers a
vendor-agnostic implementation of how to
receive, process and export telemetry
data. It removes the need to run, operate,
and maintain multiple agents/collectors.
This works with improved scalability and
supports open-source observability data
formats (e.g. Jaeger, Prometheus, Fluent
Bit, etc.) sending to one or more
open-source or commercial back-ends.
14
16. Demo #4
How can I do simple troubleshooting?
As most developers would say, the first tool to troubleshoot when something goes wrong is logging (everything if
possible).
Quarkus offers JBoss Log Manager and the JBoss Logging facade for this purpose and all the logging configuration can
be done inside your application.properties
Applications and components may use any of the following APIs for logging, and the logs will be merged:
● JDK java.util.logging (also called JUL)
● JBoss Logging
● SLF4J
● Apache Commons Logging
It is possible to change the output format of the console log when for example the output of the application is captured
by a service which can, for example, process and store the log information for later analysis (JSON Logging Format)
16
Source:
https://quarkus.io/guides/rest-json
https://quarkus.io/guides/logging
17. Demo #4
Configuring Logging
We will start from a more comple REST example here
https://github.com/quarkusio/quarkus-quickstarts/tree/main/rest-json-quickstart
This includes: 2 REST resources, Ser/Des, a simple HTML frontend
It also already includes a Logging Filter automatically injected based on ContainerRequestFilter
(https://www.baeldung.com/jersey-filters-interceptors )
We will add more logging at the Resource level, to log as WARN if we add Tomato as a fruit
import org.jboss.logging.Logger;
…
private static final Logger LOG = Logger.getLogger(FruitResource.class);
…
if(fruit.name.equalsIgnoreCase("tomato")){
LOG.warn("Tomato is not a fruit");
}
17
18. Demo #5
Where to persist data?
Not every information can be stored only in memory, thinking about your amazon order and payment?
Quarkus provides many options to persist data, we will be highlighting the most important:
● Dev Service for DBs: when testing or running in dev mode Quarkus can provide you with a zero-config database
out of the box. Depending on your database type you may need Docker installed in order to use this feature.
Dev Services is supported for the following databases: DB2 (container) (requires license acceptance), Derby (in-process), H2 (in-process), MariaDB
(container), Microsoft SQL Server (container) (requires license acceptance), MySQL (container), Oracle Express Edition (container), PostgreSQL
(container)
● Simple datasource setup: a datasource can be either a JDBC datasource, a reactive one or both. It all depends on
how you configure it and which extensions you added to your project. To define a datasource, start by defining
the kind in the application.configuration. By using a JDBC driver extension and setting the kind in the
configuration, Quarkus resolves the JDBC driver automatically, so you don’t need to configure it yourself
● Support of both Hibernate ORM with Panache:
Hibernate ORM is an object–relational mapping tool for the Java programming language. It provides a framework for mapping an object-oriented domain
model to a relational database.
Panache is a Quarkus-specific library that simplifies the development of your Hibernate-based persistence layer. Similar to Spring Data JPA, Panache
handles most of the repetitive boilerplate code for you. Its implementations of the repository and the active record pattern provide methods to create,
update, and remove records, perform basic queries, and define and execute your own queries.
18
19. Demo #5
REST with persistence on Postgres container
We will start from a full example which cover everything we have seen in the previous slide
https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-orm-panache-quickstart
This includes: 1 Hibernate with Panache entity, the corresponding REST resource, all implementing the repository pattern
Panache’s repositories provide you with a set of standard methods to find entities by their primary key. You can also persist, update and remove an
entity. The only thing you need to do to get this functionality is to define an entity-specific repository class. It has to implement the
PanacheRepository or PanacheRepositoryBase interface.
We will just modify the configuration so that the db dev service port is fixed, and we can connect to it:
quarkus.datasource.devservices.port=45432
19
Source:
https://quarkus.io/guides/databases-dev-services
https://quarkus.io/guides/datasource
https://quarkus.io/guides/hibernate-orm-panache
https://quarkus.io/blog/quarkus-devservices-testcontainers-podman/
20. Demo #6
Somebody is bothering me with Security!
As you don’t want to expose your first valuable service publicly without any protection, you might want to think about
security.
Quarkus offers a full range of security options for your services:
● Basic and Form HTTP authentication
● WebAuthn is an authentication mechanism that replaces passwords. When you write a service for registering new users, or
logging them in, instead of asking for a password, you can use WebAuthn, which replaces the password.
● Quarkus also provides mutual TLS (mTLS) authentication so that you can authenticate users based on their X.509
certificates.
● OpenID Connect (OIDC) is an identity layer that works on top of the OAuth 2.0 protocol. OIDC enables client applications to
verify the identity of a user based on the authentication performed by the OIDC provider and to retrieve basic information
about that user. You can also verify ID and access JWT tokens by using the refreshable JSON Web Key (JWK) set or you can
introspect them remotely. However, opaque (binary) tokens can only be introspected remotely.
20
Source: https://quarkus.io/guides/security
21. Demo #6
OIDC security with Security Dev Services
https://github.com/quarkusio/quarkus-quickstarts/tree/main/security-openid-connect-quickstart
You can use the Quarkus OpenID Connect (OIDC) extension to secure your JAX-RS applications using Bearer Token
Authorization. The Bearer Tokens are issued by OIDC and OAuth 2.0 compliant authorization servers, such as Keycloak.
In this example, we are using a very simple microservice which offers two endpoints:
/api/users/me
/api/admin
These endpoints are protected and can only be accessed if a client is sending a bearer token along with the request,
which must be valid (e.g.: signature, expiration and audience) and trusted by the microservice.
The /api/users/me endpoint can be accessed by any user with a valid token. As a response, it returns a JSON document
with details about the user where these details are obtained from the information carried on the token.
The /api/admin endpoint is protected with RBAC (Role-Based Access Control) where only users granted with the admin
role can access. At this endpoint, we use the @RolesAllowed annotation to declaratively enforce the access constraint.
21
Source:
https://quarkus.io/guides/security-openid-connect
22. Demo #6
BONUS!
In case you can’t find that specific protocol or standard to integrate with inside the standard quarkus libraries,
You can explore the quarkiverse
For example in the case of security we have community support for MFA: https://github.com/quarkiverse/quarkus-mfa
22
Source:
https://quarkus.io/blog/quarkiverse/