MICRONAUT LAUNCHPAD
From Ground Zero to Orbit!
ABOUT ME
• Senior Software Engineer at
OCI
• Full stack!
• Contributor to the Grails &
Micronaut frameworks
• Beth’s husband
• Micronaut announced in March 2018
• Framework open-sourced in May 2018,
1.0 release in October 2018
• Triggered a wave of excitement and
innovation around the potential for JVM
development
• Micronaut 1.3 & Micronaut Data 1.0
released in February 2020
• Micronaut continues to point the path
forwards for server-side Java
WHAT IS MICRONAUT?
WHAT IS MICRONAUT?
• A framework for microservice &
serverless applications
• Ahead Of Time (AOT) for DI,AOP, and
configuration injection
• Reactive HTTP layer built on Netty
• Declarative HTTP Client
• “Natively Cloud Native”
• A suite of official and community-
contributed integrations and libraries
WHAT CANYOU BUILD?
• Microservices
• Serverless Applications
• Message-Driven Applications with
Kafka/Rabbit
• CLI Applications
• Android Applications
• Anything with
static void main(String..args)
WHAT MAKES IT DIFFERENT?
• An Application Framework for the Future
• Ahead ofTime (AOT) Compilation
• No Reflection, Runtime Proxies, or Dynamic
Classloading
• Compatible with GraalVM
• Reactive
• Capable of running in low-memory
environments with sub second startup time
• First-class support for Java, Kotlin, and Groovy
WHAT MAKES IT DIFFERENT?
• Micronaut 1.3 - Cold Start:
• JDK 13 (no flags): ~800ms
• GraalVM native image: ~15ms
• Micronaut 1.3 - Memory:
• JDK 13: ~100mb
• GraalVM native image: ~15mb
DEMO
INSTALLINGTHE CLI
https://micronaut.io/download.html
• The Micronaut CLI is the
recommended method for creating
Micronaut apps
• Micronaut can also be added to an
existing project via Maven/Gradle
dependency
• Micronaut team recommends
SDKman for installing CLI, but other
options are available
• CLI can generate projects in Java,
Kotlin, Groovy, using Maven or
Gradle build files
INSTALLINGTHE CLI
1. Before continuing make sure you have latest version of SDKMAN
installed (https://sdkman.io/).
2. In order to install Micronaut, run following command:
3.You can also specify the version to the sdk install command.
4.You should now be able to run the Micronaut CLI.
$ mn
| Starting interactive mode...
| Enter a command name to run. Use TAB for completion:
mn>
$ sdk install micronaut 1.3.1
$ sdk install micronaut
$ sdk update
https://docs.micronaut.io/latest/guide/index.html#installSdkman
CREATING A SERVICE
mn> help
Usage: mn [-hnvVx] [COMMAND]
Micronaut CLI command line interface for generating projects and
services.
Commonly used commands are:
create-app NAME
create-cli-app NAME
create-federation NAME --services SERVICE_NAME[,SERVICE_NAME]...
create-function NAME
$ mn create-app service-a
| Generating Java project...
| Application created at /Users/dev/service-a
$ mn create-app example.micronaut.service-b
| Generating Java project...
| Application created at /Users/dev/service-b
Creating a Java app
Creating a Java app with default package
$ mn create-app service-k --lang kotlin --features tracing-jaeger
| Generating Kotlin project...
| Application created at /Users/dev/service-k
Creating a Kotlin app with features
CREATING A FEDERATION
The create-federation command applies the same
features/profiles to multiple projects, and creates a multi-
project (Gradle) or multi-module (Maven) build file.
$ mn create-federation kafka-fed --services service-a, service-b,
service-c --profile kafka
| Federation created at /Users/dev/kafka-federation
| Generating Java project…
| Generating Java project…
| Generating Java project...
POWER ON
$ cd service-a
$ ./gradlew run
> Task :run
[main] INFO io.micronaut.runtime.Micronaut - Startup completed in
955ms. Server Running: http://localhost:8080
$./mvnw compile exec:exec
[INFO] --- exec-maven-plugin:1.6.0:exec (default-cli) @ service-a ---
[main] INFO io.micronaut.runtime.Micronaut - Startup completed in
778ms. Server Running: http://localhost:8080
HOT RESTART
1. Enable with micronaut.io.watch.restart: true in
configuration properties
2. Run Gradle or Maven (via shell script) in
continuous build mode
(Alternatively, an external library like JRebel or Spring Loaded can be used -
the CLI includes features for all of these options)
HOT RESTART
$ mn create-app service-a --features file-watch
configurations {
developmentOnly
}
dependencies {
developmentOnly "io.micronaut:micronaut-runtime-osx"
developmentOnly "net.java.dev.jna:jna"
developmentOnly "io.methvin:directory-watcher"
}
run.classpath += configurations.developmentOnly
build.gradle
…or add configuration/dependencies manually:
micronaut:
io:
watch:
paths: src/main
restart: true
src/main/resources/application.yml
HOT RESTART
$ gradle run --continuous
#!/usr/bin/env sh
while true; do
./mvn compile exec:exec
sleep 1s
done
With file-watch enabled, run Gradle in continuous build mode…
If using Maven, a simple shell script accomplishes the same goal.
The result: the Micronaut application is restarted when a file change is
detected, making development time changes a breeze!
HELLO WORLD
package example.micronaut;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
@Controller("/hello")
public class HelloController {
@Get
@Produces(MediaType.TEXT_PLAIN)
public String index() {
return "Hello World";
}
}
src/main/java/example/micronaut/HelloController.java
TEST FLIGHT
@MicronautTest
public class HelloControllerTest {
@Inject @Client(“/") RxHttpClient client;
@Test public void testHello() {
HttpRequest<String> request = HttpRequest.GET("/hello");
String body = client.toBlocking().retrieve(request);
assertNotNull(body);
assertEquals("Hello World", body);
}
}
src/test/java/example/micronaut/HelloControllerTest.java
$ ./gradlew test
$ open build/reports/tests/test/index.html
Running tests and viewing results:
DEPENDENCY INJECTION
• Micronaut’s DI implements JSR 330 (javax.inject annotations)
• Beans can be injected via @Inject or as constructor arguments
• At compile-time, Micronaut analyzes your classes and generates bean
definition classes that implement the required DI logic
• Aspect Oriented Programming (AOP) capabilities are analyzed and
generated in the same way
• The result: runtime reflection and reading/caching of metadata is
avoided, leading to drastic improvements in startup and memory
usage
DEPENDENCY INJECTION
@Singleton //Bean definition generated at compile time
class WeatherService {
Integer currentTemp() { //... }
}
@Controller('/weather')
class WeatherController {
@Inject WeatherService weatherService
//DI computed at compile time
@Get("/")
HttpResponse<Integer> currentTemp() {
HttpResponse.ok(weatherService.currentTemp())
}
}
DEPENDENCY INJECTION
• Micronaut creates and manages a BeanContext
• In addition to beans, Optionals, Iterables, Streams, Arrays & Providers
can also be injected
• Qualifiers can be applied to injected beans (e.g, @Named)
• Bean scopes as specified by JSR 330 (@Singleton, @RequestScope,
@Refreshable, @ThreadLocal, etc)
• Bean instantiation can be made @Conditional (on configuration, other
beans, etc) and @Fallbacks can be specified when a bean cannot be
created
CLIENTS
@Client("/hello")
public interface HelloClient {
@Get
String hello();
}
src/main/java/example/micronaut/HelloClient.java
@Inject HelloClient client();
public String greeting() {
return client.hello();
}
Client can now be injected and called:
CLIENTS
@Client("https://api.twitter.com/1.1")
@Client("${my.serverUrl:`http://localhost:8080`}")
@Client("service-a")
Fixed absolute URL
Configuration property (with optional default)
Service ID (from a service discovery registry)
SERVICE DISCOVERY
• Micronaut supports multiple approaches to service discovery:
• DNS-based configuration
• Standalone discovery server (e.g, Consul, Eureka, ZooKeeper)
• Delegation to a cloud provider (e.g.,AWS Route 53)
• Delegation to a container runtime (e.g, Kubernetes)
• Micronaut abstracts the integration with specific service discovery registries
through a DiscoveryClient interface
• When multiple instances of a given service are registered, Micronaut will
automatically load-balance between them
https://guides.micronaut.io/micronaut-microservices-services-discover-consul
https://guides.micronaut.io/micronaut-microservices-services-discover-consul
https://guides.micronaut.io/micronaut-microservices-services-discover-consul
SERVICE DISCOVERY
$ mn create-app service-a --features discovery-consul
| Generating Java project...
| Application created at /Users/dev/service-a
implementation ‘io.micronaut:micronaut-discovery-client'
build.gradle …or add dependency manually:
SERVICE DISCOVERY
src/main/resources/application.yml
micronaut:
application:
name: service-a
consul:
client:
registration:
enabled: true
defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
$ docker run -p 8500:8500 consul:1.2.4
Start up Consul with Docker
RETRYING & CIRCUIT BREAKERS
• Micronaut provides annotations to specify behavior when a
method call fails (such as a loss of connection with another service)
• @Retryable indicates that the method call should be re-attempted
for a configurable number of times, before throwing an exception
@Retryable(
attempts = “5",
delay = “2s"
)
public Book findBook(String title) { //...
@Retryable(attempts = "${book.retry.attempts:3}",
delay = "${book.retry.delay:1s}" )
RETRYING & CIRCUIT BREAKERS
• @CircuitBreaker is a variation of @Retryable which (after a set
number of failures) will instantly re-throw the exception without
waiting for the method to fail.
• This allows an external service or resource time to recover (e.g,
an overloaded database server)
@CircuitBreaker(
attempts = “5",
delay = “2s”
reset = “30s”
)
public Book findBook(String title) { //...
CONFIGURATION
Micronaut apps can accept configuration from a variety of
sources:
• Configuration files (accepted formats are properties files,YAML,
JSON, Groovy; e.g: /src/main/resources/application.yml)
• System properties/Environment variables
• Distributed configuration (e.g Consul, Spring Cloud Config,
AWS Parameter Store)
CONFIGURATION
micronaut:
application:
name: service-a
---
consul:
client:
registration:
enabled: true
defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
---
datasources:
default:
url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
driverClassName: org.h2.Driver
username: sa
password: ''
dialect: H2
src/main/resources/application.yml
CONFIGURATION
@Singleton
public class EngineImpl implements Engine {
@Value("${my.engine.cylinders:6}")
protected int cylinders;
//...
}
src/main/java/EngineImpl.java
@Value("http://${my.host}:${my.port}")
URL url;
@Value("${my.url:`http://foo.com`}")
URL url;
Multiple placeholders
Default value
CONFIGURATION PROPERTIES
team:
name: 'Steelers'
color: 'Black'
player-names:
- 'Mason Rudolph'
- 'James Connor'
src/main/resources/application.yml
@ConfigurationProperties("team")
public class TeamConfiguration {
private String name;
private String color;
private List<String> playerNames;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public List<String> getPlayerNames() {
return playerNames;
}
public void setPlayerNames(List<String> playerNames) {
this.playerNames = playerNames;
}
}
https://guides.micronaut.io/micronaut-configuration
src/main/java/TeamConfiguration.java
@Inject
TeamConfiguration config;
@Get
public String index() {
return config.getName();
}
src/main/java/TeamController.java
The above config can now be
injected as a configuration bean:
DISTRIBUTED CONFIGURATION
• Micronaut provides a ConfigurationClient
interface which can resolve config from
distributed (cloud) sources
• Integrations available for Consul,Vault,
Spring Cloud Config, and AWS Parameter
Store Support
• Can be setup via a CLI feature or
manually
DISTRIBUTED CONFIGURATION
$ mn create-app service-a --features config-consul
…or add the configuration manually in a file named bootstrap.yml:
micronaut:
application:
name: service-a
config-client:
enabled: true
consul:
client:
defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
src/main/resources/bootstrap.yml
$ curl -X PUT -d @- localhost:8500/v1/kv/config/application/foo.bar <<< myvalue
We can now populate our Consul config service - the key foo.bar will contain the value myvalue
MONITORING
• Micronaut’s management module provides endpoint for health checks and other
monitoring needs
• Also provides API for implementing custom health checks and endpoints
• Built-in endpoints include:
• /beans — Returns loaded bean definitions from the application context
• /info — Returns static information from the application state
• /health — Returns information about the health of the application
• /metrics — Return application metrics *
• /routes — Returns available URIs in the application
• /loggers — Returns available loggers and allows change of log level
• /stop — Shuts down server on receiving a POST request
* Requires additional Micrometer metrics dependency
MONITORING
$ mn create-app service-a --features management
implementation 'io.micronaut:micronaut-management'
build.gradle
…or add dependency manually:
micronaut:
security:
enabled: true
endpoints:
beans:
enabled: true
sensitive: true
info:
enabled: true
sensitive: false
src/main/resources/application.yml
If the micronaut-security
dependency is loaded, endpoints can
be marked as “sensitive” to secure
private information
https://micronaut-projects.github.io/micronaut-security
MONITORING
DISTRIBUTEDTRACING
• Micronaut provides distributed tracing
support for the OpenTracing spec (any
implementation)
• Allows “spans” to be defined at the
method and class-level via annotations
• Also defines an instance of the
io.opentracing.Tracer interface for
complete functionality
• Integration with Jaeger and Zipkin
available via CLI features
DISTRIBUTEDTRACING
$ mn create-app service-a --features tracing-zipkin //or tracing-jaeger
implementation 'io.micronaut:micronaut-tracing'
runtime 'io.zipkin.brave:brave-instrumentation-http'
runtime 'io.zipkin.reporter2:zipkin-reporter'
implementation 'io.opentracing.brave:brave-opentracing'
build.gradle …or add dependencies manually:
tracing:
jaeger:
enabled: true
sampler:
probability: 0.5
src/main/resources/application.yml
https://guides.micronaut.io/micronaut-microservices-distributed-tracing-jaeger
$ docker run -d -p 9411:9411 
openzipkin/zipkin
Start up the Zipkin “collector" via Docker:
DISTRIBUTEDTRACING
@NewSpan("productList")
List<Product> productList() {
//Get products
}
@ContinueSpan
@Get(“/{id}”)
HttpResponse<Product> show(Long id) {
//Get product
}
@Get("/{productNumber}")
HttpResponse<Integer> hits(
@SpanTag("product") String product
) {}
• @NewSpan begins a new
tracing segment at this
method
• @ContinueSpan includes
this method within the
current span
• @SpanTag allows metadata
to be added to the (new
or current) span
DISTRIBUTEDTRACING
import io.opentracing.Tracer
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class StorefrontService {
@Inject
Tracer tracer
@NewSpan("productList")
List<ProductDetails> productList() {
products = //Get products
tracer.activeSpan().setTag("count", products.size())
products
}
Micronaut defines an instance of OpenTracing’s Tracer interface as a bean
DISTRIBUTEDTRACING
Tracing providers (Zipkin in this example) usually include a
web-based UI for viewing and interacting with tracing data
API DOCUMENTATION
• Micronaut can generate OpenAPI (Swagger)YAML
definitions at compilation time
• Standard Micronaut annotations (@Controller, @Get,
@Consumes, etc) and method return types (POJOs) will be
analyzed and corresponding SwaggerYML written to the file
• Standard Swagger annotations can be used to customize/
override the generatedYAML
• Micronaut can handle merging of OpenAPI schemas from
multiple modules (e.g., when using Micronaut Security)
API DOCUMENTATION
$ mn create-app service-a --features swagger-java
annotationProcessor("io.micronaut.configuration:micronaut-openapi:1.4.0")
implementation("io.swagger.core.v3:swagger-annotations:1.4.0")
build.gradle …or add dependencies manually:
@OpenAPIDefinition(
info = @Info(
title = "Hello World",
version = "0.0",
description = "My API",
license = @License(name = "Apache 2.0", url = "http://foo.bar"),
contact = @Contact(
url = "http://gigantic-server.com",
name = "Fred",
email = “Fred@gigagantic-server.com"
)
)
)
src/main/java/Application.java
Add an @OpenAPIDefinition
for your app:
API DOCUMENTATION
https://dzone.com/articles/a-quick-guide-to-microservices-with-the-micronaut
micronaut:
router:
static-resources:
swagger:
paths: classpath:META-INF/swagger
mapping: /swagger/**
src/main/resources/application.yml
Configuration to expose Swagger
YAML over the server:
MICRONAUT SPRING
https://micronaut-projects.github.io/micronaut-spring/latest/
• Allows Spring components to be integrated into Micronaut
apps*
• Allows a Spring app to be run as a Micronaut app
• Expose Micronaut beans to a Spring app
• At compilation time, Micronaut maps supported Spring
annotations to corresponding Micronaut ones
• Certain Spring interfaces are also mapped at compile time and
can be used (ApplicationContext, Environment, BeanFactory, etc)
MICRONAUT SPRING
https://micronaut-projects.github.io/micronaut-spring/latest/
• Micronaut for Spring can serve as a “parent context”
for a Spring app, making components written in
Micronaut (e.g, the Kafka client, Discovery client, etc)
available to the Spring context
• Most Spring Boot annotations are supported
(@ConfigurationProperties, @ConditionalOn*, @Endpoint)
• Limitations:AspectJ, SpEL, and Servlet API are not
supported by Micronaut
MICRONAUT DATA
https://micronaut-projects.github.io/micronaut-data/latest
• A persistence framework written especially for Micronaut
• Uses AOT compilation to pre-compute queries, provide
type-checking
• No runtime reflection, no in-memory model, and no
runtime query generation
• Supports Reactive query execution (Publisher or RxJava)
MICRONAUT DATA
https://micronaut-projects.github.io/micronaut-data/latest
package example;
import io.micronaut.data.annotation.*;
import io.micronaut.data.model.*;
import io.micronaut.data.repository.CrudRepository;
import java.util.List;
@Repository
interface BookRepository extends CrudRepository<Book, Long> {
Book find(String title);
}
Tomorrow in this room (411) at 10:20AM
BUILDING FOR PRODUCTION
• Micronaut apps can be built as “fat” (or “uber”) JAR
files using the Gradle Shadow Jar plugin or Maven
Shade plugin (provided automatically by the CLI).
$ ./gradlew shadowJar
$ ./mvnw package
$ java -jar build/libs/service-a-all.jar
Application can now be deployed as a runnable JAR:
GRAALVM
• GraalVM is an alternativeVM that
provides native image capability and
minimal overhead
• Micronaut applications can be
configured to run within a GraalVM
native image using a provided script
• Micronaut’s avoidance of reflection
makes it a perfect choice for apps
targeting GraalVM
GRAALVM
$ mn create-app service-a --features graal-native-image
Use the CLI feature to generate config and Dockerfile:
$ ./gradlew assemble
$ ./docker-build.sh
Build JAR file and run the provided build script to build image:
$ docker run -p 8080:8080 micronaut-graal-app
10:29:46.845 [main] INFO io.micronaut.runtime.Micronaut - Startup completed
in 12ms. Server Running: http://localhost:8080
The application can now be run by executing the native image:
TOTHE CLOUD
• Micronaut provides integration and
environment-detection for numerous cloud
platforms
• Cloud-specific configuration can be applied
with application-[provider].yml files (e.g.,
application-gcp.yml)
• Can also use Groovy config files if imperative
logic is required - e.g, obtaining values from a
distributed config server
AMAZON WEB SERVICES
https://guides.micronaut.io/micronaut-elasticbeanstalk
• Micronaut supports AWS specific
configuration (e.g, application-aws.yml files)
• Also includes a CLI profile for creating AWS
Lambda applications (functions)
• Consult Micronaut Guides website for
tutorials on deploying to AWS Elastic
Beanstalk and Lambda
https://guides.micronaut.io/micronaut-function-graalvm-aws-lambda-gateway
MICROSOFT AZURE
https://github.com/microsoft/azure-maven-plugins
• Micronaut supports Azure specific
configuration (e.g, application-azure.yml files)
• Microsoft provides a Maven plugin to facilitate
Azure deployments (community-supported
Gradle plugin also available)
• Consult Micronaut Guides website for
tutorials on deploying to Microsoft Azure
https://guides.micronaut.io/micronaut-azure-cloud/guide/index.html
GOOGLE CLOUD
• (Assuming a properly configured GCP
project)
• The simplest approach is to use
Google’s own App Engine Gradle Plugin
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.2.0'
}
}
apply plugin: 'com.google.cloud.tools.appengine'
build.gradle
GOOGLE CLOUD
ext {
appEngineProjectVersion = project.version
appEngineProjectId = 'calm-history-228704'
}
appengine {
stage.artifact = "${buildDir}/libs/${project.name}-${project.version}-all.jar"
deploy {
projectId = appEngineProjectId
version = appEngineProjectVersion
}
}
build.gradle
runtime: java
env: flex
src/main/appengine/app.yml
Minimal GAE config:
https://guides.micronaut.io/micronaut-gradle-google-cloud
https://cloud.google.com/appengine/docs/standard/java/tools/gradle
https://cloud.google.com/appengine/docs/standard/java/config/appref
GOOGLE CLOUD
$ ./gradlew appengineDeploy
Deployed service [default] to [https://calm-
history-228704.appspot.com]
You can stream logs from the command line by
running:
$ gcloud app logs tail -s default
To view your application in the web browser run:
$ gcloud app browse
BUILD SUCCESSFUL in 7m 26s
13 actionable tasks: 11 executed, 2 up-to-date
$ curl https://calm-history-228704.appspot.com
Micronaut on App Engine
https://guides.micronaut.io/micronaut-gradle-google-cloud
DEMO
AND MORE…
• Micronaut Kafka
• Micronaut Kubernetes
• Micronaut JAX-RS
• Micronaut PicoCLI
• Micronaut Kotlin
• Micronaut Micrometer
• Micronaut Security
• Micronaut Elasticsearch
• Micronaut Flyway
• Micronaut Cassandra
• Micronaut RabbitMQ
• Micronaut GraphQL
SUMMARY
• Micronaut is a full-featured framework designed
for modern cloud-based architectures
• Offers a slew of features that are useful in almost
every sort of application (not just microservices!)
• Micronaut is actively evolving and new capabilities
and integrations are being developed as we speak
• Micronaut community is growing and is super
helpful - join the Gitter channel! https://gitter.im/
micronautfw/
RESOURCES
• https://micronaut.io
• https://github.com/micronaut-projects
• User Guide: https://docs.micronaut.io
• Micronaut Guides: https://
guides.micronaut.io
• Awesome Micronaut: https://github.com/
JonasHavers/awesome-micronaut
MICRONAUT PETSTORE
https://github.com/micronaut-projects/micronaut-examples/
JOINTHE GITTER COMMUNITY
https://gitter.im/micronautfw/
© 2019, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
71
Events:
● objectcomputing.com/events
Training:
● objectcomputing.com/training
● grailstraining.com
● micronauttraining.com
Or email info@ocitraining.com to schedule a custom training program for
your team online, on site, or in our state-of-the-art, Midwest training lab.
LEARN MORE ABOUT OCI EVENTS AND TRAINING
THANK YOU!
Zachary Klein
@ZacharyAKlein
kleinz@objectcomputing.com
Come visit our booth! Just
outside of room 307 in the
main vendor hall

Micronaut Launchpad

  • 1.
  • 2.
    ABOUT ME • SeniorSoftware Engineer at OCI • Full stack! • Contributor to the Grails & Micronaut frameworks • Beth’s husband
  • 4.
    • Micronaut announcedin March 2018 • Framework open-sourced in May 2018, 1.0 release in October 2018 • Triggered a wave of excitement and innovation around the potential for JVM development • Micronaut 1.3 & Micronaut Data 1.0 released in February 2020 • Micronaut continues to point the path forwards for server-side Java WHAT IS MICRONAUT?
  • 5.
    WHAT IS MICRONAUT? •A framework for microservice & serverless applications • Ahead Of Time (AOT) for DI,AOP, and configuration injection • Reactive HTTP layer built on Netty • Declarative HTTP Client • “Natively Cloud Native” • A suite of official and community- contributed integrations and libraries
  • 6.
    WHAT CANYOU BUILD? •Microservices • Serverless Applications • Message-Driven Applications with Kafka/Rabbit • CLI Applications • Android Applications • Anything with static void main(String..args)
  • 7.
    WHAT MAKES ITDIFFERENT? • An Application Framework for the Future • Ahead ofTime (AOT) Compilation • No Reflection, Runtime Proxies, or Dynamic Classloading • Compatible with GraalVM • Reactive • Capable of running in low-memory environments with sub second startup time • First-class support for Java, Kotlin, and Groovy
  • 8.
    WHAT MAKES ITDIFFERENT? • Micronaut 1.3 - Cold Start: • JDK 13 (no flags): ~800ms • GraalVM native image: ~15ms • Micronaut 1.3 - Memory: • JDK 13: ~100mb • GraalVM native image: ~15mb
  • 9.
  • 10.
    INSTALLINGTHE CLI https://micronaut.io/download.html • TheMicronaut CLI is the recommended method for creating Micronaut apps • Micronaut can also be added to an existing project via Maven/Gradle dependency • Micronaut team recommends SDKman for installing CLI, but other options are available • CLI can generate projects in Java, Kotlin, Groovy, using Maven or Gradle build files
  • 11.
    INSTALLINGTHE CLI 1. Beforecontinuing make sure you have latest version of SDKMAN installed (https://sdkman.io/). 2. In order to install Micronaut, run following command: 3.You can also specify the version to the sdk install command. 4.You should now be able to run the Micronaut CLI. $ mn | Starting interactive mode... | Enter a command name to run. Use TAB for completion: mn> $ sdk install micronaut 1.3.1 $ sdk install micronaut $ sdk update https://docs.micronaut.io/latest/guide/index.html#installSdkman
  • 12.
    CREATING A SERVICE mn>help Usage: mn [-hnvVx] [COMMAND] Micronaut CLI command line interface for generating projects and services. Commonly used commands are: create-app NAME create-cli-app NAME create-federation NAME --services SERVICE_NAME[,SERVICE_NAME]... create-function NAME
  • 13.
    $ mn create-appservice-a | Generating Java project... | Application created at /Users/dev/service-a $ mn create-app example.micronaut.service-b | Generating Java project... | Application created at /Users/dev/service-b Creating a Java app Creating a Java app with default package $ mn create-app service-k --lang kotlin --features tracing-jaeger | Generating Kotlin project... | Application created at /Users/dev/service-k Creating a Kotlin app with features
  • 14.
    CREATING A FEDERATION Thecreate-federation command applies the same features/profiles to multiple projects, and creates a multi- project (Gradle) or multi-module (Maven) build file. $ mn create-federation kafka-fed --services service-a, service-b, service-c --profile kafka | Federation created at /Users/dev/kafka-federation | Generating Java project… | Generating Java project… | Generating Java project...
  • 15.
    POWER ON $ cdservice-a $ ./gradlew run > Task :run [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 955ms. Server Running: http://localhost:8080 $./mvnw compile exec:exec [INFO] --- exec-maven-plugin:1.6.0:exec (default-cli) @ service-a --- [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 778ms. Server Running: http://localhost:8080
  • 16.
    HOT RESTART 1. Enablewith micronaut.io.watch.restart: true in configuration properties 2. Run Gradle or Maven (via shell script) in continuous build mode (Alternatively, an external library like JRebel or Spring Loaded can be used - the CLI includes features for all of these options)
  • 17.
    HOT RESTART $ mncreate-app service-a --features file-watch configurations { developmentOnly } dependencies { developmentOnly "io.micronaut:micronaut-runtime-osx" developmentOnly "net.java.dev.jna:jna" developmentOnly "io.methvin:directory-watcher" } run.classpath += configurations.developmentOnly build.gradle …or add configuration/dependencies manually: micronaut: io: watch: paths: src/main restart: true src/main/resources/application.yml
  • 18.
    HOT RESTART $ gradlerun --continuous #!/usr/bin/env sh while true; do ./mvn compile exec:exec sleep 1s done With file-watch enabled, run Gradle in continuous build mode… If using Maven, a simple shell script accomplishes the same goal. The result: the Micronaut application is restarted when a file change is detected, making development time changes a breeze!
  • 19.
    HELLO WORLD package example.micronaut; importio.micronaut.http.MediaType; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.Produces; @Controller("/hello") public class HelloController { @Get @Produces(MediaType.TEXT_PLAIN) public String index() { return "Hello World"; } } src/main/java/example/micronaut/HelloController.java
  • 20.
    TEST FLIGHT @MicronautTest public classHelloControllerTest { @Inject @Client(“/") RxHttpClient client; @Test public void testHello() { HttpRequest<String> request = HttpRequest.GET("/hello"); String body = client.toBlocking().retrieve(request); assertNotNull(body); assertEquals("Hello World", body); } } src/test/java/example/micronaut/HelloControllerTest.java $ ./gradlew test $ open build/reports/tests/test/index.html Running tests and viewing results:
  • 21.
    DEPENDENCY INJECTION • Micronaut’sDI implements JSR 330 (javax.inject annotations) • Beans can be injected via @Inject or as constructor arguments • At compile-time, Micronaut analyzes your classes and generates bean definition classes that implement the required DI logic • Aspect Oriented Programming (AOP) capabilities are analyzed and generated in the same way • The result: runtime reflection and reading/caching of metadata is avoided, leading to drastic improvements in startup and memory usage
  • 22.
    DEPENDENCY INJECTION @Singleton //Beandefinition generated at compile time class WeatherService { Integer currentTemp() { //... } } @Controller('/weather') class WeatherController { @Inject WeatherService weatherService //DI computed at compile time @Get("/") HttpResponse<Integer> currentTemp() { HttpResponse.ok(weatherService.currentTemp()) } }
  • 23.
    DEPENDENCY INJECTION • Micronautcreates and manages a BeanContext • In addition to beans, Optionals, Iterables, Streams, Arrays & Providers can also be injected • Qualifiers can be applied to injected beans (e.g, @Named) • Bean scopes as specified by JSR 330 (@Singleton, @RequestScope, @Refreshable, @ThreadLocal, etc) • Bean instantiation can be made @Conditional (on configuration, other beans, etc) and @Fallbacks can be specified when a bean cannot be created
  • 24.
    CLIENTS @Client("/hello") public interface HelloClient{ @Get String hello(); } src/main/java/example/micronaut/HelloClient.java @Inject HelloClient client(); public String greeting() { return client.hello(); } Client can now be injected and called:
  • 25.
  • 26.
    SERVICE DISCOVERY • Micronautsupports multiple approaches to service discovery: • DNS-based configuration • Standalone discovery server (e.g, Consul, Eureka, ZooKeeper) • Delegation to a cloud provider (e.g.,AWS Route 53) • Delegation to a container runtime (e.g, Kubernetes) • Micronaut abstracts the integration with specific service discovery registries through a DiscoveryClient interface • When multiple instances of a given service are registered, Micronaut will automatically load-balance between them
  • 27.
  • 28.
  • 29.
  • 30.
    SERVICE DISCOVERY $ mncreate-app service-a --features discovery-consul | Generating Java project... | Application created at /Users/dev/service-a implementation ‘io.micronaut:micronaut-discovery-client' build.gradle …or add dependency manually:
  • 31.
    SERVICE DISCOVERY src/main/resources/application.yml micronaut: application: name: service-a consul: client: registration: enabled:true defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}" $ docker run -p 8500:8500 consul:1.2.4 Start up Consul with Docker
  • 32.
    RETRYING & CIRCUITBREAKERS • Micronaut provides annotations to specify behavior when a method call fails (such as a loss of connection with another service) • @Retryable indicates that the method call should be re-attempted for a configurable number of times, before throwing an exception @Retryable( attempts = “5", delay = “2s" ) public Book findBook(String title) { //... @Retryable(attempts = "${book.retry.attempts:3}", delay = "${book.retry.delay:1s}" )
  • 33.
    RETRYING & CIRCUITBREAKERS • @CircuitBreaker is a variation of @Retryable which (after a set number of failures) will instantly re-throw the exception without waiting for the method to fail. • This allows an external service or resource time to recover (e.g, an overloaded database server) @CircuitBreaker( attempts = “5", delay = “2s” reset = “30s” ) public Book findBook(String title) { //...
  • 34.
    CONFIGURATION Micronaut apps canaccept configuration from a variety of sources: • Configuration files (accepted formats are properties files,YAML, JSON, Groovy; e.g: /src/main/resources/application.yml) • System properties/Environment variables • Distributed configuration (e.g Consul, Spring Cloud Config, AWS Parameter Store)
  • 35.
    CONFIGURATION micronaut: application: name: service-a --- consul: client: registration: enabled: true defaultZone:"${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}" --- datasources: default: url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE driverClassName: org.h2.Driver username: sa password: '' dialect: H2 src/main/resources/application.yml
  • 36.
    CONFIGURATION @Singleton public class EngineImplimplements Engine { @Value("${my.engine.cylinders:6}") protected int cylinders; //... } src/main/java/EngineImpl.java @Value("http://${my.host}:${my.port}") URL url; @Value("${my.url:`http://foo.com`}") URL url; Multiple placeholders Default value
  • 37.
    CONFIGURATION PROPERTIES team: name: 'Steelers' color:'Black' player-names: - 'Mason Rudolph' - 'James Connor' src/main/resources/application.yml @ConfigurationProperties("team") public class TeamConfiguration { private String name; private String color; private List<String> playerNames; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public List<String> getPlayerNames() { return playerNames; } public void setPlayerNames(List<String> playerNames) { this.playerNames = playerNames; } } https://guides.micronaut.io/micronaut-configuration src/main/java/TeamConfiguration.java @Inject TeamConfiguration config; @Get public String index() { return config.getName(); } src/main/java/TeamController.java The above config can now be injected as a configuration bean:
  • 38.
    DISTRIBUTED CONFIGURATION • Micronautprovides a ConfigurationClient interface which can resolve config from distributed (cloud) sources • Integrations available for Consul,Vault, Spring Cloud Config, and AWS Parameter Store Support • Can be setup via a CLI feature or manually
  • 39.
    DISTRIBUTED CONFIGURATION $ mncreate-app service-a --features config-consul …or add the configuration manually in a file named bootstrap.yml: micronaut: application: name: service-a config-client: enabled: true consul: client: defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}" src/main/resources/bootstrap.yml $ curl -X PUT -d @- localhost:8500/v1/kv/config/application/foo.bar <<< myvalue We can now populate our Consul config service - the key foo.bar will contain the value myvalue
  • 40.
    MONITORING • Micronaut’s managementmodule provides endpoint for health checks and other monitoring needs • Also provides API for implementing custom health checks and endpoints • Built-in endpoints include: • /beans — Returns loaded bean definitions from the application context • /info — Returns static information from the application state • /health — Returns information about the health of the application • /metrics — Return application metrics * • /routes — Returns available URIs in the application • /loggers — Returns available loggers and allows change of log level • /stop — Shuts down server on receiving a POST request * Requires additional Micrometer metrics dependency
  • 41.
    MONITORING $ mn create-appservice-a --features management implementation 'io.micronaut:micronaut-management' build.gradle …or add dependency manually: micronaut: security: enabled: true endpoints: beans: enabled: true sensitive: true info: enabled: true sensitive: false src/main/resources/application.yml If the micronaut-security dependency is loaded, endpoints can be marked as “sensitive” to secure private information https://micronaut-projects.github.io/micronaut-security
  • 42.
  • 43.
    DISTRIBUTEDTRACING • Micronaut providesdistributed tracing support for the OpenTracing spec (any implementation) • Allows “spans” to be defined at the method and class-level via annotations • Also defines an instance of the io.opentracing.Tracer interface for complete functionality • Integration with Jaeger and Zipkin available via CLI features
  • 44.
    DISTRIBUTEDTRACING $ mn create-appservice-a --features tracing-zipkin //or tracing-jaeger implementation 'io.micronaut:micronaut-tracing' runtime 'io.zipkin.brave:brave-instrumentation-http' runtime 'io.zipkin.reporter2:zipkin-reporter' implementation 'io.opentracing.brave:brave-opentracing' build.gradle …or add dependencies manually: tracing: jaeger: enabled: true sampler: probability: 0.5 src/main/resources/application.yml https://guides.micronaut.io/micronaut-microservices-distributed-tracing-jaeger $ docker run -d -p 9411:9411 openzipkin/zipkin Start up the Zipkin “collector" via Docker:
  • 45.
    DISTRIBUTEDTRACING @NewSpan("productList") List<Product> productList() { //Getproducts } @ContinueSpan @Get(“/{id}”) HttpResponse<Product> show(Long id) { //Get product } @Get("/{productNumber}") HttpResponse<Integer> hits( @SpanTag("product") String product ) {} • @NewSpan begins a new tracing segment at this method • @ContinueSpan includes this method within the current span • @SpanTag allows metadata to be added to the (new or current) span
  • 46.
    DISTRIBUTEDTRACING import io.opentracing.Tracer import javax.inject.Inject importjavax.inject.Singleton @Singleton class StorefrontService { @Inject Tracer tracer @NewSpan("productList") List<ProductDetails> productList() { products = //Get products tracer.activeSpan().setTag("count", products.size()) products } Micronaut defines an instance of OpenTracing’s Tracer interface as a bean
  • 47.
    DISTRIBUTEDTRACING Tracing providers (Zipkinin this example) usually include a web-based UI for viewing and interacting with tracing data
  • 48.
    API DOCUMENTATION • Micronautcan generate OpenAPI (Swagger)YAML definitions at compilation time • Standard Micronaut annotations (@Controller, @Get, @Consumes, etc) and method return types (POJOs) will be analyzed and corresponding SwaggerYML written to the file • Standard Swagger annotations can be used to customize/ override the generatedYAML • Micronaut can handle merging of OpenAPI schemas from multiple modules (e.g., when using Micronaut Security)
  • 49.
    API DOCUMENTATION $ mncreate-app service-a --features swagger-java annotationProcessor("io.micronaut.configuration:micronaut-openapi:1.4.0") implementation("io.swagger.core.v3:swagger-annotations:1.4.0") build.gradle …or add dependencies manually: @OpenAPIDefinition( info = @Info( title = "Hello World", version = "0.0", description = "My API", license = @License(name = "Apache 2.0", url = "http://foo.bar"), contact = @Contact( url = "http://gigantic-server.com", name = "Fred", email = “Fred@gigagantic-server.com" ) ) ) src/main/java/Application.java Add an @OpenAPIDefinition for your app:
  • 50.
  • 51.
    MICRONAUT SPRING https://micronaut-projects.github.io/micronaut-spring/latest/ • AllowsSpring components to be integrated into Micronaut apps* • Allows a Spring app to be run as a Micronaut app • Expose Micronaut beans to a Spring app • At compilation time, Micronaut maps supported Spring annotations to corresponding Micronaut ones • Certain Spring interfaces are also mapped at compile time and can be used (ApplicationContext, Environment, BeanFactory, etc)
  • 52.
    MICRONAUT SPRING https://micronaut-projects.github.io/micronaut-spring/latest/ • Micronautfor Spring can serve as a “parent context” for a Spring app, making components written in Micronaut (e.g, the Kafka client, Discovery client, etc) available to the Spring context • Most Spring Boot annotations are supported (@ConfigurationProperties, @ConditionalOn*, @Endpoint) • Limitations:AspectJ, SpEL, and Servlet API are not supported by Micronaut
  • 53.
    MICRONAUT DATA https://micronaut-projects.github.io/micronaut-data/latest • Apersistence framework written especially for Micronaut • Uses AOT compilation to pre-compute queries, provide type-checking • No runtime reflection, no in-memory model, and no runtime query generation • Supports Reactive query execution (Publisher or RxJava)
  • 54.
    MICRONAUT DATA https://micronaut-projects.github.io/micronaut-data/latest package example; importio.micronaut.data.annotation.*; import io.micronaut.data.model.*; import io.micronaut.data.repository.CrudRepository; import java.util.List; @Repository interface BookRepository extends CrudRepository<Book, Long> { Book find(String title); }
  • 55.
    Tomorrow in thisroom (411) at 10:20AM
  • 56.
    BUILDING FOR PRODUCTION •Micronaut apps can be built as “fat” (or “uber”) JAR files using the Gradle Shadow Jar plugin or Maven Shade plugin (provided automatically by the CLI). $ ./gradlew shadowJar $ ./mvnw package $ java -jar build/libs/service-a-all.jar Application can now be deployed as a runnable JAR:
  • 57.
    GRAALVM • GraalVM isan alternativeVM that provides native image capability and minimal overhead • Micronaut applications can be configured to run within a GraalVM native image using a provided script • Micronaut’s avoidance of reflection makes it a perfect choice for apps targeting GraalVM
  • 58.
    GRAALVM $ mn create-appservice-a --features graal-native-image Use the CLI feature to generate config and Dockerfile: $ ./gradlew assemble $ ./docker-build.sh Build JAR file and run the provided build script to build image: $ docker run -p 8080:8080 micronaut-graal-app 10:29:46.845 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 12ms. Server Running: http://localhost:8080 The application can now be run by executing the native image:
  • 59.
    TOTHE CLOUD • Micronautprovides integration and environment-detection for numerous cloud platforms • Cloud-specific configuration can be applied with application-[provider].yml files (e.g., application-gcp.yml) • Can also use Groovy config files if imperative logic is required - e.g, obtaining values from a distributed config server
  • 60.
    AMAZON WEB SERVICES https://guides.micronaut.io/micronaut-elasticbeanstalk •Micronaut supports AWS specific configuration (e.g, application-aws.yml files) • Also includes a CLI profile for creating AWS Lambda applications (functions) • Consult Micronaut Guides website for tutorials on deploying to AWS Elastic Beanstalk and Lambda https://guides.micronaut.io/micronaut-function-graalvm-aws-lambda-gateway
  • 61.
    MICROSOFT AZURE https://github.com/microsoft/azure-maven-plugins • Micronautsupports Azure specific configuration (e.g, application-azure.yml files) • Microsoft provides a Maven plugin to facilitate Azure deployments (community-supported Gradle plugin also available) • Consult Micronaut Guides website for tutorials on deploying to Microsoft Azure https://guides.micronaut.io/micronaut-azure-cloud/guide/index.html
  • 62.
    GOOGLE CLOUD • (Assuminga properly configured GCP project) • The simplest approach is to use Google’s own App Engine Gradle Plugin buildscript { repositories { mavenCentral() } dependencies { classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.2.0' } } apply plugin: 'com.google.cloud.tools.appengine' build.gradle
  • 63.
    GOOGLE CLOUD ext { appEngineProjectVersion= project.version appEngineProjectId = 'calm-history-228704' } appengine { stage.artifact = "${buildDir}/libs/${project.name}-${project.version}-all.jar" deploy { projectId = appEngineProjectId version = appEngineProjectVersion } } build.gradle runtime: java env: flex src/main/appengine/app.yml Minimal GAE config: https://guides.micronaut.io/micronaut-gradle-google-cloud https://cloud.google.com/appengine/docs/standard/java/tools/gradle https://cloud.google.com/appengine/docs/standard/java/config/appref
  • 64.
    GOOGLE CLOUD $ ./gradlewappengineDeploy Deployed service [default] to [https://calm- history-228704.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s default To view your application in the web browser run: $ gcloud app browse BUILD SUCCESSFUL in 7m 26s 13 actionable tasks: 11 executed, 2 up-to-date $ curl https://calm-history-228704.appspot.com Micronaut on App Engine https://guides.micronaut.io/micronaut-gradle-google-cloud
  • 65.
  • 66.
    AND MORE… • MicronautKafka • Micronaut Kubernetes • Micronaut JAX-RS • Micronaut PicoCLI • Micronaut Kotlin • Micronaut Micrometer • Micronaut Security • Micronaut Elasticsearch • Micronaut Flyway • Micronaut Cassandra • Micronaut RabbitMQ • Micronaut GraphQL
  • 67.
    SUMMARY • Micronaut isa full-featured framework designed for modern cloud-based architectures • Offers a slew of features that are useful in almost every sort of application (not just microservices!) • Micronaut is actively evolving and new capabilities and integrations are being developed as we speak • Micronaut community is growing and is super helpful - join the Gitter channel! https://gitter.im/ micronautfw/
  • 68.
    RESOURCES • https://micronaut.io • https://github.com/micronaut-projects •User Guide: https://docs.micronaut.io • Micronaut Guides: https:// guides.micronaut.io • Awesome Micronaut: https://github.com/ JonasHavers/awesome-micronaut
  • 69.
  • 70.
  • 71.
    © 2019, ObjectComputing, Inc. (OCI). All rights reserved. objectcomputing.com 71 Events: ● objectcomputing.com/events Training: ● objectcomputing.com/training ● grailstraining.com ● micronauttraining.com Or email info@ocitraining.com to schedule a custom training program for your team online, on site, or in our state-of-the-art, Midwest training lab. LEARN MORE ABOUT OCI EVENTS AND TRAINING
  • 72.
    THANK YOU! Zachary Klein @ZacharyAKlein kleinz@objectcomputing.com Comevisit our booth! Just outside of room 307 in the main vendor hall