SlideShare a Scribd company logo
MichelSchudel
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
What issues do Micronaut and Quarkus address?
• Lower memory footprint, faster startup
• Ahead-Of-Time (AOT) compilation
• Capability to build native images with GraalVM
• Designed from the ground up with
microservices in mind
• Built-in support for Fault Tolerance
• Monitoring / metrics
• Service discovery
• Cloud deployment
Project source
Website
Start/ Backed by
Github stars
#Contributors
Build tools
Languages
First Commit
github: micronaut-
project/micronaut-
core
micronaut.io
ObjectComputing
2.9K
163
Maven, Gradle
Java, Kotlin, Groovy
2017-03-16
github:
quarkusio/quarkus
quarkus.io
Red Hat
2.9K
175
Maven, Gradle
Java, Kotlin, Scala
2018-06-22
Round 1: Getting started
Round 2: Programming model
Round 3: Database persistency
Round 4: Test support
Round 5: Native images, startup and heap
The match
Conference application
Conference API
Conference Service
Conference RepositoryCountryClient
H2External country service
http(s)
GET /conferences
POST /conferences
{ “name”: “Devoxx”}
{ “name”: “Devoxx”}
{ “name”: “Devoxx”,
“countryName”: “Belgium”}
{ “countryName”: “Belgium”}/conf/{name}/country
GET /conferences-with-country
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Let’s start the applications!
mvn compile quarkus:dev
mvn package exec:exec
(or start the main class)
8100
8101
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
REST Controller
@Path("/conferences")
public class ConferenceResource {
@Inject
ConferenceService conferenceService;
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Conference> getAll() {
return conferenceService.getAll();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void create(Conference conference) {
conferenceService.create(conference);
}
@Controller("/conferences")
public class ConferenceController {
@Inject
ConferenceService conferenceService;
@Get
@Produces(MediaType.APPLICATION_JSON)
public List<Conference> getAll() {
return conferenceService.getAll();
}
@Post
@Consumes(MediaType.APPLICATION_JSON)
public void create(Conference conference) {
conferenceService.create(conference);
}
Conference API
Conference Service
RepoCountryClient
Conference service
@Singleton
public class ConferenceService {
@Inject
private ConferenceRepository conferenceRepository;
@Inject
CountryClient countryClient;
public List<Conference> getAll() {
return conferenceRepository.findAll();
}
public void create(Conference conference) {
conferenceRepository.save(conference);
}
@Singleton
public class ConferenceService {
@Inject
private ConferenceRepository conferenceRepository;
@Inject
@RestClient
CountryClient countryClient;
public List<Conference> getAll() {
return conferenceRepository.findAll();
}
public void create(Conference conference) {
conferenceRepository.save(conference);
}
Conference API
Conference Service
RepoCountryClient
@Path("/")
@RegisterRestClient
@Retry(maxRetries = 3, delay = 2)
@CircuitBreaker(successThreshold = 1)
public interface CountryClient {
@GET
@Path("/conferences/{name}/country")
Country getCountry(@PathParam("name") String name);
@Client("${country.service.url}")
@Retryable(attempts = “3", delay = "1s")
@CircuitBreaker(reset = "20s")
public interface CountryClient {
@Get("/conferences/{name}/country")
Country getCountry(String name);
mypackage.CountryClient/mp-rest/url=http://localhost:9000/
mypackage.CountryClient/mp-rest/scope=javax.inject.Singleton
country.service.url=http://localhost:9000/
application.properties application.properties / yml
Conference API
Conference Service
RepoCountryClient
REST client
Configuration
app.helloMessage=Hi there! app.helloMessage=Hi there!
application.properties application.properties / application.yml
@ConfigProperty(name = "app.helloMessage",
defaultValue="hello default!")
String helloMessage;
@ConfigProperties(prefix = "app")
public class ConferenceConfiguration {
@Size(min= 5)
public String helloMessage;
}
@Value("${app.helloMessage:hello default!}")
String helloMessage;
@ConfigurationProperties("app")
public class ConferenceConfiguration {
@Size(min = 5)
public String helloMessage;
}
@Property("app.helloMessage")
String helloMessage;
Configuration profiles
app.hello-message=Hi there!
%dev.app.hello-message=Hi from dev!
%test.app.hello-message=Hi from test!
%custom.app.hello-message=Hi from custom!
app.hello-message=Hi there!
application.properties application.properties / application.yml
• dev – during quarkus:dev unless
overridden
• test- during tests
• prod – default profile
• custom
mvnw quarkus:dev –Dquarkus.profile=test
application-test.properties / application-test.yml
app.hello-message=Hi from test!
mvnw exec:exec -Dmicronaut.environments=test
Custom Configuration
Create service file
/META-
INF/services/org.eclipse.microprofile.config.spi.ConfigSour
ce
public class CustomConfigSource implements ConfigSource {
@Override
public Map<String, String> getProperties() {
//my own implementation
return null;
}
@Override
public String getValue(String s) {
//my own implementation
return null;
}
@Override
public String getName() {
return "CustomConfigSource";
}
}
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-discovery-client</artifactId>
</dependency>
spring:
cloud:
config:
enabled: true
uri: http://localhost:8888/
micronaut:
config-client:
enabled: true
• HashiCorp Consul & Vault Support
• AWS Parameter Store Support
• Spring Cloud config server Support
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
JP
@Singleton
public class ConferenceRepository {
@Inject
EntityManager entityManager;
@Transactional
public List<Conference> findAll() {
TypedQuery<Conference> query = entityManager
.createQuery("select c from Conference c",
Conference.class);
return query.getResultList();
}
@Transactional
public void save(final Conference conference) {
entityManager.persist(conference);
}
}
@Singleton
public class ConferenceRepository {
@Inject
EntityManager entityManager;
@Transactional
public List<Conference> findAll() {
TypedQuery<Conference> query = entityManager
.createQuery("select c from Conference c",
Conference.class);
return query.getResultList();
}
@Transactional
public void save(final Conference conference) {
entityManager.persist(conference);
}
}
JPA persistency Conference API
Conference Service
RepoCountryClient
Improved Quarkus persistency with Panache
@Entity
public class Conference extends PanacheEntity {
private String name;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
@Singleton
public class ConferencePanacheRepository {
public List<Conference> findAll() {
return Conference.listAll();
}
@Transactional
public void save(final Conference conference) {
conference.persist();
}
}
Micronaut Data
@Repository
public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> {
List<Conference> findByName(String name);
List<Conference> listOrderByName();
List<Conference> listOrderByNameDesc();
List<Conference> findTop3ByNameLike(String name);
}
@Repository
public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> {
}
@JdbcRepository
public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> {
List<Conference> findByName(String name);
List<Conference> listOrderByName();
List<Conference> listOrderByNameDesc();
List<Conference> findTop3ByNameLike(String name);
}
No more
JPA / Hibernate needed!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Integration testing
@MicronautTest(environments = { "test" })
public class ConferenceITTest {
@Inject
EmbeddedServer embeddedServer;
@Test
@Transactional
public void testConferences() {
Conference conference = new Conference();
conference.setName("Devoxx");
given().body(conference)
.port(embeddedServer.getPort())
.contentType("application/json")
.when()
.post("/conferences")
.then()
.statusCode(200);
given().port(embeddedServer.getPort())
.when()
.get("/conferences")
.then()
.extract()
.path("[0].name")
.equals(“Devoxx");
}
application-test.yml
micronaut:
server:
port: -1
@QuarkusTest
public class ConferenceIT {
@Test
@Transactional
public void testConferences() {
Conference conference = new Conference();
conference.setName("Devoxx");
given().body(conference)
.contentType("application/json")
.when()
.post("/conferences")
.then()
.statusCode(204);
given()
.when()
.get("/conferences")
.then()
.extract()
.path("[0].name")
.equals("Devoxx");
}
quarkus.http.test-port=0
application.properties
Integration testing with Quarkus
@QuarkusTest
public class ConferenceIT {
@Inject
ConferenceResource conferenceResource;
@Test
public void testConferenceInternal() {
conferenceResource.getAll();
}
}
Testing internally
@Mock
@ApplicationScoped
@RestClient
public class MockCountryClient implements CountryClient {
@Override
public Country getCountryOfConference(String name) {
Country country = new Country();
country.setName("Belgium");
return country;
}
}
Mocking
@MicronautTest(environments = { "test" })
public class ConferenceITTest {
@Inject
private ConferenceController conferenceController;
@Test
public void testConferencesInternal() {
conferenceController.getAll();
}
@MockBean(CountryClient.class)
CountryClient countryClient() {
final CountryClient mock = Mockito.mock(CountryClient.class);
Country country = new Country();
country.setName("Belgium");
when(mock.getCountryOfConference(isA(String.class)))
.thenReturn(country);
return mock;
}
Integration testing native images
@SubstrateTest
public class NativeConferenceResourceIT extends ConferenceIT {
// Execute the same tests but in native mode.
}
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Building native images with GraalVM
./mvnw package –Pnative –Dnative-
image.docker-build=true
docker build -f
src/main/docker/Dockerfile.native –t
conference-service-quarkus .
./mvnw package
docker build . –t
conference-service-micronaut
Include feature native-imageNo additional actions needed
Let’s run the applications!
JVM: port 8100
Native: port 8200
JVM: port 8101
Native: port 8201
docker run -i --rm -p 8200:8080
conference-service-quarkus
docker run -i --rm -p 8201:8080
conference-service-quarkus-micronaut
https://medium.com/graalvm/lightweight-cloud-native-java-
applications-35d56bc45673
Research Oleg Šelajev (@shelajev)
https://medium.com/graalvm/lightweight-cloud-native-java-
applications-35d56bc45673
Research Oleg Šelajev (@shelajev)
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Summary
• Small images, faster startup,
lowest mem usage
• Microprofile Programming
model
• Really fast release cycle
• Close to Spring’s programming model
• Feels little more mature
• Micronaut Data
• More extensive support for existing
cloud environments
• Could do with a nicer
persistency solution
• Few of out-of-the-box
monitoring
• I’d like an initializer site!
MichelSchudel
https://github.com/MichelSchudel/conference-service-quarkus
https://github.com/MichelSchudel/conference-service-micronaut

More Related Content

PPTX
HOW AND WHY GRAALVM IS QUICKLY BECOMING RELEVANT FOR YOU
PPTX
Introduction to java 8 stream api
PDF
Spring Boot
PDF
Java 8 Lambda Expressions & Streams
PPTX
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
PDF
JavaScript Programming
PDF
Fundamental JavaScript [UTC, March 2014]
PDF
Introduction to RxJS
HOW AND WHY GRAALVM IS QUICKLY BECOMING RELEVANT FOR YOU
Introduction to java 8 stream api
Spring Boot
Java 8 Lambda Expressions & Streams
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
JavaScript Programming
Fundamental JavaScript [UTC, March 2014]
Introduction to RxJS

What's hot (20)

PDF
Deep Dive Java 17 Devoxx UK
PDF
Loom Virtual Threads in the JDK 19
PDF
TypeScript: coding JavaScript without the pain
PPTX
Hash table in java
PDF
GraalVM Native Images by Oleg Selajev @shelajev
PPTX
Spring Boot
PDF
Jvm分享20101228
PDF
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
PDF
JPA and Hibernate
PDF
Being Functional on Reactive Streams with Spring Reactor
PPTX
Dart ppt
PDF
Native Java with GraalVM
PDF
스위프트 성능 이해하기
PPT
Hibernate
PPTX
Java 8 Lambda and Streams
PDF
Lambda Expressions in Java
PPT
React js
PDF
Spring Framework - AOP
PPTX
JavaScript Engines and Event Loop
PPTX
Introduction to Spring & Spring BootFramework
Deep Dive Java 17 Devoxx UK
Loom Virtual Threads in the JDK 19
TypeScript: coding JavaScript without the pain
Hash table in java
GraalVM Native Images by Oleg Selajev @shelajev
Spring Boot
Jvm分享20101228
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
JPA and Hibernate
Being Functional on Reactive Streams with Spring Reactor
Dart ppt
Native Java with GraalVM
스위프트 성능 이해하기
Hibernate
Java 8 Lambda and Streams
Lambda Expressions in Java
React js
Spring Framework - AOP
JavaScript Engines and Event Loop
Introduction to Spring & Spring BootFramework
Ad

Similar to Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition! (20)

PDF
Microservices with Micronaut
PDF
Microservices with Micronaut
PDF
Microservices with Micronaut
PDF
Meetup 2022 - APIs with Quarkus.pdf
PDF
Micronaut Deep Dive - Devoxx Belgium 2019
PDF
Introduction to Micronaut
PDF
Introduction to Micronaut - JBCNConf 2019
PDF
Reactive microservices with Micronaut - GR8Conf EU 2018
PDF
Micronaut Deep Dive - Devnexus 2019
PDF
Introduction to Micronaut at Oracle CodeOne 2018
PPTX
Micronaut brainbit
PDF
"gRPC vs REST: let the battle begin!" GeeCON Krakow 2018 edition
PDF
Micronaut: Evolving Java for the Microservices and Serverless Era
PPTX
Micronaut: A new way to build microservices
PDF
"gRPC vs REST: let the battle begin!" OSCON 2018 edition
PDF
Micronaut Launchpad
PDF
A Microservices approach with Cassandra and Quarkus | DevNation Tech Talk
PDF
Reactive microservices with Micronaut - Greach 2018
PDF
Design Patterns para Microsserviços com MicroProfile
PDF
"gRPC vs REST: let the battle begin!" DevoxxUK 2018 edition
Microservices with Micronaut
Microservices with Micronaut
Microservices with Micronaut
Meetup 2022 - APIs with Quarkus.pdf
Micronaut Deep Dive - Devoxx Belgium 2019
Introduction to Micronaut
Introduction to Micronaut - JBCNConf 2019
Reactive microservices with Micronaut - GR8Conf EU 2018
Micronaut Deep Dive - Devnexus 2019
Introduction to Micronaut at Oracle CodeOne 2018
Micronaut brainbit
"gRPC vs REST: let the battle begin!" GeeCON Krakow 2018 edition
Micronaut: Evolving Java for the Microservices and Serverless Era
Micronaut: A new way to build microservices
"gRPC vs REST: let the battle begin!" OSCON 2018 edition
Micronaut Launchpad
A Microservices approach with Cassandra and Quarkus | DevNation Tech Talk
Reactive microservices with Micronaut - Greach 2018
Design Patterns para Microsserviços com MicroProfile
"gRPC vs REST: let the battle begin!" DevoxxUK 2018 edition
Ad

More from Michel Schudel (16)

PPTX
java 21 unleashed: exciting new features since java 17!
PPTX
Testing an onion architecture - done right
PPTX
What makes a high performance team tick?
PPTX
Atonomy of-a-tls-handshake-mini-conferentie
PPTX
Spring boot Under Da Hood
PPTX
Cryptography 101 for Java Developers - Devoxx 2019
PPTX
Cryptography 101 for_java_developers, Fall 2019
PPTX
Cryptography 101 for Java Developers - JavaZone2019
PPTX
Java n-plus-1-incl-demo-slides
PPTX
Cryptography 101 for Java developers
PPTX
Let's build a blockchain.... in 40 minutes!
PPTX
Cryptography 101 for Java developers
PPTX
Let's Build A Blockchain... in 40 minutes!
PPTX
What's new in Java 11
PPTX
Java 9 overview
PPTX
Test your microservices with REST-Assured
java 21 unleashed: exciting new features since java 17!
Testing an onion architecture - done right
What makes a high performance team tick?
Atonomy of-a-tls-handshake-mini-conferentie
Spring boot Under Da Hood
Cryptography 101 for Java Developers - Devoxx 2019
Cryptography 101 for_java_developers, Fall 2019
Cryptography 101 for Java Developers - JavaZone2019
Java n-plus-1-incl-demo-slides
Cryptography 101 for Java developers
Let's build a blockchain.... in 40 minutes!
Cryptography 101 for Java developers
Let's Build A Blockchain... in 40 minutes!
What's new in Java 11
Java 9 overview
Test your microservices with REST-Assured

Recently uploaded (20)

PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPT
Introduction Database Management System for Course Database
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Odoo POS Development Services by CandidRoot Solutions
PPTX
L1 - Introduction to python Backend.pptx
PPTX
ai tools demonstartion for schools and inter college
PDF
How Creative Agencies Leverage Project Management Software.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PPTX
Introduction to Artificial Intelligence
PPTX
history of c programming in notes for students .pptx
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Nekopoi APK 2025 free lastest update
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
System and Network Administraation Chapter 3
PPTX
Transform Your Business with a Software ERP System
Odoo Companies in India – Driving Business Transformation.pdf
How to Choose the Right IT Partner for Your Business in Malaysia
Introduction Database Management System for Course Database
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Odoo POS Development Services by CandidRoot Solutions
L1 - Introduction to python Backend.pptx
ai tools demonstartion for schools and inter college
How Creative Agencies Leverage Project Management Software.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Understanding Forklifts - TECH EHS Solution
Softaken Excel to vCard Converter Software.pdf
How to Migrate SBCGlobal Email to Yahoo Easily
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Introduction to Artificial Intelligence
history of c programming in notes for students .pptx
Navsoft: AI-Powered Business Solutions & Custom Software Development
Nekopoi APK 2025 free lastest update
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
System and Network Administraation Chapter 3
Transform Your Business with a Software ERP System

Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!

  • 3. What issues do Micronaut and Quarkus address? • Lower memory footprint, faster startup • Ahead-Of-Time (AOT) compilation • Capability to build native images with GraalVM • Designed from the ground up with microservices in mind • Built-in support for Fault Tolerance • Monitoring / metrics • Service discovery • Cloud deployment
  • 4. Project source Website Start/ Backed by Github stars #Contributors Build tools Languages First Commit github: micronaut- project/micronaut- core micronaut.io ObjectComputing 2.9K 163 Maven, Gradle Java, Kotlin, Groovy 2017-03-16 github: quarkusio/quarkus quarkus.io Red Hat 2.9K 175 Maven, Gradle Java, Kotlin, Scala 2018-06-22
  • 5. Round 1: Getting started Round 2: Programming model Round 3: Database persistency Round 4: Test support Round 5: Native images, startup and heap The match
  • 6. Conference application Conference API Conference Service Conference RepositoryCountryClient H2External country service http(s) GET /conferences POST /conferences { “name”: “Devoxx”} { “name”: “Devoxx”} { “name”: “Devoxx”, “countryName”: “Belgium”} { “countryName”: “Belgium”}/conf/{name}/country GET /conferences-with-country
  • 11. Let’s start the applications! mvn compile quarkus:dev mvn package exec:exec (or start the main class) 8100 8101
  • 14. REST Controller @Path("/conferences") public class ConferenceResource { @Inject ConferenceService conferenceService; @GET @Produces(MediaType.APPLICATION_JSON) public List<Conference> getAll() { return conferenceService.getAll(); } @POST @Consumes(MediaType.APPLICATION_JSON) public void create(Conference conference) { conferenceService.create(conference); } @Controller("/conferences") public class ConferenceController { @Inject ConferenceService conferenceService; @Get @Produces(MediaType.APPLICATION_JSON) public List<Conference> getAll() { return conferenceService.getAll(); } @Post @Consumes(MediaType.APPLICATION_JSON) public void create(Conference conference) { conferenceService.create(conference); } Conference API Conference Service RepoCountryClient
  • 15. Conference service @Singleton public class ConferenceService { @Inject private ConferenceRepository conferenceRepository; @Inject CountryClient countryClient; public List<Conference> getAll() { return conferenceRepository.findAll(); } public void create(Conference conference) { conferenceRepository.save(conference); } @Singleton public class ConferenceService { @Inject private ConferenceRepository conferenceRepository; @Inject @RestClient CountryClient countryClient; public List<Conference> getAll() { return conferenceRepository.findAll(); } public void create(Conference conference) { conferenceRepository.save(conference); } Conference API Conference Service RepoCountryClient
  • 16. @Path("/") @RegisterRestClient @Retry(maxRetries = 3, delay = 2) @CircuitBreaker(successThreshold = 1) public interface CountryClient { @GET @Path("/conferences/{name}/country") Country getCountry(@PathParam("name") String name); @Client("${country.service.url}") @Retryable(attempts = “3", delay = "1s") @CircuitBreaker(reset = "20s") public interface CountryClient { @Get("/conferences/{name}/country") Country getCountry(String name); mypackage.CountryClient/mp-rest/url=http://localhost:9000/ mypackage.CountryClient/mp-rest/scope=javax.inject.Singleton country.service.url=http://localhost:9000/ application.properties application.properties / yml Conference API Conference Service RepoCountryClient REST client
  • 17. Configuration app.helloMessage=Hi there! app.helloMessage=Hi there! application.properties application.properties / application.yml @ConfigProperty(name = "app.helloMessage", defaultValue="hello default!") String helloMessage; @ConfigProperties(prefix = "app") public class ConferenceConfiguration { @Size(min= 5) public String helloMessage; } @Value("${app.helloMessage:hello default!}") String helloMessage; @ConfigurationProperties("app") public class ConferenceConfiguration { @Size(min = 5) public String helloMessage; } @Property("app.helloMessage") String helloMessage;
  • 18. Configuration profiles app.hello-message=Hi there! %dev.app.hello-message=Hi from dev! %test.app.hello-message=Hi from test! %custom.app.hello-message=Hi from custom! app.hello-message=Hi there! application.properties application.properties / application.yml • dev – during quarkus:dev unless overridden • test- during tests • prod – default profile • custom mvnw quarkus:dev –Dquarkus.profile=test application-test.properties / application-test.yml app.hello-message=Hi from test! mvnw exec:exec -Dmicronaut.environments=test
  • 19. Custom Configuration Create service file /META- INF/services/org.eclipse.microprofile.config.spi.ConfigSour ce public class CustomConfigSource implements ConfigSource { @Override public Map<String, String> getProperties() { //my own implementation return null; } @Override public String getValue(String s) { //my own implementation return null; } @Override public String getName() { return "CustomConfigSource"; } } <dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-discovery-client</artifactId> </dependency> spring: cloud: config: enabled: true uri: http://localhost:8888/ micronaut: config-client: enabled: true • HashiCorp Consul & Vault Support • AWS Parameter Store Support • Spring Cloud config server Support
  • 22. JP @Singleton public class ConferenceRepository { @Inject EntityManager entityManager; @Transactional public List<Conference> findAll() { TypedQuery<Conference> query = entityManager .createQuery("select c from Conference c", Conference.class); return query.getResultList(); } @Transactional public void save(final Conference conference) { entityManager.persist(conference); } } @Singleton public class ConferenceRepository { @Inject EntityManager entityManager; @Transactional public List<Conference> findAll() { TypedQuery<Conference> query = entityManager .createQuery("select c from Conference c", Conference.class); return query.getResultList(); } @Transactional public void save(final Conference conference) { entityManager.persist(conference); } } JPA persistency Conference API Conference Service RepoCountryClient
  • 23. Improved Quarkus persistency with Panache @Entity public class Conference extends PanacheEntity { private String name; public String getName() { return name; } public void setName(final String name) { this.name = name; } @Singleton public class ConferencePanacheRepository { public List<Conference> findAll() { return Conference.listAll(); } @Transactional public void save(final Conference conference) { conference.persist(); } }
  • 24. Micronaut Data @Repository public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> { List<Conference> findByName(String name); List<Conference> listOrderByName(); List<Conference> listOrderByNameDesc(); List<Conference> findTop3ByNameLike(String name); } @Repository public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> { } @JdbcRepository public interface ConferenceCrudRepository extends CrudRepository<Conference, Long> { List<Conference> findByName(String name); List<Conference> listOrderByName(); List<Conference> listOrderByNameDesc(); List<Conference> findTop3ByNameLike(String name); } No more JPA / Hibernate needed!
  • 27. Integration testing @MicronautTest(environments = { "test" }) public class ConferenceITTest { @Inject EmbeddedServer embeddedServer; @Test @Transactional public void testConferences() { Conference conference = new Conference(); conference.setName("Devoxx"); given().body(conference) .port(embeddedServer.getPort()) .contentType("application/json") .when() .post("/conferences") .then() .statusCode(200); given().port(embeddedServer.getPort()) .when() .get("/conferences") .then() .extract() .path("[0].name") .equals(“Devoxx"); } application-test.yml micronaut: server: port: -1 @QuarkusTest public class ConferenceIT { @Test @Transactional public void testConferences() { Conference conference = new Conference(); conference.setName("Devoxx"); given().body(conference) .contentType("application/json") .when() .post("/conferences") .then() .statusCode(204); given() .when() .get("/conferences") .then() .extract() .path("[0].name") .equals("Devoxx"); } quarkus.http.test-port=0 application.properties
  • 28. Integration testing with Quarkus @QuarkusTest public class ConferenceIT { @Inject ConferenceResource conferenceResource; @Test public void testConferenceInternal() { conferenceResource.getAll(); } } Testing internally @Mock @ApplicationScoped @RestClient public class MockCountryClient implements CountryClient { @Override public Country getCountryOfConference(String name) { Country country = new Country(); country.setName("Belgium"); return country; } } Mocking @MicronautTest(environments = { "test" }) public class ConferenceITTest { @Inject private ConferenceController conferenceController; @Test public void testConferencesInternal() { conferenceController.getAll(); } @MockBean(CountryClient.class) CountryClient countryClient() { final CountryClient mock = Mockito.mock(CountryClient.class); Country country = new Country(); country.setName("Belgium"); when(mock.getCountryOfConference(isA(String.class))) .thenReturn(country); return mock; }
  • 29. Integration testing native images @SubstrateTest public class NativeConferenceResourceIT extends ConferenceIT { // Execute the same tests but in native mode. }
  • 32. Building native images with GraalVM ./mvnw package –Pnative –Dnative- image.docker-build=true docker build -f src/main/docker/Dockerfile.native –t conference-service-quarkus . ./mvnw package docker build . –t conference-service-micronaut Include feature native-imageNo additional actions needed
  • 33. Let’s run the applications! JVM: port 8100 Native: port 8200 JVM: port 8101 Native: port 8201 docker run -i --rm -p 8200:8080 conference-service-quarkus docker run -i --rm -p 8201:8080 conference-service-quarkus-micronaut
  • 40. Summary • Small images, faster startup, lowest mem usage • Microprofile Programming model • Really fast release cycle • Close to Spring’s programming model • Feels little more mature • Micronaut Data • More extensive support for existing cloud environments • Could do with a nicer persistency solution • Few of out-of-the-box monitoring • I’d like an initializer site!

Editor's Notes

  • #14: Quarkus uses @ConfigProperty from the microprofile specification. Properties are read from one application.properties file. Profiles are supported. There are three pofiles: dev, test and prod out-of-the-box, but you can specifiy more. Properties of all profiles have to be specified in either the application.properties (with % as prefix), or through jvm parameters (-D) Micronaut uses the @Value construction known from SpringBoot. Configuration profiles are supported and implemented by different property files like –T.yml. This seems a little more clear than with Quarkus. Moreso, micronaut supports integration with Spring Cloud Config server.
  • #22: Both quarkus and micronaut support Hibernate for database access, with automatic schema generation. Both frameworks support entity managers, no problem. But this feels a little... Well... Midlevel. Quarkus support Panache, which makes life a little bit easier. (show) Micronaut has Micronuat data (formerly predator), which is now on milestone 3. It has a programming model similair to Spring Data, where you can useto make declarative interfaces, as we will see now. Evenmore, you can use this so generate repos base don pure jdbc access, which is really cool. Definitely points to Micronaut here!
  • #25: Of course jdbc cannot do stuff like lazy loading, dirty checking, optimistic locking and stuff.
  • #27: Quarkus has the @QuarkusTest annotation which spins up a test version of the application. By default, it spins up on port 8081, so not a random port as we saw in Spring Boot, for example. Mock objects are supported for stubbing test clients. Micronaut has @MicronautTest annotation, same thing. Default is port 8081. Now, micronaut does not recieve the port binding automatically, so you have to set it yourself. Mocking is done through the @MockBean annotation, which you can use to specify any mock you want, for example with Mockito.
  • #32: You can start micronaut with a java –jar target\...jar command. Quarkus doesn’t build fat jars of the box, so if you want to do that, you need to specify the <uberJar> configuration in your maven-quarkus-plugin. If we start the application with java-jar, quarkus is notably quicker here then micronaut, but both are faster than SpringBoot. File size wise, there is not much difference. Quarkus fat jar is 42MB while Micronaut’s is 46MB, both definately smaller than any Spring Boot application that boast the same functionality. Mmemory usage: Quarkus: 425MB/176MB SpringBoot: 547MB/428MB Micronaut: 541MB/251MB Points go to Quarkus here.
  • #37: You can start micronaut with a java –jar target\...jar command. Quarkus doesn’t build fat jars of the box, so if you want to do that, you need to specify the <uberJar> configuration in your maven-quarkus-plugin. If we start the application with java-jar, quarkus is notably quicker here then micronaut, but both are faster than SpringBoot. File size wise, there is not much difference. Quarkus fat jar is 42MB while Micronaut’s is 46MB, both definately smaller than any Spring Boot application that boast the same functionality. Mmemory usage: Quarkus: 425MB/176MB SpringBoot: 547MB/428MB Micronaut: 541MB/251MB Points go to Quarkus here.
  • #38: You can start micronaut with a java –jar target\...jar command. Quarkus doesn’t build fat jars of the box, so if you want to do that, you need to specify the <uberJar> configuration in your maven-quarkus-plugin. If we start the application with java-jar, quarkus is notably quicker here then micronaut, but both are faster than SpringBoot. File size wise, there is not much difference. Quarkus fat jar is 42MB while Micronaut’s is 46MB, both definately smaller than any Spring Boot application that boast the same functionality. Mmemory usage: Quarkus: 425MB/176MB SpringBoot: 547MB/428MB Micronaut: 541MB/251MB Points go to Quarkus here.
  • #39: You can start micronaut with a java –jar target\...jar command. Quarkus doesn’t build fat jars of the box, so if you want to do that, you need to specify the <uberJar> configuration in your maven-quarkus-plugin. If we start the application with java-jar, quarkus is notably quicker here then micronaut, but both are faster than SpringBoot. File size wise, there is not much difference. Quarkus fat jar is 42MB while Micronaut’s is 46MB, both definately smaller than any Spring Boot application that boast the same functionality. Mmemory usage: Quarkus: 425MB/176MB SpringBoot: 547MB/428MB Micronaut: 541MB/251MB Points go to Quarkus here.