@holly_cummins @geoand86
#Quarkus #RedHat
reminder:
what makes quarkus special
Slide 32
Slide 32 text
traditional way vs quarkus way
@
@
>
build time
runtime
Slide 33
Slide 33 text
@
@
>
traditional way vs quarkus way
@
@
>
build time
runtime
build time
Slide 34
Slide 34 text
@
@
>
traditional way vs quarkus way
@
@
>
build time
runtime
runtime
build time
Slide 35
Slide 35 text
the quarkus way enables native compilation
native
@
@
>
JVM
build time
Slide 36
Slide 36 text
9
but … for a normal framework …
Slide 37
Slide 37 text
9
they load way too many classes
but … for a normal framework …
Slide 38
Slide 38 text
9
they load way too many classes
they are way too dynamic
but … for a normal framework …
Slide 39
Slide 39 text
9
they load way too many classes
they are way too dynamic
(which means they use way too much reflection)
but … for a normal framework …
Slide 40
Slide 40 text
9
they load way too many classes
they are way too dynamic
(which means they use way too much reflection)
they perform a lot of initialization at runtime
but … for a normal framework …
Slide 41
Slide 41 text
@
@
>
Packaging
(maven, gradle…)
build time
runtime
how does a framework start?
Slide 42
Slide 42 text
@
@
>
Load and parse config files,
properties, yaml, xml, etc.
build time
runtime
how does a framework start?
Slide 43
Slide 43 text
@
@
>
Classpath scanning and
annotation discovery
Attempt to load class to
enable/disable features
build time
runtime
how does a framework start?
Slide 44
Slide 44 text
@
@
>
Build its metamodel
of the world.
build time
runtime
how does a framework start?
Slide 45
Slide 45 text
@
@
>
Start thread pools,
IO, etc.
build time
runtime
how does a framework start?
Slide 46
Slide 46 text
Do the work once, not at each start
Get rid of all bootstrap classes
Less time to start, less memory needed
Less or no reflection nor dynamic proxies
what if we initialize at build time?
Slide 47
Slide 47 text
@
@
>
build time
Do the work once, not at each start
Get rid of all bootstrap classes
Less time to start, less memory needed
Less or no reflection nor dynamic proxies
what if we initialize at build time?
Slide 48
Slide 48 text
@
@
>
runtime
build time
Do the work once, not at each start
Get rid of all bootstrap classes
Less time to start, less memory needed
Less or no reflection nor dynamic proxies
what if we initialize at build time?
Slide 49
Slide 49 text
and another thing
Slide 50
Slide 50 text
and another thing
Slide 51
Slide 51 text
and another thing
developer experience
Slide 52
Slide 52 text
and another thing
developer experience
developer joy
Slide 53
Slide 53 text
“while we’re manipulating the
bytecode to support native, why
don’t we make coding … easier?”
[warning: may not actually be Quarkus origin story]
Slide 54
Slide 54 text
automagic dev instances (“dev services”)
unified config
opinionated shortcuts
joy comes in several forms:
@holly_cummins @geoand86
#Quarkus #RedHat
dynamic-but-static
“wouldn’t it be nice if …
… but it’s too expensive to do it at runtime.”
Slide 60
Slide 60 text
@holly_cummins @geoand86
#Quarkus #RedHat
public class CassandraConnector {
private Cluster cluster;
private Session session;
public void connect(String node, Integer port) {
Builder b = Cluster.builder().addContactPoint(node);
if (port != null) {
b.withPort(port);
}
cluster = b.build();
session = cluster.connect();
}
public Session getSession() {
return this.session;
}
public void close() {
session.close();
cluster.close();
}
}
Slide 61
Slide 61 text
@holly_cummins @geoand86
#Quarkus #RedHat
public class CassandraConnector {
private Cluster cluster;
private Session session;
public void connect(String node, Integer port) {
Builder b = Cluster.builder().addContactPoint(node);
if (port != null) {
b.withPort(port);
}
cluster = b.build();
session = cluster.connect();
}
public Session getSession() {
return this.session;
}
public void close() {
session.close();
cluster.close();
}
}
@Inject
private QuarkusCqlSession session;
Slide 62
Slide 62 text
@holly_cummins @geoand86
#Quarkus #RedHat
“opinionated choices
and educated guesses.”
Slide 63
Slide 63 text
@holly_cummins @geoand86
#Quarkus #RedHat
recap: why extensions?
• good behaviour in native mode
• fast behaviour in normal mode (pre-do all the things)
• good dev experience
Slide 64
Slide 64 text
@geoand86 @holly_cummins
#Quarkus #RedHat
Slide 65
Slide 65 text
@geoand86 @holly_cummins
#Quarkus #RedHat
Slide 66
Slide 66 text
@geoand86 @holly_cummins
#Quarkus #RedHat
Slide 67
Slide 67 text
@geoand86 @holly_cummins
#Quarkus #RedHat
Slide 68
Slide 68 text
@holly_cummins @geoand86
#Quarkus #RedHat
why write a new extension?
• the community hasn’t written one yet
• it’s your library
• support a use case particular to your environment
Slide 69
Slide 69 text
@holly_cummins @geoand86
#Quarkus #RedHat
“hook a build step?”
Slide 70
Slide 70 text
@holly_cummins @geoand86
#Quarkus #RedHat
“hook a build step?”
Slide 71
Slide 71 text
@holly_cummins @geoand86
#Quarkus #RedHat
“hook a build step?”
@holly_cummins @geoand86
#Quarkus #RedHat
framework automatically
determines correct execution
order and injects parameters
Slide 97
Slide 97 text
@holly_cummins @geoand86
#Quarkus #RedHat
build items are communication
mechanism between build steps
framework automatically
determines correct execution
order and injects parameters
Slide 98
Slide 98 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items intermediate state build items terminal state build items
Slide 99
Slide 99 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
intermediate state build items terminal state build items
Slide 100
Slide 100 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
intermediate state build items terminal state build items
Slide 101
Slide 101 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
ConfigClassBuildItem
intermediate state build items terminal state build items
Slide 102
Slide 102 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
ConfigClassBuildItem
UnremovableBeanBuildItem
intermediate state build items terminal state build items
Slide 103
Slide 103 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
ConfigClassBuildItem
UnremovableBeanBuildItem
BuildSystemTargetBuildItem
intermediate state build items terminal state build items
Slide 104
Slide 104 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
ConfigClassBuildItem
UnremovableBeanBuildItem
BuildSystemTargetBuildItem
LaunchModeBuildItem
intermediate state build items terminal state build items
Slide 105
Slide 105 text
@holly_cummins @geoand86
#Quarkus #RedHat
initial state build items
JarResultBuildStep
GeneratedResourceBuildItem
ConfigClassBuildItem
UnremovableBeanBuildItem
BuildSystemTargetBuildItem
LaunchModeBuildItem
most extensions do stuff here
intermediate state build items terminal state build items
Slide 106
Slide 106 text
@holly_cummins @geoand86
#Quarkus #RedHat
what kind of things
can build items do?
Create a servlet
Create a route
Pull an external bean into the closed world
Turn one annotation into another
Add a log handler
Read an extra application archive
Flag a capability as present
Interact with Kubernetes
…
Slide 107
Slide 107 text
@holly_cummins @geoand86
#Quarkus #RedHat
existing build items
cover almost all needs
like a library for extension writers
Slide 108
Slide 108 text
@holly_cummins @geoand86
#Quarkus #RedHat
Slide 109
Slide 109 text
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
index
Slide 110
Slide 110 text
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
index
Slide 111
Slide 111 text
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
index
eliminates need for runtime classpath scanning
Slide 112
Slide 112 text
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
index
“jandex”
eliminates need for runtime classpath scanning
Slide 113
Slide 113 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
Slide 114
Slide 114 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise
Slide 115
Slide 115 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
Slide 116
Slide 116 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
runtime class surprise!
Slide 117
Slide 117 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
runtime class surprise!
Slide 118
Slide 118 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
no worries
runtime class surprise!
Slide 119
Slide 119 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
no worries
runtime class surprise!
Slide 120
Slide 120 text
@holly_cummins @geoand86
#Quarkus #RedHat
open world closed world
hard to build-time optimise easy to build-time optimise
uh oh, this is outside
our closed world
no worries
runtime class surprise!
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
bytecode recording
easier than writing ASM
(if recording isn’t optimised enough,
use Gizmo to hand-craft bytecode)
Slide 124
Slide 124 text
Example
@Recorder
public class CaffeineCacheBuildRecorder {
// a proxy of this is invoked at build time
// the “real” invocation happens at runtime with the CaffeineCacheInfo obtained at build time
public Supplier getCacheManagerSupplier(Set cacheInfos) {
return new Supplier() {
@Override
public CacheManager get() {
if (cacheInfos.isEmpty()) {
return new CacheManagerImpl(Collections.emptyMap());
} else {
Map caches = new HashMap<>(cacheInfos.size() + 1, 1.0F);
for (CaffeineCacheInfo cacheInfo : cacheInfos) {
CaffeineCache cache = new CaffeineCache(cacheInfo);
caches.put(cacheInfo.name, cache);
}
return new CacheManagerImpl(caches);
}
}
};
}
}
@holly_cummins @geoand86
#Quarkus #RedHat
extension concept
GraalVM
● Contribute GraalVM configuration
○ Reflection registration
○ Dynamic proxy registration
○ Resource files
○ Message bundles
○ Etc.
● Provide substitutions
○ Pieces of code that are used in place of regular library code when
in native mode
Slide 143
Slide 143 text
Substitutions
@TargetClass(org.infinispan.client.hotrod.impl.RemoteCacheImpl.class)
public final class SubstituteRemoteCacheImpl {
@Delete
private ObjectName mbeanObjectName;
@Substitute
private void registerMBean(ObjectName jmxParent) {
}
@Substitute
private void unregisterMBean() {
}
@Delete
public void init(OperationsFactory operationsFactory, Configuration configuration, ObjectName
jmxParent) {
}
}
Slide 144
Slide 144 text
Real world examples
● Jackson extension
● Hibernate Validator extension
● Spring DI extension
Resources
● http:/
/quarkus.io
● https:/
/quarkus.io/guides/all-builditems
● https:/
/quarkus.io/blog/quarkus-aws-cloudwatch_extension/
● https:/
/quarkus.io/blog/solving-problems-with-custom-extensions/
Slide 145
Slide 145 text
®
thank you
@holly_cummins
@geoand86
https://github.com/holly-
cummins/quarkus-minecraft-
observability-extension
code