Modified: tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-metered.html URL: http://svn.apache.org/viewvc/tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-metered.html?rev=1849998&r1=1849997&r2=1849998&view=diff ============================================================================== --- tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-metered.html (original) +++ tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-metered.html Sun Dec 30 19:02:51 2018 @@ -88,59 +88,138 @@ <div class="col-md-12"> <div class='page-header'> - <h1>null</h1> + <h1>MicroProfile Metrics Metered</h1> </div> </div> </div> <div class="row"> <div class="col-md-12"> - <h1>Microprofile Metrics</h1> + <div id="preamble"> +<div class="sectionbody"> +<div class="paragraph"> <p>This is an example on how to use microprofile metrics in TomEE.</p> -<h5>Run the application:</h5> -<pre><code>mvn clean install tomee:run -</code></pre> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_run_the_application">Run the application:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>mvn clean install tomee:run</pre> +</div> +</div> +<div class="paragraph"> <p>Within the application, there is an enpoint that will give you a weather weather status for the day and week.</p> -<h5>For the day status call:</h5> -<pre><code>GET http://localhost:8080/mp-metrics-metered/weather/day/status -</code></pre> -<h5>Response:</h5> -<pre><code>Hi, today is a sunny day! -</code></pre> -<h4>Metered Feature</h4> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_for_the_day_status_call">For the day status call:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>GET http://localhost:8080/mp-metrics-metered/weather/day/status</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_response">Response:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>Hi, today is a sunny day!</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_metered_feature">Metered Feature</h2> +<div class="sectionbody"> +<div class="paragraph"> <p>MicroProfile metrics has a feature that can be used to find the rate of requests to a service.</p> +</div> +<div class="paragraph"> <p>To use this feature you need to annotate the JAX-RS resource method with @Metered.</p> -<pre><code>@Path("/weather") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@ApplicationScoped -public class WeatherService { +</div> +<div class="listingblock"> +<div class="content"> +<pre class="highlight"><code class="language-java" data-lang="java"> @Path("/weather") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApplicationScoped + public class WeatherService { - @Path("/day/status") - @Metered(name = "dailyStatus", unit = MetricUnits.MINUTES, description = "Metrics to daily weather status method", absolute = true) - @GET - @Produces(MediaType.TEXT_PLAIN) - public String dayStatus() { - return "Hi, today is a sunny day!"; - } -... -} -</code></pre> + @Path("/day/status") + @Metered(name = "dailyStatus", unit = MetricUnits.MINUTES, description = "Metrics to daily weather status method", absolute = true) + @GET + @Produces(MediaType.TEXT_PLAIN) + public String dayStatus() { + return "Hi, today is a sunny day!"; + } + ... + }</code></pre> +</div> +</div> +<div class="paragraph"> <p>There are some configurations, as part of @Metered, that you need to know:</p> -<p><strong>String name</strong><br/>Optional. Sets the name of the metric. If not explicitly given the name of the annotated object is used.</p> -<p><strong>boolean absolute</strong><br/>If true, uses the given name as the absolute name of the metric. If false, prepends the package name and class name before the given name. Default value is false.</p> -<p><strong>String displayName</strong><br/>Optional. A human-readable display name for metadata.</p> -<p><strong>String description</strong><br/>Optional. A description of the metric.</p> -<p><strong>String[] tags</strong><br/>Optional. Array of Strings in the <key>=<value> format to supply special tags to a metric.</p> -<p><strong>boolean reusable</strong><br/>Denotes if a metric with a certain name can be registered in more than one place. Does not apply to gauges.</p> -<p><strong>String unit</strong><br/>Unit of the metric. Default for @Metered is nanoseconds.</p> -<h4>Metric data</h4> +</div> +<div class="paragraph"> +<p><strong>String name</strong> +Optional. Sets the name of the metric. If not explicitly given the name of the annotated object is used.</p> +</div> +<div class="paragraph"> +<p><strong>boolean absolute</strong> +If true, uses the given name as the absolute name of the metric. If false, prepends the package name and class name before the given name. Default value is false.</p> +</div> +<div class="paragraph"> +<p><strong>String displayName</strong> +Optional. A human-readable display name for metadata.</p> +</div> +<div class="paragraph"> +<p><strong>String description</strong> +Optional. A description of the metric.</p> +</div> +<div class="paragraph"> +<p><strong>String[] tags</strong> +Optional. Array of Strings in the <key>=<value> format to supply special tags to a metric.</p> +</div> +<div class="paragraph"> +<p><strong>boolean reusable</strong> +Denotes if a metric with a certain name can be registered in more than one place. Does not apply to gauges.</p> +</div> +<div class="paragraph"> +<p><strong>String unit</strong> +Unit of the metric. Default for @Metered is nanoseconds.</p> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_metric_data">Metric data</h2> +<div class="sectionbody"> +<div class="paragraph"> <p>Check the Metered metric doing a <em>GET</em> request:</p> -<h5>Prometheus format:</h5> -<pre><code>GET http://localhost:8080/mp-metrics-metered/metrics/application/dailyStatus -</code></pre> -<h5>Response:</h5> -<pre><code># TYPE application:daily_status_seconds_count meter +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_prometheus_format">Prometheus format:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>GET http://localhost:8080/mp-metrics-metered/metrics/application/dailyStatus</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_response_2">Response:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre># TYPE application:daily_status_seconds_count meter application:daily_status_seconds_count 1.2E-7 # TYPE application:daily_status_rate_per_second meter application:daily_status_rate_per_second 0.0 @@ -149,44 +228,85 @@ application:daily_status_one_min_rate_pe # TYPE application:daily_status_five_min_rate_per_second meter application:daily_status_five_min_rate_per_second 3.5942838529305413E-20 # TYPE application:daily_status_fifteen_min_rate_per_second meter -application:daily_status_fifteen_min_rate_per_second 3.4665766454142955E-21 -</code></pre> -<h5>JSON Format:</h5> -<p>For json format add the header <em>Accept=application/json</em> to the request. </p> -<pre><code>{ - "dailyStatus": { - "count": 2, - "fifteenMinRate": 5.77762774235716e-14, - "fiveMinRate": 5.990473088217569e-13, - "meanRate": 0, - "oneMinRate": 2.229333774034164e-12, - "unit": "minutes" - } -} -</code></pre> -<h4>Metric metadata</h4> -<p>A metric will have a metadata so you can know more information about it, like displayName, description, tags etc.</p> +application:daily_status_fifteen_min_rate_per_second 3.4665766454142955E-21</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_json_format">JSON Format:</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>For json format add the header <em>Accept=application/json</em> to the request.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "dailyStatus": { + "count": 2, + "fifteenMinRate": 5.77762774235716e-14, + "fiveMinRate": 5.990473088217569e-13, + "meanRate": 0, + "oneMinRate": 2.229333774034164e-12, + "unit": "minutes" + } +}</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_metric_metadata">Metric metadata</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>A metric will have a metadata so you can know more information about it, like displayName, description, tags etc.</p> +</div> +<div class="paragraph"> <p>Check the metric metadata doing a <em>OPTIONS</em> request:</p> -<h5>Request</h5> -<pre><code>OPTIONS http://localhost:8080/mp-metrics-metered/metrics/application/dailyStatus -</code></pre> -<h5>Response:</h5> -<pre><code>{ - "dailyStatus": { - "description": "Metrics to daily weather status method", - "displayName": "", - "name": "dailyStatus", - "reusable": false, - "tags": "", - "type": "meter", - "typeRaw": "METERED", - "unit": "minutes" - } -} -</code></pre> -<h5>Test the application:</h5> -<pre><code>mvn test -</code></pre> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_request">Request</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>OPTIONS http://localhost:8080/mp-metrics-metered/metrics/application/dailyStatus</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_response_3">Response:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>{ + "dailyStatus": { + "description": "Metrics to daily weather status method", + "displayName": "", + "name": "dailyStatus", + "reusable": false, + "tags": "", + "type": "meter", + "typeRaw": "METERED", + "unit": "minutes" + } +}</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_test_the_application">Test the application:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>mvn test</pre> +</div> +</div> +</div> +</div> </div> </div>
Modified: tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-timed.html URL: http://svn.apache.org/viewvc/tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-timed.html?rev=1849998&r1=1849997&r2=1849998&view=diff ============================================================================== --- tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-timed.html (original) +++ tomee/site/trunk/content/tomee-8.0/examples/mp-metrics-timed.html Sun Dec 30 19:02:51 2018 @@ -88,58 +88,130 @@ <div class="col-md-12"> <div class='page-header'> - <h1>Microprofile Metrics Timed</h1> + <h1>MicroProfile Metrics Timed</h1> </div> </div> </div> <div class="row"> <div class="col-md-12"> - <h1>Microprofile Metrics</h1> + <div id="preamble"> +<div class="sectionbody"> +<div class="paragraph"> <p>This is an example on how to use MicroProfile metrics in TomEE.</p> -<h5>Run the application:</h5> -<pre><code>mvn clean install tomee:run -</code></pre> -<p>Within the application there is an endpoint that will give you the weather status for the day.</p> -<h5>For the day status call:</h5> -<pre><code>GET http://localhost:8080/mp-metrics-timed/weather/day/status -</code></pre> -<h5>Response:</h5> -<pre><code>Hi, today is a sunny day! -</code></pre> -<h4>Timed Feature</h4> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_run_the_application">Run the application:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>mvn clean install tomee:run</pre> +</div> +</div> +<div class="paragraph"> +<p>Within the application there is an endpoint that will give you the +weather status for the day.</p> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_for_the_day_status_call">For the day status call:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>GET http://localhost:8080/mp-metrics-timed/weather/day/status</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_response">Response:</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>Hi, today is a sunny day!</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_timed_feature">Timed Feature</h2> +<div class="sectionbody"> +<div class="paragraph"> <p>MicroProfile Metrics has a feature that tracks the time of an event.</p> -<p>To use this feature you need to annotate the JAX-RS resource method with @Timed.</p> -<pre><code>@Path("/weather") +</div> +<div class="paragraph"> +<p>To use this feature you need to annotate the JAX-RS resource method with +@Timed.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>@Path("/weather") @ApplicationScoped public class WeatherService { - @Path("/day/status") - @Timed(name = "weather_day_status", absolute = true, - displayName = "Weather Day Status", - description = "This metric shows the weather status of the day.") + @Path("/day/status") + @Timed(name = "weather_day_status", absolute = true, + displayName = "Weather Day Status", + description = "This metric shows the weather status of the day.") @GET @Produces(MediaType.TEXT_PLAIN) public String dayStatus() { - return "Hi, today is a sunny day!"; + return "Hi, today is a sunny day!"; } ... -} -</code></pre> +}</pre> +</div> +</div> +<div class="paragraph"> <p>There are some configurations, as part of @Timed, that you need to know:</p> -<p><strong>String name</strong><br/>Optional. Sets the name of the metric. If not explicitly given the name of the annotated object is used.</p> -<p><strong>boolean absolute</strong><br/>If true, uses the given name as the absolute name of the metric. If false, prepends the package name and class name before the given name. Default value is false.</p> -<p><strong>String displayName</strong><br/>Optional. A human readable display name for metadata.</p> -<p><strong>String description</strong><br/>Optional. A description of the metric.</p> -<p><strong>String[] tags</strong><br/>Optional. Array of Strings in the <key>=<value> format to supply special tags to a metric.</p> -<p><strong>String unit</strong><br/>Unit of the metric. Default for @Timed is nanoseconds.</p> -<h4>Metric data</h4> +</div> +<div class="paragraph"> +<p><strong>String name</strong> Optional. Sets the name of the metric. If not explicitly +given the name of the annotated object is used.</p> +</div> +<div class="paragraph"> +<p><strong>boolean absolute</strong> If true, uses the given name as the absolute name of +the metric. If false, prepends the package name and class name before +the given name. Default value is false.</p> +</div> +<div class="paragraph"> +<p><strong>String displayName</strong> Optional. A human readable display name for +metadata.</p> +</div> +<div class="paragraph"> +<p><strong>String description</strong> Optional. A description of the metric.</p> +</div> +<div class="paragraph"> +<p><strong>String[] tags</strong> Optional. Array of Strings in the = format to supply +special tags to a metric.</p> +</div> +<div class="paragraph"> +<p><strong>String unit</strong> Unit of the metric. Default for @Timed is nanoseconds.</p> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_metric_data">Metric data</h2> +<div class="sectionbody"> +<div class="paragraph"> <p>Check the timed metric doing a <em>GET</em> request:</p> -<h5>Prometheus format:</h5> -<pre><code>GET http://localhost:8080/mp-metrics-timed/metrics/application/weather_day_status -</code></pre> -<h5>Response:</h5> -<pre><code># TYPE application:weather_day_status_seconds summary timer +</div> +<div class="sect2"> +<h3 id="_prometheus_format">Prometheus format:</h3> +<div class="literalblock"> +<div class="content"> +<pre>GET http://localhost:8080/mp-metrics-timed/metrics/application/weather_day_status</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_response_2">Response:</h3> +<div class="literalblock"> +<div class="content"> +<pre># TYPE application:weather_day_status_seconds summary timer # TYPE application:weather_day_status_seconds_count timer application:weather_day_status_seconds_count 1.0 # TYPE application:weather_day_status_rate_per_second timer @@ -159,61 +231,94 @@ application:weather_day_status_mean_seco # TYPE application:weather_day_status_stddev_seconds timer application:weather_day_status_stddev_seconds 0.0 # TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.5"} 48352.0 +application:weather_day_status_seconds{quantile="0.5"} 48352.0 # TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.75"} 48352.0 +application:weather_day_status_seconds{quantile="0.75"} 48352.0 # TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.95"} 48352.0 +application:weather_day_status_seconds{quantile="0.95"} 48352.0 # TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.98"} 48352.0 +application:weather_day_status_seconds{quantile="0.98"} 48352.0 # TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.99"} 48352.0 -# TYPE application:weather_day_status_seconds timer -application:weather_day_status_seconds{quantile="0.999"} 48352.0 -</code></pre> -<h5>JSON Format:</h5> -<p>For json format add the header <em>Accept=application/json</em> to the request. </p> -<pre><code>{ - "weather_day_status": { - "count": 1, - "fifteenMinRate": 0, - "fiveMinRate": 0, - "max": 48352, - "mean": 48352, - "meanRate": 0, - "min": 48352, - "oneMinRate": 0, - "p50": 48352, - "p75": 48352, - "p95": 48352, - "p98": 48352, - "p99": 48352, - "p999": 48352, - "stddev": 0 +application:weather_day_status_seconds{quantile="0.99"} 48352.0 +# TYPE application:weather_day_status_seconds timer +application:weather_day_status_seconds{quantile="0.999"} 48352.0</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_json_format">JSON Format:</h3> +<div class="paragraph"> +<p>For json format add the header <em>Accept=application/json</em> to the request.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "weather_day_status": { + "count": 1, + "fifteenMinRate": 0, + "fiveMinRate": 0, + "max": 48352, + "mean": 48352, + "meanRate": 0, + "min": 48352, + "oneMinRate": 0, + "p50": 48352, + "p75": 48352, + "p95": 48352, + "p98": 48352, + "p99": 48352, + "p999": 48352, + "stddev": 0 } -} -</code></pre> -<h4>Metric metadata</h4> -<p>A metric will have metadata so you can know more about it, like displayName, description, tags e etc.</p> +}</pre> +</div> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_metric_metadata">Metric metadata</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>A metric will have metadata so you can know more about it, like +displayName, description, tags e etc.</p> +</div> +<div class="paragraph"> <p>Check the metric metadata doing a <em>OPTIONS</em> request:</p> -<h5>Request</h5> -<pre><code>OPTIONS http://localhost:8080/mp-metrics-timed/metrics/application/weather_day_status -</code></pre> -<h5>Response:</h5> -<pre><code>{ - "weather_day_status": { - "description": "This metric shows the weather status of the day.", - "displayName": "Weather Day Status", - "name": "weather_day_status", - "reusable": false, - "tags": "", - "type": "timer", - "typeRaw": "TIMER", - "unit": "nanoseconds" +</div> +<div class="sect2"> +<h3 id="_request">Request</h3> +<div class="literalblock"> +<div class="content"> +<pre>OPTIONS http://localhost:8080/mp-metrics-timed/metrics/application/weather_day_status</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_response_3">Response:</h3> +<div class="literalblock"> +<div class="content"> +<pre>{ + "weather_day_status": { + "description": "This metric shows the weather status of the day.", + "displayName": "Weather Day Status", + "name": "weather_day_status", + "reusable": false, + "tags": "", + "type": "timer", + "typeRaw": "TIMER", + "unit": "nanoseconds" } -} -</code></pre> -<p>You can also try it out using the WeatherServiceTest.java available in the project.</p> +}</pre> +</div> +</div> +<div class="paragraph"> +<p>You can also try it out using the WeatherServiceTest.java available in +the project.</p> +</div> +</div> +</div> +</div> </div> </div> Modified: tomee/site/trunk/content/tomee-8.0/examples/mp-opentracing-traced.html URL: http://svn.apache.org/viewvc/tomee/site/trunk/content/tomee-8.0/examples/mp-opentracing-traced.html?rev=1849998&r1=1849997&r2=1849998&view=diff ============================================================================== --- tomee/site/trunk/content/tomee-8.0/examples/mp-opentracing-traced.html (original) +++ tomee/site/trunk/content/tomee-8.0/examples/mp-opentracing-traced.html Sun Dec 30 19:02:51 2018 @@ -88,21 +88,14 @@ <div class="col-md-12"> <div class='page-header'> - <h1>null</h1> + <h1>MicroProfile OpenTracing @Traced</h1> </div> </div> </div> <div class="row"> <div class="col-md-12"> - <div class="paragraph"> -<p>index-group=Traced -type=page -status=in progress -<sub>~</sub><sub>~</sub></p> -</div> -<div class="sect1"> -<h2 id="_microprofile_opentracing_traced">Microprofile OpenTracing @Traced</h2> + <div id="preamble"> <div class="sectionbody"> <div class="paragraph"> <p>This is an example on how to use the @Traced annotation in TomEE.</p> @@ -119,6 +112,8 @@ This example is a work in progress. </tr> </table> </div> +</div> +</div> <div class="sect4"> <h5 id="_run_the_application">Run the application:</h5> <div class="literalblock"> @@ -275,8 +270,6 @@ Complete the URL for the above <code>cur </div> </div> </div> -</div> -</div> </div> </div> Modified: tomee/site/trunk/content/tomee-8.0/examples/mp-rest-client.html URL: http://svn.apache.org/viewvc/tomee/site/trunk/content/tomee-8.0/examples/mp-rest-client.html?rev=1849998&r1=1849997&r2=1849998&view=diff ============================================================================== --- tomee/site/trunk/content/tomee-8.0/examples/mp-rest-client.html (original) +++ tomee/site/trunk/content/tomee-8.0/examples/mp-rest-client.html Sun Dec 30 19:02:51 2018 @@ -88,75 +88,117 @@ <div class="col-md-12"> <div class='page-header'> - <h1>Microprofile Rest Client</h1> + <h1>MicroProfile Rest Client</h1> </div> </div> </div> <div class="row"> <div class="col-md-12"> - <h1>Microprofile Rest client</h1> -<p>This is a basic example on how to configure and use MicroProfile Rest Client in TomEE.</p> -<h2>Run the tests for different scenarios related with JWT validation</h2> -<pre><code>mvn clean test -</code></pre> -<h2>Requirementes and configuration</h2> + <div id="preamble"> +<div class="sectionbody"> +<div class="paragraph"> +<p>This is a basic example on how to configure and use MicroProfile Rest +Client in TomEE.</p> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_run_the_tests_for_different_scenarios_related_with_jwt_validation">Run the tests for different scenarios related with JWT validation</h3> +<div class="literalblock"> +<div class="content"> +<pre>mvn clean test</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_requirementes_and_configuration">Requirementes and configuration</h3> +<div class="paragraph"> <p>To use MicroProfile Rest Client you need 3 changes in your project:</p> -<p>1) Add the to the <code>pom.xml</code> the dependency:</p> -<pre><code> <dependency> - <groupId>org.eclipse.microprofile.rest.client</groupId> - <artifactId>microprofile-rest-client-api</artifactId> - <version>${microprofile.rest-client.version}</version> - <scope>provided</scope> - </dependency> -</code></pre> -<p>2) Provide configuration files: <code>microprofile-config.properties</code></p> -<pre><code> org.superbiz.rest.BookResourceClient/mp-rest/url=http://localhost:4444 -</code></pre> -<p>3) Provide an interface that you can build from the JAX-RS resource you want to consume: <code>BookResourceClient.java</code></p> -<pre><code> package org.superbiz.rest; - - import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - import javax.enterprise.context.Dependent; - import javax.ws.rs.*; - import javax.ws.rs.core.MediaType; - import java.util.List; - - @Dependent - @RegisterRestClient - @Path("/test/api/library") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public interface BookResourceClient { - - @GET - String status(); - - @POST - @Path("/books") - void addBook(Book newBook); - - @DELETE - @Path("/books/{id}") - void deleteBook(@PathParam("id") int id); - - @PUT - @Path("/books") - void updateBook(Book updatedBook); - - @GET - @Path("/books/{id}") - Book getBook(@PathParam("id") int id); - - @GET - @Path("/books") - List<Book> getListOfBooks(); - - } -</code></pre> -<h2>Use of MicroProfile Rest Client in TomEE</h2> -<p>The class <code>BookResourceTest.java</code> shows how easy is to use the type-safe approach provided by MicroProfile Rest Client to consume an existing JAX-RS resource. </p> -<pre><code>package org.superbiz.rest; +</div> +<div class="olist arabic"> +<ol class="arabic"> +<li> +<p>Add the to the <code>pom.xml</code> the dependency:</p> +<div class="literalblock"> +<div class="content"> +<pre> <dependency> + <groupId>org.eclipse.microprofile.rest.client</groupId> + <artifactId>microprofile-rest-client-api</artifactId> + <version>${microprofile.rest-client.version}</version> + <scope>provided</scope> + </dependency></pre> +</div> +</div> +</li> +<li> +<p>Provide configuration files: <code>microprofile-config.properties</code></p> +<div class="literalblock"> +<div class="content"> +<pre> org.superbiz.rest.BookResourceClient/mp-rest/url=http://localhost:4444</pre> +</div> +</div> +</li> +<li> +<p>Provide an interface that you can build from the JAX-RS resource you +want to consume: <code>BookResourceClient.java</code></p> +<div class="literalblock"> +<div class="content"> +<pre> package org.superbiz.rest; + + import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + import javax.enterprise.context.Dependent; + import javax.ws.rs.*; + import javax.ws.rs.core.MediaType; + import java.util.List; + + @Dependent + @RegisterRestClient + @Path("/test/api/library") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public interface BookResourceClient { + + @GET + String status(); + + @POST + @Path("/books") + void addBook(Book newBook); + + @DELETE + @Path("/books/{id}") + void deleteBook(@PathParam("id") int id); + + @PUT + @Path("/books") + void updateBook(Book updatedBook); + + @GET + @Path("/books/{id}") + Book getBook(@PathParam("id") int id); + + @GET + @Path("/books") + List<Book> getListOfBooks(); + + }</pre> +</div> +</div> +</li> +</ol> +</div> +</div> +<div class="sect2"> +<h3 id="_use_of_microprofile_rest_client_in_tomee">Use of MicroProfile Rest Client in TomEE</h3> +<div class="paragraph"> +<p>The class <code>BookResourceTest.java</code> shows how easy is to use the type-safe +approach provided by MicroProfile Rest Client to consume an existing +JAX-RS resource.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>package org.superbiz.rest; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.jboss.arquillian.container.test.api.Deployment; @@ -176,14 +218,14 @@ public class BookResourceTest { @Deployment() public static WebArchive createDeployment() { - final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war") + final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war") .addClass(BookResource.class) .addClass(Book.class) .addClass(BookBean.class) .addClass(BookResourceClient.class) .addClass(ApplicationConfig.class) - .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml") - .addAsResource("META-INF/microprofile-config.properties"); + .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml") + .addAsResource("META-INF/microprofile-config.properties"); return webArchive; } @@ -194,31 +236,39 @@ public class BookResourceTest { @Test() public void testServerStatus(){ - bookResourceClient.addBook(new Book(1,"TomEE Book")); + bookResourceClient.addBook(new Book(1,"TomEE Book")); } @Test public void testBookResource(){ - bookResourceClient.addBook(new Book(1, "TomEE and MicroProfile Adventures")); - bookResourceClient.addBook(new Book(2, "Top 10 Tomee Configuraiton Tips")); + bookResourceClient.addBook(new Book(1, "TomEE and MicroProfile Adventures")); + bookResourceClient.addBook(new Book(2, "Top 10 Tomee Configuraiton Tips")); assertTrue(bookResourceClient.getListOfBooks().size() == 2); - assertTrue(bookResourceClient.getBook(1).getName().equalsIgnoreCase("TomEE and MicroProfile Adventures")); + assertTrue(bookResourceClient.getBook(1).getName().equalsIgnoreCase("TomEE and MicroProfile Adventures")); bookResourceClient.deleteBook(1); assertTrue(bookResourceClient.getListOfBooks().size() == 1); - assertTrue(bookResourceClient.getBook(2).getName().equalsIgnoreCase("Top 10 Tomee Configuraiton Tips")); + assertTrue(bookResourceClient.getBook(2).getName().equalsIgnoreCase("Top 10 Tomee Configuraiton Tips")); - bookResourceClient.updateBook(new Book(2, "Top 3 Tomee Configuraiton Tips")); + bookResourceClient.updateBook(new Book(2, "Top 3 Tomee Configuraiton Tips")); assertTrue(bookResourceClient.getListOfBooks().size() == 1); - assertTrue(bookResourceClient.getBook(2).getName().equalsIgnoreCase("Top 3 Tomee Configuraiton Tips")); + assertTrue(bookResourceClient.getBook(2).getName().equalsIgnoreCase("Top 3 Tomee Configuraiton Tips")); } -} -</code></pre> -<h2>About the Test architecture</h2> -<p>The test cases from this project are built using Arquillian and TomEE Remote. The arquillian configuration can be found in<br/><code>src/test/resources/arquillian.xml</code></p> +}</pre> +</div> +</div> +</div> +<div class="sect2"> +<h3 id="_about_the_test_architecture">About the Test architecture</h3> +<div class="paragraph"> +<p>The test cases from this project are built using Arquillian and TomEE +Remote. The arquillian configuration can be found in +<code>src/test/resources/arquillian.xml</code></p> +</div> +</div> </div> </div> Modified: tomee/site/trunk/content/tomee-8.0/examples/mp-rest-jwt.html URL: http://svn.apache.org/viewvc/tomee/site/trunk/content/tomee-8.0/examples/mp-rest-jwt.html?rev=1849998&r1=1849997&r2=1849998&view=diff ============================================================================== --- tomee/site/trunk/content/tomee-8.0/examples/mp-rest-jwt.html (original) +++ tomee/site/trunk/content/tomee-8.0/examples/mp-rest-jwt.html Sun Dec 30 19:02:51 2018 @@ -88,21 +88,41 @@ <div class="col-md-12"> <div class='page-header'> - <h1>Microprofile Rest JWT</h1> + <h1>MicroProfile JWT</h1> </div> </div> </div> <div class="row"> <div class="col-md-12"> - <h1>MP REST JWT</h1> -<p>This is a basic example on how to configure and use MicroProfile JWT in TomEE.</p> -<h2>Run the tests for different scenarios related with JWT validation</h2> -<pre><code>mvn clean test -</code></pre> -<h2>Configuration in TomEE</h2> -<p>The class <code>MoviesMPJWTConfigurationProvider.java</code> provides to TomEE the figuration need it for JWT validation.</p> -<pre><code>package org.superbiz.moviefun.rest; + <div id="preamble"> +<div class="sectionbody"> +<div class="paragraph"> +<p>This is a basic example on how to configure and use MicroProfile JWT in +TomEE.</p> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_run_the_tests_for_different_scenarios_related_with_jwt_validation">Run the tests for different scenarios related with JWT validation</h2> +<div class="sectionbody"> +<div class="literalblock"> +<div class="content"> +<pre>mvn clean test</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_configuration_in_tomee">Configuration in TomEE</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The class <code>MoviesMPJWTConfigurationProvider.java</code> provides to TomEE the +figuration need it for JWT validation.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>package org.superbiz.moviefun.rest; import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo; @@ -124,19 +144,19 @@ public class MoviesMPJWTConfigurationPro JWTAuthContextInfo contextInfo = new JWTAuthContextInfo(); // todo use MP Config to load the configuration - contextInfo.setIssuedBy("https://server.example.com"); + contextInfo.setIssuedBy("https://server.example.com"); - final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" + - "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" + - "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" + - "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" + - "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" + - "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" + - "nQIDAQAB"; + final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" + + "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" + + "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" + + "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" + + "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" + + "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" + + "nQIDAQAB"; byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded); final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes); - final KeyFactory kf = KeyFactory.getInstance("RSA"); + final KeyFactory kf = KeyFactory.getInstance("RSA"); final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec); contextInfo.setSignerKey(pk); @@ -148,11 +168,23 @@ public class MoviesMPJWTConfigurationPro JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException { return getOptionalContextInfo().get(); } -} -</code></pre> -<h2>Use MicroProfile JWT in TomEE</h2> -<p>The JAX-RS resource <code>MoviesRest.java</code> contains several endpoint that are secured using the standard annotation <code>@RolesAllowed</code>. MicroProfile JWT takes care of performing the validation for incoming requests with <code>Authorization</code> header providing a signed <code>Access Token</code></p> -<pre><code> package org.superbiz.moviefun.rest; +}</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_use_microprofile_jwt_in_tomee">Use MicroProfile JWT in TomEE</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The JAX-RS resource <code>MoviesRest.java</code> contains several endpoint that are +secured using the standard annotation <code>@RolesAllowed</code>. MicroProfile JWT +takes care of performing the validation for incoming requests with +<code>Authorization</code> header providing a signed <code>Access Token</code></p> +</div> +<div class="literalblock"> +<div class="content"> +<pre> package org.superbiz.moviefun.rest; import org.superbiz.moviefun.Movie; import org.superbiz.moviefun.MoviesBean; @@ -163,7 +195,7 @@ public class MoviesMPJWTConfigurationPro import javax.ws.rs.core.MediaType; import java.util.List; - @Path("cinema") + @Path("cinema") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class MoviesRest { @@ -174,40 +206,40 @@ public class MoviesMPJWTConfigurationPro @GET @Produces(MediaType.TEXT_PLAIN) public String status() { - return "ok"; + return "ok"; } @GET - @Path("/movies") - @RolesAllowed({"crud", "read-only"}) + @Path("/movies") + @RolesAllowed({"crud", "read-only"}) public List<Movie> getListOfMovies() { return moviesBean.getMovies(); } @GET - @Path("/movies/{id}") - @RolesAllowed({"crud", "read-only"}) - public Movie getMovie(@PathParam("id") int id) { + @Path("/movies/{id}") + @RolesAllowed({"crud", "read-only"}) + public Movie getMovie(@PathParam("id") int id) { return moviesBean.getMovie(id); } @POST - @Path("/movies") - @RolesAllowed("crud") + @Path("/movies") + @RolesAllowed("crud") public void addMovie(Movie newMovie) { moviesBean.addMovie(newMovie); } @DELETE - @Path("/movies/{id}") - @RolesAllowed("crud") - public void deleteMovie(@PathParam("id") int id) { + @Path("/movies/{id}") + @RolesAllowed("crud") + public void deleteMovie(@PathParam("id") int id) { moviesBean.deleteMovie(id); } @PUT - @Path("/movies") - @RolesAllowed("crud") + @Path("/movies") + @RolesAllowed("crud") public void updateMovie(Movie updatedMovie) { moviesBean.updateMovie(updatedMovie); } @@ -215,50 +247,85 @@ public class MoviesMPJWTConfigurationPro } @Inject - @ConfigProperty(name = "java.runtime.version") - private String javaVersion; -</code></pre> -<h2>About the Test architecture</h2> -<p>The test cases from this project are builded using Arquillian. The arquillian configuration can be found in<br/><code>src/test/resources/arquillian.xml</code></p> -<p>The class <code>TokenUtils.java</code> is used during the test to act as an Authorization server who generates <code>Access Tokens</code> based on the configuration files <code>privateKey.pem</code>,<code>publicKey.pem</code>,<code>Token1.json</code>, and <code>Token2.json</code>.<br/><code>nimbus-jose-jwt</code> is the library used for JWT generation during the tests.</p> + @ConfigProperty(name = "java.runtime.version") + private String javaVersion;</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_about_the_test_architecture">About the Test architecture</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p>The test cases from this project are builded using Arquillian. The +arquillian configuration can be found in +<code>src/test/resources/arquillian.xml</code></p> +</div> +<div class="paragraph"> +<p>The class <code>TokenUtils.java</code> is used during the test to act as an +Authorization server who generates <code>Access Tokens</code> based on the +configuration files <code>privateKey.pem</code>,<code>publicKey.pem</code>,<code>Token1.json</code>, and +<code>Token2.json</code>.<br> +<code>nimbus-jose-jwt</code> is the library used for JWT generation during the +tests.</p> +</div> +<div class="paragraph"> <p><code>Token1.json</code></p> -<pre><code>{ - "iss": "https://server.example.com", - "jti": "a-123", - "sub": "24400320", - "upn": "[email protected]", - "preferred_username": "jdoe", - "aud": "s6BhdRkqt3", - "exp": 1311281970, - "iat": 1311280970, - "auth_time": 1311280969, - "groups": [ - "group1", - "group2", - "crud", - "read-only" +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "iss": "https://server.example.com", + "jti": "a-123", + "sub": "24400320", + "upn": "[email protected]", + "preferred_username": "jdoe", + "aud": "s6BhdRkqt3", + "exp": 1311281970, + "iat": 1311280970, + "auth_time": 1311280969, + "groups": [ + "group1", + "group2", + "crud", + "read-only" ] -} -</code></pre> +}</pre> +</div> +</div> +<div class="paragraph"> <p><code>Token2.json</code></p> -<pre><code>{ - "iss": "https://server.example.com", - "jti": "a-123", - "sub": "24400320", - "upn": "[email protected]", - "preferred_username": "alice", - "aud": "s6BhdRkqt3", - "exp": 1311281970, - "iat": 1311280970, - "auth_time": 1311280969, - "groups": [ - "read-only" +</div> +<div class="literalblock"> +<div class="content"> +<pre>{ + "iss": "https://server.example.com", + "jti": "a-123", + "sub": "24400320", + "upn": "[email protected]", + "preferred_username": "alice", + "aud": "s6BhdRkqt3", + "exp": 1311281970, + "iat": 1311280970, + "auth_time": 1311280969, + "groups": [ + "read-only" ] -} -</code></pre> -<h2>Test Scenarios</h2> -<p><code>MovieTest.java</code> contains 4 OAuth2 scenarios for different JWT combinations.</p> -<pre><code>package org.superbiz.moviefun; +}</pre> +</div> +</div> +</div> +</div> +<div class="sect1"> +<h2 id="_test_scenarios">Test Scenarios</h2> +<div class="sectionbody"> +<div class="paragraph"> +<p><code>MovieTest.java</code> contains 4 OAuth2 scenarios for different JWT +combinations.</p> +</div> +<div class="literalblock"> +<div class="content"> +<pre>package org.superbiz.moviefun; import org.apache.cxf.feature.LoggingFeature; import org.apache.cxf.jaxrs.client.WebClient; @@ -289,11 +356,11 @@ public class MoviesTest { @Deployment(testable = false) public static WebArchive createDeployment() { - final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war") + final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war") .addClasses(Movie.class, MoviesBean.class, MoviesTest.class) .addClasses(MoviesRest.class, ApplicationConfig.class) .addClass(MoviesMPJWTConfigurationProvider.class) - .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml"); + .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml"); System.out.println(webArchive.toString(true)); @@ -315,19 +382,19 @@ public class MoviesTest { //Testing rest endpoint deployment (GET without security header) - String responsePayload = webClient.reset().path("/rest/cinema/").get(String.class); - LOGGER.info("responsePayload = " + responsePayload); - assertTrue(responsePayload.equalsIgnoreCase("ok")); + String responsePayload = webClient.reset().path("/rest/cinema/").get(String.class); + LOGGER.info("responsePayload = " + responsePayload); + assertTrue(responsePayload.equalsIgnoreCase("ok")); //POST (Using token1.json with group of claims: [CRUD]) - Movie newMovie = new Movie(1, "David Dobkin", "Wedding Crashers"); + Movie newMovie = new Movie(1, "David Dobkin", "Wedding Crashers"); Response response = webClient.reset() - .path("/rest/cinema/movies") - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + token(1)) + .path("/rest/cinema/movies") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + token(1)) .post(newMovie); - LOGGER.info("responseCode = " + response.getStatus()); + LOGGER.info("responseCode = " + response.getStatus()); assertTrue(response.getStatus() == 204); @@ -335,31 +402,31 @@ public class MoviesTest { //This test should be updated to use token2.json once TOMEE- gets resolved. Collection<? extends Movie> movies = webClient .reset() - .path("/rest/cinema/movies") - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + token(1)) + .path("/rest/cinema/movies") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + token(1)) .getCollection(Movie.class); LOGGER.info(movies.toString()); assertTrue(movies.size() == 1); //Should return a 403 since POST require group of claims: [crud] but Token 2 has only [read-only]. - Movie secondNewMovie = new Movie(2, "Todd Phillips", "Starsky & Hutch"); + Movie secondNewMovie = new Movie(2, "Todd Phillips", "Starsky & Hutch"); Response responseWithError = webClient.reset() - .path("/rest/cinema/movies") - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + token(2)) + .path("/rest/cinema/movies") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + token(2)) .post(secondNewMovie); - LOGGER.info("responseCode = " + responseWithError.getStatus()); + LOGGER.info("responseCode = " + responseWithError.getStatus()); assertTrue(responseWithError.getStatus() == 403); //Should return a 401 since the header Authorization is not part of the POST request. Response responseWith401Error = webClient.reset() - .path("/rest/cinema/movies") - .header("Content-Type", "application/json") + .path("/rest/cinema/movies") + .header("Content-Type", "application/json") .post(new Movie()); - LOGGER.info("responseCode = " + responseWith401Error.getStatus()); + LOGGER.info("responseCode = " + responseWith401Error.getStatus()); assertTrue(responseWith401Error.getStatus() == 401); } @@ -368,14 +435,17 @@ public class MoviesTest { private String token(int token_type) throws Exception { HashMap<String, Long> timeClaims = new HashMap<>(); if (token_type == 1) { - return TokenUtils.generateTokenString("/Token1.json", null, timeClaims); + return TokenUtils.generateTokenString("/Token1.json", null, timeClaims); } else { - return TokenUtils.generateTokenString("/Token2.json", null, timeClaims); + return TokenUtils.generateTokenString("/Token2.json", null, timeClaims); } } -} -</code></pre> +}</pre> +</div> +</div> +</div> +</div> </div> </div>
