<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Tim Quinn on Medium]]></title>
        <description><![CDATA[Stories by Tim Quinn on Medium]]></description>
        <link>https://medium.com/@tquinno600?source=rss-66479c519f05------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*0cu8sR_xvVgNwsAt.jpg</url>
            <title>Stories by Tim Quinn on Medium</title>
            <link>https://medium.com/@tquinno600?source=rss-66479c519f05------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 14 Apr 2026 02:53:00 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@tquinno600/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Major Improvements with Helidon and OpenAPI]]></title>
            <link>https://medium.com/helidon/major-improvements-with-helidon-and-openapi-f76a0951508e?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/f76a0951508e</guid>
            <category><![CDATA[generator]]></category>
            <category><![CDATA[releases]]></category>
            <category><![CDATA[open-api]]></category>
            <category><![CDATA[helidon]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Fri, 06 Jan 2023 13:14:33 GMT</pubDate>
            <atom:updated>2023-01-06T13:14:33.522Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5-9bqf-8j6YwXNXJoruT-g.png" /></figure><p>With releases 2.5.5 and 3.1.0, Helidon significantly improves its participation in the OpenAPI ecosystem. You can now take advantage of</p><ul><li>powerful code generation from OpenAPI documents, and</li><li>a convenient user interface for test-driving your application’s operations.</li></ul><p>This is in addition to built-in support for OpenAPI which Helidon has included almost from its beginning.</p><h3>Existing OpenAPI support — a longstanding Helidon feature</h3><p>Since its early releases, Helidon has had strong support for <a href="https://www.openapis.org">OpenAPI</a>.</p><p>With Helidon SE you can package a static OpenAPI document with your service or even write your own code to build the document at runtime. Helidon then automatically serves the document at /openapi.</p><p>Helidon MP (which implements the <a href="https://download.eclipse.org/microprofile/microprofile-open-api-3.0/microprofile-openapi-spec-3.0.html">MicroProfile OpenAPI specification</a>) in addition can <em>automatically</em> derive an OpenAPI document from the JAX-RS endpoints in your application.</p><h3>New, stronger support in OpenAPITools generators for Helidon</h3><p>The <a href="https://openapi-generator.tech">OpenAPITools generator</a> is an open-source project separate from the Helidon project which generates code for a wide variety of platforms and languages from an OpenAPI document. Starting with release 6.2.1, that project provides much stronger support for generating Helidon SE and MP servers and clients.</p><p>The Helidon team has contributed two new generators — java-helidon-server and java-helidon-client — to the OpenAPITools generator project. Each new generator supports two libraries — mp and se — so you can generate code for either flavor of Helidon.</p><p>The java-helidon-server generator creates code to <em>implement</em> in a Helidon server the operations declared in an OpenAPI document. The generated code includes skeleton implementations which you then extend with business logic you write yourself. If your OpenAPI document changes, you can regenerate the code without disturbing your customizations.</p><p>The java-helidon-client generator creates a library to <em>invoke</em> your operations as implemented in a server. (The server does not have to be generated using the tool; it does need to honor the OpenAPI document you use to generate the client.) Most developers would add a dependency on the generated client library from one or more other projects that need to contact the server.</p><p>As a developer, once you have an OpenAPI document which describes your application’s endpoints, you can use the new generators in several ways:</p><ol><li>Use the OpenAPITools CLI to create an entire new Helidon MP or SE project which contains generated code to <em>implement</em> your operations (for servers) or <em>invoke</em> your operations (for clients).</li><li>Use the OpenAPITools CLI to update an existing server or client project with revised interfaces or classes that reflect any changes in the OpenAPI document.</li><li>Invoke the Maven plug-in for the OpenAPITools generator from your project’s pom.xml. Each time you build the project, the plug-in recreates the generated files according to the current version of the OpenAPI document.</li></ol><p>Many developers will choose to use the Helidon CLI to create a project, then edit the pom.xml to invoke the OpenAPITools generator Maven plug-in as an automatic part of the build.</p><p>To use the <a href="https://openapi-generator.tech/docs/installation/#jar">generator CLI</a>, first download it using a command similar to this:</p><pre>curl https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/6.2.1/openapi-generator-cli-6.2.1.jar \<br>     -o openapi-generator-cli.jar</pre><p>Then you can create a Helidon MP project from your OpenAPI document very simply:</p><pre>mkdir myproject<br><br>cd myproject<br><br>java -jar ${path-to-generator}/openapi-generator-cli.jar \<br>  generate \<br>  --input-spec ${path-to-openapi-document}myAppOpenAPI.yaml \<br>  --generator-name java-helidon-server \<br>  --library mp</pre><p>To create an SE project, change the--library to se. To generate a client, change the --generator-name to java-helidon-client.</p><p>The OpenAPITools site describes <a href="https://openapi-generator.tech/docs/usage">how to use the tool in general</a>, for all generators and all languages and frameworks. We have added to our own Helidon web site new documentation which explains in detail not only how to use the tool to generate an <a href="https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-generator">MP project</a> or an <a href="https://helidon.io/docs/latest/index.html#/se/openapi/openapi-generator">SE project</a> but also how to then work with the generated files to complete your project. We have also added examples which show generated <a href="https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-mp">Helidon MP</a> and <a href="https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-se">SE</a> projects along with detailed step-by-step instructions.</p><h3>Integration with the SmallRye OpenAPI user interface</h3><p>SmallRye offers an <a href="https://github.com/smallrye/smallrye-open-api/tree/3.1.0/ui/open-api-ui">OpenAPI user interface</a> which displays a web page based on your application’s OpenAPI document. Through that UI, users can invoke the operations declared in the document. While not generally suitable for end-users, the OpenAPI UI can be useful for demonstrating and “test driving” your service’s endpoints.</p><p>Helidon now includes a new, optional component which plugs the OpenAPI UI into your Helidon SE or MP application very simply. In many cases you can simply add a single runtime dependency to your project:</p><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.integrations.openapi-ui&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-integrations-openapi-ui&lt;/artifactId&gt;<br>&lt;/dependency&gt;</pre><p>Rebuild and run your project, and then use a browser to access/openapi/ui which launches the UI.</p><p>Here is how the UI looks for the Helidon MP QuickStart application:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/893/1*t45TpCnlnljP--NoYVbw4A.png" /></figure><p>The screen lists the operations which the MP QuickStart application’s OpenAPI document defines. To run one of the operations:</p><ul><li>Click on the operation.</li><li>Click “Try it out”.</li><li>Fill in any parameters you want to pass to the operation (the first red box in the image below).</li><li>Click “Execute” (red arrow).</li></ul><p>The UI sends the request to the operation and displays the response (second red box):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/894/1*qNVplp3UNjf-23oggn04cg.png" /></figure><p>The Helidon documentation contains new sections describing in detail how to add the UI to your <a href="https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-ui">MP application</a> and <a href="https://helidon.io/docs/latest/index.html#/se/openapi/openapi-ui">SE application</a>. You can even customize the path where you want the UI to respond.</p><h3>Next Steps</h3><p>Take a look at the expanded Helidon documentation describing the new generators and the new UI integration.</p><ul><li>Generating MP applications <a href="https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-generator">https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-generator</a></li><li>Generating SE applications <a href="https://helidon.io/docs/latest/index.html#/se/openapi/openapi-generator">https://helidon.io/docs/latest/index.html#/se/openapi/openapi-generator</a></li><li>Integrating the OpenAPI UI into MP applications <a href="https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-ui">https://helidon.io/docs/latest/index.html#/mp/openapi/openapi-ui</a></li><li>Integrating the OpenAPI UI into SE applications <a href="https://helidon.io/docs/latest/index.html#/se/openapi/openapi-ui">https://helidon.io/docs/latest/index.html#/se/openapi/openapi-ui</a></li></ul><p>Browse the examples of using the generators:</p><ul><li>Example using the OpenAPI generator for an MP application<br><a href="https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-mp">https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-mp</a></li><li>Example using the OpenAPI generator for an SE application <a href="https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-se">https://github.com/helidon-io/helidon/tree/3.1.0/examples/openapi-tools/quickstart-se</a></li></ul><p>Then you will be ready to use the generators and the UI in your own projects with your own OpenAPI documents.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f76a0951508e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/major-improvements-with-helidon-and-openapi-f76a0951508e">Major Improvements with Helidon and OpenAPI</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Exemplars in Helidon Metrics]]></title>
            <link>https://medium.com/helidon/using-exemplars-in-helidon-metrics-56dbf70e972c?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/56dbf70e972c</guid>
            <category><![CDATA[open-metrics]]></category>
            <category><![CDATA[exemplar]]></category>
            <category><![CDATA[prometheus]]></category>
            <category><![CDATA[oracle]]></category>
            <category><![CDATA[helidon]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Tue, 01 Jun 2021 06:34:23 GMT</pubDate>
            <atom:updated>2021-06-01T06:34:23.264Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/770/1*YQge_BkMkvVDJ5eMZ00nKA.png" /></figure><p>The <a href="https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md">OpenMetrics</a> (Prometheus) metrics format allows metrics providers like Helidon to add optional strings to the metrics output. These strings describe <em>exemplars</em> — samples that are, in some way, typical of all the samples represented by the metric. In particular, an exemplar string for a metric often identifies a trace for an actual use of a service in the application that triggered an update of that metric.</p><p>Beginning with Helidon 2.3.0, you can add exemplars to Helidon OpenMetrics output for histograms, counters, timers, and simple timers by adding a few dependencies to the pom.xml of your Helidon SE or MP application. You do not have to change your application code or your configuration.</p><p>In this article, we assume you have an existing Helidon application, such as the Helidon QuickStart application created using the Helidon CLI. You can easily add exemplar support to your application and see it in action:</p><ul><li>Add a few dependencies to your pom.xml.</li><li>Run Zipkin locally.</li><li>Run and access your application.</li><li>Browse the Zipkin traces identified by the new metrics exemplars.</li></ul><h4>How Helidon implements exemplars</h4><p>When you enable exemplar support, each time Helidon updates a metric with a data value it also records the trace ID and the current system time for the sample.</p><p>Later, when Helidon formats an OpenMetrics (Prometheus) response to a request sent to your application’s/metrics endpoint, it selects one representative sample — one exemplar — for each relevant metric value and adds information about that sample to the output for that metric value. (See the examples below.)</p><p>Some metric values, such as min or max, correspond directly to at least one sample and Helidon uses such a sample for the exemplar. Other metric values are aggregates of multiple samples, such as mean. For aggregate metrics, Helidon selects for the exemplar a sample with a value as close as possible to the reported metric value.</p><p>In many cases, the exemplar’s value will not be the same as an aggregate metric value. For example, consider a metric that is the mean of samples with values 3, 4, and 8. No sample has a value equal to the mean — 5 — so Helidon would choose as the exemplar for this metric the sample with value 4 because that sample has value closest to the mean.</p><h3>Adding exemplar support to your application</h3><h4>Update your pom.xml</h4><p>Add dependencies for exemplar support, tracing support, and Zipkin support:</p><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.metrics&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-metrics-trace-exemplar&lt;/artifactId&gt;<br>    &lt;scope&gt;runtime&lt;/scope&gt;<br>&lt;/dependency&gt;</pre><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.microprofile.tracing&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-microprofile-tracing&lt;/artifactId&gt;<br>    &lt;scope&gt;runtime&lt;/scope&gt;<br>&lt;/dependency&gt;</pre><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.tracing&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-tracing-zipkin&lt;/artifactId&gt;<br>    &lt;scope&gt;runtime&lt;/scope&gt;<br>&lt;/dependency&gt;</pre><p>You could add Helidon Jaeger support instead of Zipkin if you prefer.</p><h4>Start Zipkin</h4><p>If you do not start Zipkin, your application will still function correctly and Helidon will add exemplars to the metrics output, but Helidon will log a warning message when it cannot connect to the Zipkin server to report the tracing spans (and of course you will be unable to browse the traces in Zipkin).</p><pre>docker run --name zipkin -d -p 9411:9411 openzipkin/zipkin</pre><h4>Try the revised application</h4><p>Build and run your application:</p><pre>mvn package<br>java -jar target/quickstart-mp.jar</pre><p>Access some of the application’s services (responses in <em>italics</em>):</p><pre>curl -X GET http://localhost:8080/greet<br><em>{&quot;message&quot;:&quot;Hello World!&quot;}</em><br><br>curl -X GET http://localhost:8080/greet/Joe<br><em>{&quot;message&quot;:&quot;Hello Joe!&quot;}</em><br><br>curl -X PUT -H &quot;Content-Type: application/json&quot; -d &#39;{&quot;greeting&quot; : &quot;Hola&quot;}&#39; http://localhost:8080/greet/greeting<br><br>curl -X GET http://localhost:8080/greet/Jose<br><em>{&quot;message&quot;:&quot;Hola Jose!&quot;}</em><br><br>curl -X GET http://localhost:8080/greet          <br><em>{&quot;message&quot;:&quot;Hola World!&quot;}</em></pre><h4>Retrieve metrics</h4><p>Now, retrieve the metrics and note the exemplar that now appears in the output. Exemplars actually appear as comments at the end of metrics output, as prescribed in the OpenMetrics spec:</p><pre>curl -s -X GET http://localhost:8080/metrics/vendor<br><em># TYPE vendor_requests_count_total counter<br># HELP vendor_requests_count_total Each request (regardless of HTTP method) will increase this counter<br>vendor_requests_count_total 6 </em><strong><em># {trace_id=&quot;acc807bee31f8b96&quot;} 1 1619637182.784000</em></strong><br><strong>...</strong></pre><p>Each exemplar shows</p><ul><li>the trace ID,</li><li>the value which that sample contributed to the metric (in this case, the count), and</li><li>the time in epoch seconds when Helidon recorded that sample.</li></ul><h4>Browse the Zipkin Traces</h4><p>Access Zipkin in your browser at<a href="http://localhost:9411,">http://localhost:9411</a>.</p><p>Click RUN QUERYto see the scans your Helidon application reported to Zipkin.</p><figure><img alt="Zipkin Dashboard" src="https://cdn-images-1.medium.com/max/1024/1*oMzb5SwsWA15ilfsJIx5kQ.png" /><figcaption>Zipkin Dashboard</figcaption></figure><p>Then click EXPAND ALL to reveal the trace IDs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Le1NE8JJhG0dkOyEN-sHZg.png" /><figcaption>Zipkin Trace Overview</figcaption></figure><p>Find the trace ID listed in the metrics output. Click SHOW in that row to see the trace details.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mWV6Ow_OuvzrNFSMnRmjZg.png" /><figcaption>Zipkin Trace Expended Overview</figcaption></figure><p>Explore the details of the selected trace and its various sub-spans.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1lbYM31eukUtaaF7C3Q6eg.png" /><figcaption>Zipkin Trace Detail</figcaption></figure><h3>Bottom Line</h3><p>Without changing your application code, and by adding just a few dependencies to your project’s pom.xml, you can enable exemplars in your Helidon application’s metrics output.</p><p>You can use the trace IDs from the exemplars in the metrics output to identify representative traces for the metric values and use the trace utility (e.g., Zipkin) to find out details about each of those traces.</p><h4>More Information</h4><p>Please read the documentation about metrics exemplar support for <a href="https://helidon.io/docs/latest/index.html/se/metrics/04_prometheus_exemplar_support">Helidon SE </a>and <a href="https://helidon.io/docs/latest/index.html/mp/metrics/04_prometheus_exemplar_support">Helidon MP</a> applications for more information.</p><p>The <a href="https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md">OpenMetrics spec</a> describes exemplars.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=56dbf70e972c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/using-exemplars-in-helidon-metrics-56dbf70e972c">Using Exemplars in Helidon Metrics</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Micrometer in Helidon Applications]]></title>
            <link>https://medium.com/helidon/using-micrometer-in-helidon-applications-c8dfc7ccd1de?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/c8dfc7ccd1de</guid>
            <category><![CDATA[oracle]]></category>
            <category><![CDATA[micrometer]]></category>
            <category><![CDATA[helidon]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[releases]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Mon, 24 May 2021 13:28:51 GMT</pubDate>
            <atom:updated>2021-05-24T13:28:51.446Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pGSZVxBMREANoogra2tk7g.png" /></figure><p>Oracle’s Project <a href="https://helidon.io">Helidon</a> simplifies the job of building Java microservices by, among other things, including support for metrics inspired by the <a href="https://download.eclipse.org/microprofile/microprofile-metrics-2.3/microprofile-metrics-spec-2.3.html">MicroProfile Metrics specification</a>. Helidon metrics include some built-in measurements, but also allow app developers to add their own using the same MicroProfile-inspired API.</p><p>Helidon release 2.3.0 adds built-in support for Micrometer metrics. You can use the Micrometer API and annotations to create and update your own application meters and make them available via an endpoint Helidon creates. (This does <em>not</em> replace the built-in Helidon metrics features.)</p><p>This article shows how to add Micrometer support and your own Micrometer meters to a <a href="https://helidon.io/docs/latest/index.html#/se/guides/02_quickstart">Helidon </a>SE or MP app. We’ll assume you have used the Helidon <a href="https://helidon.io/docs/latest/index.html/about/05_cli">CLI</a> to create an SE or MP quick-start Helidon application.</p><h3>Adding Micrometer support to your SE app</h3><h4>Modify pom.xml</h4><p>Add the Helidon Micrometer integration dependency:</p><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.integrations.micrometer/groupId&gt;<br>    &lt;artifactId&gt;helidon-integrations-micrometer&lt;/artifactId&gt;<br>&lt;/dependency&gt;</pre><h4>Modify Main.java</h4><p>The main class sets up the Helidon routing for your endpoints and any built-in Helidon features you choose. Change the main class to create and register MicrometerSupport as well.</p><pre><strong>import io.helidon.integrations.micrometer.MicrometerSupport;</strong><br>...<br><strong>MicrometerSupport micrometerSupport = MicrometerSupport.<em>create</em>();<br></strong>GreetService greetService = <br>        new GreetService(config, <strong>micrometerSupport.registry()</strong>);<br>...<br>Routing.builder()<br>    .register(health)<em><br>    </em>.register(metrics)<em><br></em><strong><em>    </em>.register(micrometerSupport)<br></strong>    .register(&quot;/greet&quot;, greetService)<br>    .build();</pre><p>The new .register invocation exposes Helidon’s built-in Micrometer support /micrometer endpoint to produce Prometheus-formatted output.</p><h4>Modify GreetService.java</h4><p>Revise the GreetService class so its constructor accepts the Micrometer registry as a parameter and GET accesses create and update a Micrometer meter.</p><p>Add imports:</p><pre>import io.micrometer.core.instrument.Counter;<br>import io.micrometer.core.instrument.MeterRegistry;</pre><p>Declare Micrometer MeterRegistry and Micrometer Counterfields:</p><pre>private final MeterRegistry meterRegistry;<br>private final Counter getCounter;</pre><p>Change the constructor to accept and save the MeterRegistry parameter and create the counter:</p><pre>GreetService(Config config, <strong>MeterRegistry meterRegistry</strong>) {<br>    <strong>this.meterRegistry = meterRegistry;</strong><br>    <strong>getCounter = meterRegistry.counter(&quot;greeting.get&quot;);</strong><br>    greeting.set(config.get(&quot;app.greeting&quot;).asString()<br>        .orElse(&quot;Ciao&quot;));<br>}</pre><p>Change theupdate methodto add a request handler for every get HTTP operation. This handler updates the Micrometer Counterbefore passing the request off to the next handler without disturbing the other handlers for the service:</p><pre>public void update(Routing.Rules rules) {<br>    rules<br>        <strong>.get((req, resp) -&gt; {<br>            getCounter.increment();<br>            req.next();<br>        })</strong><br>        .get(&quot;/&quot;, this::getDefaultMessageHandler)<br>        .get(&quot;/{name}&quot;, this::getMessageHandler)<br>        .put(&quot;/greeting&quot;, this::updateGreetingHandler);<br>}</pre><h4>Try it</h4><p>Build and run the revised application:</p><pre>mvn package<br>java -jar target/quickstart-se.jar</pre><p>Access the new endpoint:</p><pre>% curl <a href="http://localhost:8080/micrometer">http://localhost:8080/<strong>micrometer</strong></a><br># HELP greeting_get_total<br># TYPE greeting_get_total counter<br>greeting_get_total 0.0</pre><p>Retrieve at least one greeting:</p><pre>% curl <a href="http://localhost:8080/greet">http://localhost:8080/greet</a><br>{&quot;message&quot;:&quot;Hello World!&quot;}</pre><pre>% curl <a href="http://localhost:8080/greet/reader">http://localhost:8080/greet/reader</a><br>{&quot;message&quot;:&quot;Hello reader!&quot;}</pre><p>Check the Micrometer output again, noting the change in value:</p><pre>curl <a href="http://localhost:8080/micrometer">http://localhost:8080/micrometer</a><br># HELP greeting_get_total<br># TYPE greeting_get_total counter<br><strong>greeting_get_total 2.0</strong></pre><h3>Add Micrometer support to your MP app</h3><p>You can use the Micrometer @Counted and @Timedannotations in your Helidon MP application.</p><h4>Modify pom.xml</h4><p>Add the dependency for Helidon Micrometer with CDI support:</p><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.integrations.micrometer&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-integrations-micrometer-cdi&lt;/artifactId&gt;<br>&lt;/dependency&gt;</pre><h4>Add Micrometer annotations to GreetResource.java</h4><p>We use Micrometer annotations to track (by time and invocation count) all GET accesses and to count separately all requests for personalized greetings.</p><p>We will use the same @Timedannotation on two GET methods, so first define constants we can reuse:</p><pre>private static final String <em>GETS_TIMER_NAME </em>= &quot;allGets&quot;;<br>private static final String <em>GETS_TIMER_DESCR </em>= <br>        &quot;Tracks all GET operations&quot;;</pre><p>Add</p><ul><li>Micrometer @Timed annotation to <em>both</em> GET methods, and</li><li>Micrometer @Counted annotation to the personalized GET method:</li></ul><pre>@GET<br><strong>@Timed(value = <em>GETS_TIMER_NAME</em>, description = <em>GETS_TIMER_DESCR</em>)</strong><br>@Produces(MediaType.<em>APPLICATION_JSON</em>)<br>public JsonObject getDefaultMessage() {<br>    ...<br>}<br>...<br><strong>@Counted(value = &quot;personalizedGets&quot;, <br>        description = &quot;Counts personalized GET operations&quot;)<br>@Timed(value = <em>GETS_TIMER_NAME</em>, description = <em>GETS_TIMER_DESCR</em>)</strong><br>@Path(&quot;/{name}&quot;)<br>@GET<br>@Produces(MediaType.<em>APPLICATION_JSON</em>)<br>public JsonObject getMessage(@PathParam(&quot;name&quot;) String name) {<br>    ...<br>}</pre><h4>Try it</h4><p>Build and run the revised application:</p><pre>mvn package<br>java -jar target/quickstart-mp.jar</pre><p>Access the Micrometer endpoint:</p><pre>curl <a href="http://localhost:8080/micrometer">http://localhost:8080/micrometer</a><br># HELP allGets_seconds_max Tracks all GET operations<br># TYPE allGets_seconds_max gauge<br>allGets_seconds_max 0.0<br># HELP allGets_seconds Tracks all GET operations<br># TYPE allGets_seconds summary<br>allGets_seconds_count 0.0<br>allGets_seconds_sum 0.0<br># HELP personalizedGets_total Counts personalized GET operations<br># TYPE personalizedGets_total counter<br>personalizedGets_total 0.0</pre><p>Retrieve at least one greeting:</p><pre>% curl <a href="http://localhost:8080/greet">http://localhost:8080/greet</a><br>{&quot;message&quot;:&quot;Hello World!&quot;}</pre><pre>% curl <a href="http://localhost:8080/greet/reader">http://localhost:8080/greet/reader</a><br>{&quot;message&quot;:&quot;Hello reader!&quot;}</pre><p>Check the Micrometer output again, noting the change in values:</p><pre>curl <a href="http://localhost:8080/micrometer">http://localhost:8080/micrometer</a><br># HELP allGets_seconds_max Tracks all GET operations<br># TYPE allGets_seconds_max gauge<br><strong>allGets_seconds_max 0.003666501</strong><br># HELP allGets_seconds Tracks all GET operations<br># TYPE allGets_seconds summary<br><strong>allGets_seconds_count 2.0</strong><br>allGets_seconds_sum 0.003923641<br># HELP personalizedGets_total Counts personalized GET operation<br># TYPE personalizedGets_total counter<br><strong>personalizedGets_total 1.0</strong></pre><h3>Summary</h3><p>With just a few changes, you can add Micrometer support for your own metrics to your Helidon SE or MP application and make those metrics accessible at the built-in /micrometer endpoint.</p><p>Built-in Helidon metrics continue to be available at the/metricsendpoint.</p><p>Go to our documentation site to find out more about Micrometer support in <a href="https://helidon.io/docs/latest/#/se/metrics/02_micrometer">Helidon SE</a> and <a href="https://helidon.io/docs/latest/#/mp/metrics/02_micrometer">Helidon MP</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c8dfc7ccd1de" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/using-micrometer-in-helidon-applications-c8dfc7ccd1de">Using Micrometer in Helidon Applications</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Helidon 2.0 and CORS]]></title>
            <link>https://medium.com/helidon/helidon-2-0-and-cors-14f34e2b1d17?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/14f34e2b1d17</guid>
            <category><![CDATA[helidon]]></category>
            <category><![CDATA[cors]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Thu, 25 Jun 2020 02:01:01 GMT</pubDate>
            <atom:updated>2020-06-25T02:01:01.361Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J5IrGcbxYw_hsz8RjMbz-Q.png" /></figure><p>Beginning with newly-released Helidon 2.0 [1], you can easily add CORS support to your application and to Helidon’s built-in services for health, metrics, and OpenAPI.</p><p>A <em>same-origin policy</em> [2], implemented in browsers and other well-behaved web clients, restricts a page or app from one origin — URL scheme, host, and port — from accessing resources from other origins.</p><p>But, in certain cases, relaxing that restriction makes sense. <em>Cross-origin resource sharing</em> (CORS) [3] is a standard approach using HTTP headers in which web clients ask for and servers grant (or refuse) controlled access to resources from one origin on behalf of a resource in a different origin.</p><p>With the recent release of Helidon 2.0, you can easily add CORS support to the endpoints in your own SE [4] and MP [5] applications as well as the endpoints of built-in Helidon services such as health, metrics, and OpenAPI.</p><p>The examples below are inspired by the Helidon greeting example app [6, 7]. We’ll assume that you want to permit resources from <a href="http://foo.com">http://foo.com</a> and <a href="http://there.com">http://there.com</a> to have PUT and DELETE access to your app’s resources while granting simple access — GET, HEAD, etc. — to all other origins.</p><h3>CORS in Helidon SE</h3><h4>Add this dependency to your pom.xml</h4><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.webserver&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-webserver-cors&lt;/artifactId&gt;<br>&lt;/dependency&gt;</pre><h4>Create a CorsSupport instance in your code</h4><p>Build a CorsSupport object to represent the CORS behavior you want for your app’s resources. You use two CrossOriginConfig objects, one for the PUT and DELETE access and a second for all other access:</p><pre>CorsSupport corsSupport = CorsSupport.builder()<br>    .addCrossOriginConfig(CrossOriginConfig.builder()<br>        .allowOrigins(&quot;http://foo.com&quot;, &quot;http://there.com&quot;)<br>        .allowMethods(&quot;PUT&quot;, &quot;DELETE&quot;)<br>        .build())<br>    .addCrossOriginConfig(CrossOriginConfig.create())<br>        .build();</pre><h4>Use the CorsSupport instance</h4><p>Use the instance of CorsSupport <em>in the same </em><em>register call </em>that sets up routing for your application’s path:</p><pre>return Routing.builder()<br>    .register(JsonSupport.create())<br>    .register(health)                  // Health at &quot;/health&quot;<br>    .register(metrics)                 // Metrics at &quot;/metrics&quot;<br>   <strong> .register(&quot;/greet&quot;, corsSupport, greetService)</strong><br>    .build();</pre><p>Then rebuild and restart your app. That’s it. See below for some simple ways to see the CORS support in action with your app.</p><h3>CORS in Helidon MP</h3><h4>Add this dependency to your pom.xml</h4><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile-cors&lt;/artifactId&gt;<br>&lt;/dependency&gt;</pre><h4>Use the @CrossOrigin annotation</h4><p>In your JAX-RS resource class, add a no-op method for HTTP OPTIONS requests and annotate it:</p><pre>@OPTIONS<br><strong>@CrossOrigin(<br>    allowMethods = {&quot;PUT&quot;, &quot;DELETE&quot;}, <br>    allowOrigins = {&quot;http://foo.com&quot;, &quot;http://there.com&quot;})</strong><br>public void optionsForGreeting() {}</pre><p>Then rebuild and restart your app.</p><h3>Trying it out (SE and MP)</h3><p>You can use curl to see Helidon’s CORS support in action for your app’s endpoints. The code snippets below highlight the CORS-related headers.</p><p>For “simple” operations — GET, HEAD, etc. — CORS simply adds headers to the normal HTTP request.</p><pre>curl -i -X GET \<br>   <strong>-H &quot;Origin: http://foo.com&quot; -H &quot;Host: here.com&quot;</strong> \<br>   http://localhost:8080/greet</pre><p>And to the response.</p><pre>HTTP/1.1 200 OK<br><strong>Access-Control-Allow-Origin: *</strong><br>Content-Type: application/json<br>Date: Thu, 30 Apr 2020 17:25:51 -0500<br><strong>Vary: Origin</strong><br>connection: keep-alive<br>content-length: 27<br><br>{&quot;greeting&quot;:&quot;Hello World!&quot;}</pre><p>For so-called “non-simple” operations that can change the application’s server-side state, CORS uses a <em>pre-flight</em> request that lets the server “pre-approve” the desired access as declared by the client. Usually a browser sends pre-flight requests (and checks the responses) invisibly, but the followingcurl command simulates this step:</p><pre>curl -i <strong>-X OPTIONS \<br>    -H &quot;Access-Control-Request-Method: PUT&quot; \<br>    -H &quot;Origin: http://foo.com&quot; \<br>    -H &quot;Host: here.com&quot; \</strong><br>    http://localhost:8080/greet/greeting</pre><p>The server indicates that it is OK with the requested cross-origin resource sharing:</p><pre>HTTP/1.1 200 OK<br><strong>Access-Control-Allow-Methods: PUT<br>Access-Control-Allow-Origin: http://foo.com<br></strong>Date: Thu, 30 Apr 2020 17:30:59 -0500<br>transfer-encoding: chunked<br>connection: keep-alive</pre><p>At this point the client issues the desired PUT request, in our example to change the greeting:</p><pre>curl -i -X PUT \<br><strong>    -H &quot;Origin: http://foo.com&quot; \<br>    -H &quot;Host: here.com&quot; \<br>    -H &quot;Access-Control-Allow-Methods: PUT&quot; \<br>    -H &quot;Access-Control-Allow-Origin: http://foo.com&quot; \</strong><br>    -H &quot;Content-Type: application/json&quot; \<br>    -d &quot;{ \&quot;greeting\&quot; : \&quot;Cheers\&quot; }&quot; \<br>    http://localhost:8080/greet/greeting</pre><p>The server responds normally:</p><pre>HTTP/1.1 204 No Content<br><strong>Access-Control-Allow-Origin: http://foo.com</strong><br>Date: Thu, 30 Apr 2020 17:32:55 -0500<br><strong>Vary: Origin</strong><br>connection: keep-alive</pre><h3>Bottom Line</h3><p>With very little extra code, your Helidon SE or MP application’s endpoints can participate in the CORS protocol. And we’ve only hit the high points here. You can use configuration to simplify your CORS-related changes even more.</p><p>Further, you can easily turn on and control CORS for Helidon’s built-in services that add endpoints to your application: health, metrics, and OpenAPI.</p><p>For complete information, please refer to the documentation ([4], [5]).</p><h3>References</h3><p>[1] <a href="https://helidon.io">https://helidon.io</a><br>[2] <a href="https://www.w3.org/Security/wiki/Same_Origin_Policy">https://www.w3.org/Security/wiki/Same_Origin_Policy</a><br>[3] <a href="https://www.w3.org/TR/cors/">https://www.w3.org/TR/cors/</a><br>[4] <a href="https://helidon.io/docs/2.0.0-RC2/#/se/cors/01_introduction">https://helidon.io/docs/latest/#/se/cors/01_introduction</a><br>[5] <a href="https://helidon.io/docs/2.0.0-RC2/#/mp/cors/01_introduction">https://helidon.io/docs/latest/#/mp/cors/01_introduction</a><br>[6] <a href="https://github.com/oracle/helidon/tree/2.0.0-RC2/examples/cors">https://github.com/oracle/helidon/tree/latest/examples/cors</a><br>[7] <a href="https://github.com/oracle/helidon/tree/2.0.0-RC2/examples/microprofile/cors">https://github.com/oracle/helidon/tree/latest/examples/microprofile/cors</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=14f34e2b1d17" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/helidon-2-0-and-cors-14f34e2b1d17">Helidon 2.0 and CORS</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MicroProfile 3.2 and Helidon MP 1.4 — new maven bundles]]></title>
            <link>https://medium.com/helidon/microprofile-3-2-and-helidon-mp-1-4-new-maven-bundles-a9f2bdc1b5eb?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/a9f2bdc1b5eb</guid>
            <category><![CDATA[microprofile]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[helidon]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Tue, 03 Dec 2019 10:32:02 GMT</pubDate>
            <atom:updated>2019-12-03T10:39:13.698Z</atom:updated>
            <content:encoded><![CDATA[<h3>MicroProfile 3.2 and Helidon MP 1.4 — new Maven bundles</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NF_Daw9WreeRP2y40SFGJg.png" /></figure><p>The recent 1.4 release of <a href="https://github.com/oracle/helidon/releases/tag/1.4.0">Project Helidon</a> includes support for the new <a href="https://github.com/eclipse/microprofile/releases/tag/3.2">MicroProfile 3.2 release</a>.</p><p>The major change in the new MicroProfile release is <a href="https://github.com/eclipse/microprofile-metrics/releases/tag/2.2">MicroProfile Metrics 2.2</a> (which is basically the same as 2.1 but with one incompatible change reverted).</p><h3>TL;DR — existing Helidon MP apps work with Helidon 1.4</h3><h4>Updating the Helidon version</h4><p>Your existingpom.xml probably already has a dependency on some Helidon MP bundle. Change the &lt;version&gt; in that dependency to &lt;1.4.0&gt;.</p><h4>Using the same, earlier MicroProfile release</h4><p>By simply changing the Helidon version as above, you allow your app to use Helidon 1.4 with whatever earlier MicroProfile release you had been using.</p><h4>Using MicroProfile 3.2</h4><p>To use MicroProfile 3.2 in your app <em>remove</em> the MicroProfile release number suffix from your existing bundle dependency:</p><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile.bundles&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile&lt;/artifactId&gt;<br>  &lt;version&gt;1.4.0&lt;/version&gt;<br>&lt;/dependency&gt;</pre><p>There is no Helidon MP bundle artifact with 3.2 in its name. The helidon-microprofile bundle <em>is</em> the MicroProfile 3.2 support in Helidon 1.4.</p><h4>Looking ahead</h4><p>You do not <em>have</em> to change anything else, but you might <em>want</em> to make some other changes in your pom.xml file to optimize your app and to prepare for future Helidon releases.</p><p>Here’s why.</p><h3>Moving to a new bundling approach</h3><h4>Background</h4><p>All Helidon MP releases (including 1.4) have included bundles corresponding to the various MicroProfile releases. For example, in your application’s pom.xml you could include a dependency on io.helidon.microprofile.bundles:helidon-microprofile-2.2 to use the MicroProfile 2.2 API and the Helidon implementation of it. Each numbered bundle contains _all_ of the Helidon MP artifacts for that MicroProfile release.</p><h4>Technology-focused, not version-focused, bundles</h4><p>Beginning with Helidon 1.4 we are deprecating those numbered MP bundles. Helidon 1.4 still includes bundles for MP releases up through MP 3.0.¹ But we plan to remove those numbered bundles from releases beyond 1.4.</p><p>Instead you will choose one of two Helidon MicroProfile bundles, not related to MicroProfile releases but rather to sets of MicroProfile technologies: a <em>core</em> bundle and a <em>full</em> bundle. In each Helidon release these bundles will support the then-current MicroProfile release. The Helidon release notes always identify which MicroProfile release is supported.</p><h4>Helidon MP core bundle</h4><p>The new core bundle includes the bare minimum to run the simplest microservices: the Helidon MP server, JAX-RS, CDI, JSON, and MicroProfile config. Use the core bundle by using this dependency in your application’s pom.xml file:</p><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile.bundles&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile-core&lt;/artifactId&gt;<br>  &lt;version&gt;1.4.0&lt;/version&gt;<br>&lt;/dependency&gt;</pre><p>If your app uses other MicroProfile technologies, add dependencies for those specific Helidon MP modules. For example, to add metrics support beyond what is in core, just add the metrics dependency to the one for the core bundle:²</p><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile.bundles&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile-core&lt;/artifactId&gt;<br>  &lt;version&gt;1.4.0&lt;/version&gt;<br>&lt;/dependency&gt;<br>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile.metrics&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile-metrics2&lt;/artifactId&gt;<br>  &lt;version&gt;1.4.0&lt;/version&gt;<br>&lt;/dependency&gt;</pre><p>We expect many developers will start with the core bundle and then add the specific additional dependencies each app requires. This makes very clear exactly what each app depends on and helps minimize its footprint.</p><h4>Helidon MP full bundle</h4><p>As an alternative, you can depend on the full bundle which, as with the older-style numbered bundles, includes _all_ the Helidon MP artifacts. You can add this dependency to your pom:</p><pre>&lt;dependency&gt;<br>  &lt;groupId&gt;io.helidon.microprofile.bundles&lt;/groupId&gt;<br>  &lt;artifactId&gt;helidon-microprofile&lt;/artifactId&gt;<br>  &lt;version&gt;1.4.0&lt;/version&gt;<br>&lt;/dependency&gt;</pre><p>Note that the artifact ID for the full bundle is just helidon-microprofile — no suffix.</p><p>Because the full bundle includes all the Helidon MP artifacts, you will not have to add any other dependencies to use any of the MicroProfile technologies. Although using the full bundle is a little simpler for you as a developer, it does hide exactly what technologies your app actually uses and might result in a bigger Docker image, for example.</p><h4>How does this help developers?</h4><p>Under the previous approach, with the numbered artifact IDs for the Helidon MP bundles, developers who wanted to adopt a newer MicroProfile release would have to update their pom.xml files in two ways:</p><ol><li>the &lt;version&gt; for the Helidon MP bundle (<em>e.g.</em>, from 1.3.1 to 1.4.0), and</li><li>the &lt;artifactId&gt; for the Helidon MP bundle (<em>e.g.</em>, from helidon-microprofile-2.2 to helidon-microprofile-3.0).</li></ol><p>With Helidon 1.4, and going forward, you will need to update only the Helidon &lt;version&gt; and you will automatically get the APIs and implementations for the corresponding (typically, the then-current) MicroProfile release.</p><p>We believe this matches up with how most developers work: when they adopt a new implementation of Helidon they typically also will want to move to the current MicroProfile APIs and technologies.</p><h4>Any drawbacks?</h4><p>After Helidon 1.4, to use an older MicroProfile release you must use the corresponding older Helidon release that supports that MicroProfile version. We will not offer a way for you to upgrade Helidon but stay with an older release of MicroProfile.</p><p>To the extent that successive MicroProfile releases are backward compatible, applications written to older MicroProfile APIs will continue to work even with newer MP and Helidon releases. But, if and when future MicroProfile releases include <em>incompatible</em> changes, you might need to revise your apps accordingly in order to adopt the latest Helidon releases.</p><p>[1] Actually, there is also a bundle for MP 3.1 but don’t use that one because it had to rely on the problematic API change in MP metrics 2.1 mentioned earlier.</p><p>[2] By the way, the 2 in the Helidon MP metrics artifact ID is important. Helidon currently supports both MicroProfile Metrics 1 and 2 to ease developers’ transition with the API incompatibilities between those metrics versions.</p><p>For Helidon 1.4 be sure to use the metrics2 artifact to bind to the latest metrics API and implementation. In a future major release we plan to retire metrics2 and going forward the metrics artifact will again be the then-current metrics.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a9f2bdc1b5eb" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/microprofile-3-2-and-helidon-mp-1-4-new-maven-bundles-a9f2bdc1b5eb">MicroProfile 3.2 and Helidon MP 1.4 — new maven bundles</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reusability in MicroProfile Metrics 2.0 and Helidon 1.3]]></title>
            <link>https://medium.com/helidon/reusability-in-microprofile-metrics-2-0-and-helidon-1-3-a9bb1555011b?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/a9bb1555011b</guid>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Mon, 07 Oct 2019 09:54:16 GMT</pubDate>
            <atom:updated>2019-10-07T09:54:16.272Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NF_Daw9WreeRP2y40SFGJg.png" /></figure><p>Helidon 1.3 has been released, and it includes support for MicroProfile 3.0. Metrics 2.0 is part of that MicroProfile release.</p><p>In an <a href="https://medium.com/helidon/microprofile-metrics-in-helidon-1-3-640694c79fd6">earlier article</a>, Santiago has described some of the backward-incompatible changes from MP Metrics 1.1 to 2.0, and how Helidon 1.3 can help insulate you as a developer from those changes if you want.</p><p>This post talks about <em>registering, referencing, </em>and <em>reusing</em> metrics. Notably, one aspect of metric reusability has changed from MP Metrics 1.1 to 2.0 and we’ll get to that. There is also some ambiguity in the spec about reusability; this article describes how Helidon handles it.</p><h3>Registering metrics</h3><p>Think of <em>registering</em> a metric as recording a place in your app that updates that metric.</p><p>This code registers a meter by annotating a JAX-RS endpoint:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/85412276ad1d570795d1672a83ca1365/href">https://medium.com/media/85412276ad1d570795d1672a83ca1365/href</a></iframe><p>As specified by the MP metric naming convention, this metric has the name com.mycorp.myapp.MyEndpoints.greetings (package plus class plus method).</p><p>The system registers this meter for you in the application registry and automatically updates the meter as this greet method is invoked.</p><p>Or, you can register a metric explicitly in your application code. Here is one way:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/008bf1b36d215d4800b2ab3a5a00caea/href">https://medium.com/media/008bf1b36d215d4800b2ab3a5a00caea/href</a></iframe><p>Your code needs to declare the meter, instantiate it, register it, and update it. Most developers find using the annotations more convenient.</p><h3>Referencing (referring to) metrics</h3><p>In this article, <em>referencing</em> a metric means “get if present, register if absent.” That is, if the metric has been previously registered then get a reference to it; otherwise, register the metric and use a reference to that newly-created one.</p><p>You will not find the term “referencing” or “referring to” metrics in the MP Metrics spec. I think it’s helpful to distinguish <em>referencing </em>from <em>registering</em> metrics, because some additional metrics annotations and APIs we are about to look at behave differently from the ones we saw earlier which actually do <em>register</em> a metric.</p><p>Here are three ways to <em>reference</em> a metric. There are more variations but these give us plenty to talk about:</p><ol><li>using @Inject on a Meter field: (both of these @Injects are equivalent)</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4587503dc268b2a23b801bc4637c8b0f/href">https://medium.com/media/4587503dc268b2a23b801bc4637c8b0f/href</a></iframe><p>2. programmatically, by metric name:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b652ee9c48a23c9ea67db1060374e58e/href">https://medium.com/media/b652ee9c48a23c9ea67db1060374e58e/href</a></iframe><p>3. programmatically, by metadata:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4100952791dd59751bb87afe4159534a/href">https://medium.com/media/4100952791dd59751bb87afe4159534a/href</a></iframe><p>In these three examples, the system cannot automatically update the metric because it does not know what you want to measure with the meter. You would need to write your own code to do that.</p><p>Taken by themselves, each of these examples would indeed register the metric, because the “get-if-present” step of the reference would not find an existing metric, so the “register-if-absent” step would kick in.</p><p>What if your application combines <em>more than one</em> of the above techniques?</p><p>For example, suppose your application used the original @Metered annotation and also example 1? The @Metered annotation would <em>register</em> the metric and the @Inject sites would <em>reference </em>it by getting the already-registered metric.</p><p>In fact, if your app uses the original @Metered annotation and <em>all</em> of the examples above, then using our terms all of the example code <em>reference</em> the metric and get the already-registered one; only the @Metered annotation registers the metric.</p><p>One interesting point: The exact same lines of code can either register or reference a metric, depending on what else is in your app. Usually this doesn’t matter too much, but it’s noteworthy. In fact, we glossed over this earlier. Example 1, with its two @Inject usages, illustrates this by itself. Internally, one @Inject will register the metric and the other will get a reference to it. We cannot predict which is which and that’s fine because it doesn’t matter; the injections occur before our code runs anyway.</p><p>Note that referencing is <em>not</em> what MP Metrics means by metric reuse!</p><h3>Reusing metrics</h3><p>Well, then, what <em>is</em> metric reuse?</p><p>Metric reuse is <em>multiple registration</em> of the same metric using annotations.</p><p>Continuing our earlier example, if your app has more than one @Metered annotation then those injection sites <em>reuse</em> the metric:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/553b4518e25608481806ce99e7251810/href">https://medium.com/media/553b4518e25608481806ce99e7251810/href</a></iframe><p>Here, the system will register the meter and automatically update it<em> at both annotation sites.</em></p><p>We might write the code this way if we don’t care about measuring the two methods separately, but instead we are interested in the aggregate traffic to our app for retrieving greetings, regardless of the format (plain text or HTML) the client might request.</p><p><em>This </em>is reuse of the metric.</p><p>Note that gauges are never reusable, but the other types can be if you declare them to be.</p><h4>State your intentions</h4><p>By default, MP Metrics forbids reuse of a metric registered using annotations. This is why we had to add reusable = true to the @Metered annotations above when we wanted to reuse that metric. Without that, the system would throw an exception trying to register the metric the second time because on the annotations the default setting is reusable = false.</p><p>Why is this? The MP Metrics spec makes the very valid point that this prevents <em>accidental</em> reuse of a metric due to careless copy-and-paste as you write code. You could inadvertently have one metric collecting data from multiple unrelated points in your application, leaving you with useless data in that metric.</p><p>If your application also included example 1, as written, the injected fields would always give your code access to the current values for the single, reused metric.</p><p>Remember that annotations like @Metered can convey other metadata as well, as can other injection points using the @Metric annotation. Anywhere you refer to the same metric, <em>all</em> the metadata specified at <em>all</em> annotation sites must agree. That includes the reusability setting.</p><h4>Metadata and reusability in the API</h4><p>The earlier examples 2 and 3 show how your code can refer to a metric programmatically by invoking methods on a MetricRegistry object: counter, concurrentGauge, histogram, meter, and timer. (Again, gauges are treated a little differently and there is no such method for those.)</p><p>A few important points:</p><ol><li>The rule about metadata consistency for a metric includes calls into the API. If your application references a metric by passing metadata (as in example 3 above), then the metadata supplied on all the API invocations and on all the annotations referring to that metric must agree.</li><li>Using the API, if you do not specify the reusability when you build the metadata then in MP Metrics 2.0 the default reusability is true, not false as it is with annotations.</li><li>You cannot reuse a metric by invoking MetricRegistry.register multiple times for the same metric. The register methods fail if the metric already exists under the same name. Instead, simply invoke MetricRegistry.register once, save the metric in a variable, and then access the variable from multiple places to update the metric.</li></ol><h4>Change in default reusability in MP Metrics 1.1 vs. 2.0</h4><p>Here’s the backward-incompatible change in MP Metrics we mentioned at the outset.</p><p>If you have been working with MP Metrics 1.1, the default reusability when using the API <em>has changed</em>. In 1.1, reusability always defaulted to false, via the API and annotations. As described earlier, in MP Metrics 2.0 the default reusability via the API is true and remains false in annotations.</p><h3>Bottom Line</h3><p>Let’s recap.</p><p>We’ve used a meter as an example metric, but the same ideas apply to any metric:</p><ul><li>counters (@Counted)</li><li>concurrent gauges (@ConcurrentGauge )</li><li>gauges ( @Gauge ) — although remember, you cannot reuse gauges</li><li>histograms (no annotation but you can add an @Inject or @Metric annotation to a field of type Histogram for example)</li><li>meters ( @Metered )</li><li>timers ( @Timed )</li></ul><p>You can <em>register</em> a metric using one of these annotations and <em>reference </em>it using @Inject or @Metric or the API.</p><p>Referencing a metric uses “get if present, register if absent” semantics.</p><p>You can <em>reuse</em> a metric (except for gauges) by registering multiple places in your app using the same annotation at each site, explicitly setting reusability = true each time.</p><h3>Acknowledgements</h3><p>Thanks to <a href="https://medium.com/@santiago.pericasgeertsen?source=post_page-----640694c79fd6----------------------">Santiago Pericas-Geertsen</a> who, in private conversations, helped identify some of the ambiguity in the spec and clarify my own thinking about this topic. And to Jan Martiška who, in the MicroProfile Google group, explained some of the original intent about MP metrics reuse.</p><h3>References</h3><ul><li><a href="https://download.eclipse.org/microprofile/microprofile-metrics-2.0.2/microprofile-metrics-spec-2.0.2.html">MicroProfile Metrics 2.0.2 spec</a></li><li><a href="https://helidon.io/">Project Helidon website</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a9bb1555011b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/reusability-in-microprofile-metrics-2-0-and-helidon-1-3-a9bb1555011b">Reusability in MicroProfile Metrics 2.0 and Helidon 1.3</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Project Helidon and OpenAPI]]></title>
            <link>https://medium.com/helidon/project-helidon-and-openapi-54a1fadc75b1?source=rss-66479c519f05------2</link>
            <guid isPermaLink="false">https://medium.com/p/54a1fadc75b1</guid>
            <category><![CDATA[microprofile]]></category>
            <category><![CDATA[helidon]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[open-api]]></category>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Tim Quinn]]></dc:creator>
            <pubDate>Mon, 17 Jun 2019 23:07:36 GMT</pubDate>
            <atom:updated>2019-09-30T20:32:51.046Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4an1OKIgU-Pd4_vmgqiSNw.jpeg" /></figure><p>Here’s how to use OpenAPI in your Helidon SE and MP apps.</p><p><a href="https://helidon.io">Helidon</a> is a collection of Java libraries for writing microservices. Helidon MP supports <a href="https://microprofile.io">MicroProfile</a>, and Helidon SE offers a functional-style API, both of which help you write microservices in Java quickly.</p><p>Beginning with release 1.1.1, Helidon supports <a href="https://github.com/OAI/OpenAPI-Specification">OpenAPI</a>. Helidon MP implements the <a href="https://github.com/eclipse/microprofile-open-api">MicroProfile OpenAPI spec</a>, and you can support OpenAPI in your SE app as well. Our documentation describes all the details for <a href="https://helidon.io/docs/latest/index.html#/microprofile/08_openapi">MP</a> and <a href="https://helidon.io/docs/latest/index.html#/openapi/01_openapi">SE</a>, and our GitHub repository includes fully-working example apps with OpenAPI for <a href="https://github.com/oracle/helidon/tree/master/examples/microprofile/openapi-basic">MP</a> and <a href="https://github.com/oracle/helidon/tree/master/examples/openapi">SE</a>.</p><p>This article shows the very simplest way to add OpenAPI support to your applications.</p><p>The changes you make depend on whether you use Helidon MP or SE, so there are separate sections for each below. The way you access your app’s OpenAPI document is the same, so that’s described once near the end.</p><h3>Using OpenAPI in Helidon MP</h3><h4>Update your pom.xml</h4><p>Build a Jandex index that will be used to speed up scanning for OpenAPI-related annotations. In the &lt;build&gt;&lt;plugins&gt; section add:</p><pre>&lt;plugin&gt;<br>    &lt;groupId&gt;org.jboss.jandex&lt;/groupId&gt;<br>    &lt;artifactId&gt;jandex-maven-plugin&lt;/artifactId&gt;<br>    &lt;version&gt;1.0.6&lt;/version&gt;<br>    &lt;executions&gt;<br>      &lt;execution&gt;<br>          &lt;id&gt;make-index&lt;/id&gt;<br>          &lt;goals&gt;<br>              &lt;goal&gt;jandex&lt;/goal&gt;<br>          &lt;/goals&gt;<br>      &lt;/execution&gt;<br>    &lt;/executions&gt;<br>&lt;/plugin&gt;</pre><p>Add dependencies so you can use OpenAPI annotations (see below) and so the Helidon OpenAPI runtime (and the rest of Helidon support for MicroProfile 2.2) will be present when your app runs.</p><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;org.eclipse.microprofile.openapi&lt;/groupId&gt;<br>    &lt;artifactId&gt;microprofile-openapi-api&lt;/artifactId&gt;<br>    &lt;version&gt;1.1.2&lt;/version&gt;<br>&lt;/dependency</pre><pre>&lt;dependency&gt;<br>    &lt;groupId&gt;io.helidon.microprofile.bundles&lt;/groupId&gt;<br>    &lt;artifactId&gt;helidon-microprofile-2.2&lt;/artifactId&gt;<br>    &lt;version&gt;1.1.2&lt;/version&gt;<br>&lt;/dependency&gt;</pre><h4>Annotate the endpoints</h4><p>Add OpenAPI annotations to your app’s endpoints.</p><p>Here’s a simple GET endpoint from the working example, updated for OpenAPI:</p><pre><a href="http://twitter.com/GET">@GET</a><br>@<a href="http://twitter.com/Operation">Operation</a>(<br>    summary = &quot;Returns a generic greeting&quot;,<br>    description = &quot;Greets the user generically&quot;)<br><a href="http://twitter.com/APIResponse">@APIResponse</a>(<br>    description = &quot;Simple JSON containing the greeting&quot;,<br>    content = <a href="http://twitter.com/Content">@Content</a>(<br>        mediaType = &quot;application/json&quot;,<br>        schema = <a href="http://twitter.com/Schema">@Schema</a>(implementation = GreetingMessage.class)))<br><a href="http://twitter.com/Produces">@Produces</a>(MediaType.APPLICATION_JSON)<br>public JsonObject getDefaultMessage() {...}</pre><p>The @Operation and @APIResponse annotations are new.</p><h3>Using OpenAPI in Helidon SE</h3><p>OpenAPI support in SE is basically the same as in MP except for annotation processing. SE does not do annotation processing, so OpenAPI cannot rely on that to gather endpoint information.</p><p>Instead, your SE app will typically include a static file containing the OpenAPI document that describes the app’s endpoints.</p><p>Follow these steps:</p><h4>Update your pom.xml</h4><p>Add this dependency:</p><pre>&lt;dependency&gt;<br>     &lt;groupId&gt;io.helidon.openapi&lt;/groupId&gt;<br>     &lt;artifactId&gt;helidon-openapi&lt;/artifactId&gt;<br>     &lt;version&gt;1.1.2&lt;/version&gt;<br>&lt;/dependency&gt;</pre><h4>Register OpenAPISupport in your code</h4><p>Your SE app will already have code similar to this. Just add the line that registers OpenAPISupport:</p><pre>Config config = Config.create();<br>...<br>return Routing.builder()<br>         .register(JsonSupport.create())<br>         <strong>.register(OpenAPISupport.create(config))</strong><br>         .register(health)<br>         .register(metrics)<br>         .register(&quot;/greet&quot;, greetService)<br>         .build();</pre><h4>Add a static OpenAPI document file</h4><p>Tools such as Swagger let you describe your app’s API and they then generate an OpenAPI document file. Or you can just use an editor and create the file manually.</p><p>Once you have the file, add it to your project at META-INF/openapi.yml. The Helidon OpenAPI support will find it automatically.</p><h3>Access the OpenAPI document</h3><p>After you make the changes and build your app, run it. Then send a GET request to the automatically-supported/openapi endpoint. You will see a lot of output, including this describing the endpoint in the source code above:</p><pre>paths:<br>  /greet:<br>    get:<br>      summary: Returns a generic greeting<br>      description: Greets the user generically<br>      responses:<br>        default:<br>          description: Simple JSON containing the greeting<br>          content:<br>            application/json:<br>              schema:<br>                $ref: &#39;#/components/schemas/GreetingMessage&#39;</pre><h3>What next?</h3><p>We’ve just scratched the surface here. For example, your MP or SE app can contain your own code that programmatically adds to or changes the OpenAPI model of your endpoints: <em>model readers</em> and <em>filters</em>.</p><p>In fact, Helidon OpenAPI support combines endpoint information from all of these sources:</p><ul><li>static documents,</li><li>annotations (only for MP),</li><li>configuration settings,</li><li>model reader, and</li><li>filter.</li></ul><p>Our documentation at <a href="https://helidon.io/docs">https://helidon.io/docs</a> goes much further. Look for OpenAPI (that’s for SE) and MicroProfile -&gt; OpenAPI in the navigation panel. Here are direct links to the <a href="https://helidon.io/docs/latest/index.html#/openapi/01_openapi">SE</a> and <a href="https://helidon.io/docs/latest/index.html#/microprofile/08_openapi">MP</a> OpenAPI doc pages.</p><p>And remember the examples in the Helidon GitHub site are ready to build and run: <a href="https://github.com/oracle/helidon/tree/master/examples/openapi">openapi</a> for SE and <a href="https://github.com/oracle/helidon/tree/master/examples/microprofile/openapi-basic">openapi-basic</a> for MP.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=54a1fadc75b1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/helidon/project-helidon-and-openapi-54a1fadc75b1">Project Helidon and OpenAPI</a> was originally published in <a href="https://medium.com/helidon">Helidon</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>