|
| 1 | +//// |
| 2 | +This guide is maintained in the main Quarkus repository |
| 3 | +and pull requests should be submitted there: |
| 4 | +https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc |
| 5 | +//// |
| 6 | +[id="extension-maturity-matrix"] |
| 7 | += A maturity matrix for Quarkus extensions |
| 8 | +include::_attributes.adoc[] |
| 9 | +:diataxis-type: concept |
| 10 | +:categories: writing-extensions |
| 11 | +:topics: extensions |
| 12 | +:summary: Quarkus extensions can do a lot, or a little. This guide explains some of the capabilities extension authors might want to include. |
| 13 | +//// |
| 14 | +The document header ends at the first blank line. Do not remove the blank line between the header and the abstract summary. |
| 15 | +//// |
| 16 | + |
| 17 | +What makes a good Quarkus extension? What capabilities is a Quarkus extension expected to provide? Of course, it depends on the extension you are building. But, we found a set of attributes common to many extensions. This document explains what they are. |
| 18 | + |
| 19 | +image::extension-maturity-matrix.svg[A maturity matrix] |
| 20 | + |
| 21 | +This isn't defining an exact order, even within a single row. Different extensions have different goals, and different developers will have different views on what capabilities are most important. You may wish to (for example) prioritise a fantastic programming model over enhancing your extension's Dev UI tile. That's fine! |
| 22 | + |
| 23 | +Also, not every step will apply to every extension. For example, you don't need a Dev Service if your extension doesn't depend on external services. |
| 24 | + |
| 25 | +It's completely OK to publish a first version of an extension that doesn't handle everything. In fact, it's OK if your extension _never_ gets to the more advanced features. This is a suggested pathway, not a minimum feature set. |
| 26 | + |
| 27 | +Also note that this list only includes the technical features of your extension. |
| 28 | +You might also want to think about how you share your extension, and how it presents itself to the world. |
| 29 | +The link:https://hub.quarkiverse.io/checklistfornewprojects/[new extension checklist] on the Quarkiverse Hub has a useful list of ways extensions can participate in the ecosystem. |
| 30 | +It's also a good idea to spend some time on the metadata in the xref:extension-metadata#quarkus-extension-yaml[`quarkus-extension.yaml` file], which is used by Quarkus tooling. |
| 31 | + |
| 32 | +Here are some pointers on how to achieve those capabilities. |
| 33 | + |
| 34 | +== Run modes |
| 35 | + |
| 36 | +Quarkus applications can be run as a normal jar-based JVM application, |
| 37 | +or live-coded in dev mode, or compiled to a native binary. |
| 38 | +Each environment places different demands on framework extensions. |
| 39 | + |
| 40 | +=== Works in JVM mode |
| 41 | + |
| 42 | +For most extensions, this is the minimum expectation. |
| 43 | +When wrapping an existing library, this is usually trivial to achieve; if an extension is providing net-new capability, it might be a bit more work. Quarkus provides tools for xref:writing-extensions.adoc#testing-extensions[unit testing and integration testing] extensions. |
| 44 | + |
| 45 | +=== Works in dev mode |
| 46 | + |
| 47 | +In some cases, extra work may be needed to ensure any wrapped libraries can tolerate |
| 48 | +dev mode, since the classloading is different and hot reloading can break some assumptions. Extensions may also wish to add some |
| 49 | +xref:writing-extensions.adoc#integrating-with-development-mode[special handling for dev mode]. |
| 50 | +To add automated tests which validate dev mode, you can xref:writing-extensions.adoc#testing-hot-reload[add tests which extend the `QuarkusDevModeTest`]. |
| 51 | + |
| 52 | +=== Works as a native application |
| 53 | + |
| 54 | +For many libraries, native mode support is the primary motivation for creating an extension. See xref:writing-extensions.adoc#native-executable-support[the guide on native executable support] for more discussion about some of the adaptations that might be needed. |
| 55 | + |
| 56 | +== Developer Joy |
| 57 | + |
| 58 | +Developer Joy is an important Quarkus principle. |
| 59 | +Here are some extension capabilities that contribute to joyful development. |
| 60 | + |
| 61 | +=== Configuration support |
| 62 | + |
| 63 | +Extensions should support Quarkus's unified configuration, by xref:writing-extensions.adoc#configuration[integrating with the Quarkus configuration model]. |
| 64 | +The Writing Extensions guide has more guidance on xref:writing-extensions.adoc#how-to-expose-configuration[the Quarkus configuration philosophy]. |
| 65 | + |
| 66 | +=== CDI Beans |
| 67 | + |
| 68 | +Quarkus extensions should aim to xref:writing-extensions.adoc#expose-your-components-via-cdi[expose components via CDI], so that they can be consumed in a frictionless way by user applications. |
| 69 | +Having everything injectable as CDI beans also helps testing, especially xref:getting-started-testing#mock-support[mocking]. |
| 70 | + |
| 71 | +=== Dev Service |
| 72 | + |
| 73 | +Dev Services are generally relevant for extensions that "connect" to something, such as databases for datasources, a keycloak instance for security, an Apache Kafka instance for messaging, etc. |
| 74 | + |
| 75 | +To provide a Dev Service, use the `DevServicesResultBuildItem` build item. See the xref:extension-writing-dev-service.adoc[Dev Services how-to] for more information. |
| 76 | + |
| 77 | +=== Basic Dev UI |
| 78 | + |
| 79 | +Every extension gets a tile in the Dev UI. The default tile pulls information from the xref:extension-metadata.adoc[extension metadata], which is another reason to spend a bit of time getting the metadata right. |
| 80 | + |
| 81 | +Extensions also use Dev UI hooks to present extra information to users. For example, the tile could include a link to an external console, or an internal page which presents simple text metrics. See the xref:dev-ui.adoc[Dev UI for extension developers] guide. |
| 82 | + |
| 83 | + |
| 84 | +=== Rich Dev UI |
| 85 | + |
| 86 | +Some extensions provide extremely sophisticated Dev UIs. |
| 87 | +For example, they might allow users to interact with the running application, xref:dev-ui.adoc#hot-reload[respond to reloads], visualise application metrics, or xref:dev-ui.adoc#add-a-log-to-the-footer[stream an application-specific log]. |
| 88 | +The xref:dev-ui.adoc[Dev UI for extension developers] guide also explains these more advanced options. |
| 89 | + |
| 90 | +=== Joyful programming model |
| 91 | + |
| 92 | +Quarkus's build-time philosophy means extensions can tidy up API boilerplate and make programming models more concise and expressive. |
| 93 | +A good starting point is usually to use |
| 94 | + xref:writing-extensions.adoc#scanning-deployments-using-jandex[Jandex] to scan user code for annotations and other markers. |
| 95 | +Although providing new, joyful, ways to do things is good, |
| 96 | +it's important to not break the normal patterns that users may be familiar with. |
| 97 | + |
| 98 | +For some inspiration in this area, have a look at xref:logging#simplified-logging[simplified logging], xref:hibernate-orm-panache.adoc[simplified Hibernate ORM with Panache], the xref:rest-client.adoc#query-parameters[`@RestQuery` annotation], or the way Quarkus allows test containers to be used xref:getting-started-dev-services.adoc[without any configuration]. |
| 99 | + |
| 100 | +=== Codestart application template |
| 101 | + |
| 102 | +Codestarts are templates which can be used to generate applications for users. |
| 103 | +Extensions can xref:extension-codestart.adoc[provide their own codestart templates]. |
| 104 | + |
| 105 | +== Supersonic subatomic performance |
| 106 | + |
| 107 | +Extensions should use build-time application knowledge to eliminate wasteful runtime code paths. We call this supersonic subatomic performance. |
| 108 | +Because Quarkus moves work to the build stage, Quarkus applications should have fast startup, high throughput, and low memory requirements. Performance tuning is a large subject, but extensions should use build-time application knowledge to eliminate wasteful runtime code paths at runtime. |
| 109 | + |
| 110 | +=== Static initialization |
| 111 | + |
| 112 | +Do as much initialization as much as possible statically. |
| 113 | +This avoid runtime overhead. |
| 114 | + |
| 115 | +=== Replace reflection with generated bytecode |
| 116 | + |
| 117 | +Many Java libraries make heavy use of reflection to delay decisions to run-time. Quarkus aims to improve performance by moving logic to build time, reducing unnecessary dynamism. |
| 118 | +Extensions should aim to replace reflection with build-time code. |
| 119 | +This is enabled by |
| 120 | + xref:writing-extensions.adoc#scanning-deployments-using-jandex[Jandex], an "offline reflection" library. It may also be necessary to do some bytecode transformation of existing libraries. |
| 121 | + |
| 122 | +For a case study of how to eliminate reflection and what the performance benefits turned out to be, see https://quarkus.io/blog/quarkus-metaprogramming/[reflectionless Jackson serialization] |
| 123 | + |
| 124 | +=== Virtual thread support |
| 125 | + |
| 126 | +Not every library is suitable for using with virtual threads, out of the box. |
| 127 | +xref:virtual-threads#why-not["Why not virtual threads everywhere?"] explains why. |
| 128 | + |
| 129 | +To get your library working properly with virtual threads, you should make sure the library is not pinning the carrier thread. |
| 130 | + Quarkus has xref:virtual-threads.adoc#testing-virtual-thread-applications[test helpers to do these checks in an automated way]. |
| 131 | + For dispatching work, you should use the xref:virtual-threads.adoc#inject-the-virtual-thread-executor[virtual executor managed by Quarkus]. The link:https://quarkus.io/extensions/io.quarkus/quarkus-websockets-next/[WebSockets-next extension] uses the virtual dispatcher and smart dispatch, and is a good example to follow. |
| 132 | + |
| 133 | +=== Hot path performance optimization |
| 134 | + |
| 135 | +Although Quarkus offers some unique opportunities for extension performance, extension developers shouldn't forget https://www.linkedin.com/pulse/how-optimize-software-performance-efficiency-subcodevs/[the basics of performance optimization]. |
| 136 | + |
| 137 | +=== Non-blocking internals |
| 138 | + |
| 139 | +Quarkus's reactive core is a key contributor to its excellent throughput and scalability. Extensions should consider adopting this model for their own internal operations. |
| 140 | + |
| 141 | +=== Add Mutiny-based APIs |
| 142 | + |
| 143 | +For maximum scalability, go beyond the reactive core and enable fully reactive programming, using Mutiny. Most projects that support a reactive programming model offer two distinct extensions, a `-reactive` and a plain one. |
| 144 | +See, for example, https://quarkus.io/extensions/io.quarkiverse.quarkus-elasticsearch/quarkus-elasticsearch/[ElasticSearch] and https://quarkus.io/extensions/io.quarkiverse.quarkus-elasticsearch-reactive/quarkus-elasticsearch-reactive/[ElasticSearch Reactive] extensions. |
| 145 | + |
| 146 | +== Operations |
| 147 | + |
| 148 | +Developer joy is important, but so are observability, maintainability, and other operational considerations. |
| 149 | +Many of these characteristics come by default with the Quarkus framework or https://quarkus.io/extensions/io.quarkus/quarkus-opentelemetry/[observability-focussed extensions]. But extensions can do more. |
| 150 | + |
| 151 | +=== Logging |
| 152 | + |
| 153 | +Quarkus uses JBoss Logging as its logging engine, and xref:logging[supports several logging APIs]. (This is normal Java logging, not OpenTelemetry logging.) |
| 154 | + |
| 155 | +Avoid using errors and warnings for conditions that will not affect normal operation. These outputs can cause false alarms in user monitoring systems. |
| 156 | + |
| 157 | + |
| 158 | +=== Define health endpoints |
| 159 | + |
| 160 | +Extensions may wish to xref:writing-extensions#extension-defined-endpoints[define library-specific endpoints] for health criteria which are specific to that extension. To add a new endpoint, extensions should produce a `NonApplicationRootPathBuildItem`. |
| 161 | + |
| 162 | +=== Tracing context |
| 163 | + |
| 164 | +You should test that OpenTelemetry output for applications using your extension have properly-defined spans. You may need to do extra work to ensure spans are created with the right tracing ID. |
| 165 | +For example, extensions which have reactive internals should support xref:duplicated-context.adoc[duplicated contexts] for correct context propagation. |
| 166 | + |
| 167 | +=== Advanced Kubernetes and containers integration |
| 168 | + |
| 169 | +Quarkus is designed to be a Kubernetes-native runtime. |
| 170 | +Extensions can continue this philosophy by adding library-specific integration points with Kubernetes. |
| 171 | +Being Kubernetes-native implies being container-native. At a minimum, extensions should always work well in containers, but extensions may also have opportunities to integrate with the lower levels of the container stack. |
| 172 | + |
| 173 | + |
| 174 | +== References |
| 175 | + |
| 176 | +- xref:writing-extensions.adoc[Writing your own extension] guide |
| 177 | +- xref:building-my-first-extension.adoc[Building your first extension] |
| 178 | +- link:https://hub.quarkiverse.io.adoc[The Quarkiverse Hub documentation] |
0 commit comments