blob: 120efc1ec0c0a7d6a08a82c01f77aae6bb7a46c2 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Apache TomEE</title>
<meta name="description"
content="Apache TomEE is a lightweight, yet powerful, JavaEE Application server with feature rich tooling." />
<meta name="keywords" content="tomee,asf,apache,javaee,jee,shade,embedded,test,junit,applicationcomposer,maven,arquillian" />
<meta name="author" content="Luka Cvetinovic for Codrops" />
<link rel="icon" href="../../favicon.ico">
<link rel="icon" type="image/png" href="../../favicon.png">
<meta name="msapplication-TileColor" content="#80287a">
<meta name="theme-color" content="#80287a">
<link rel="stylesheet" type="text/css" href="../../css/normalize.css">
<link rel="stylesheet" type="text/css" href="../../css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="../../css/owl.css">
<link rel="stylesheet" type="text/css" href="../../css/animate.css">
<link rel="stylesheet" type="text/css" href="../../fonts/font-awesome-4.1.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="../../fonts/eleganticons/et-icons.css">
<link rel="stylesheet" type="text/css" href="../../css/jqtree.css">
<link rel="stylesheet" type="text/css" href="../../css/idea.css">
<link rel="stylesheet" type="text/css" href="../../css/cardio.css">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-2717626-1']);
_gaq.push(['_setDomainName', 'apache.org']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="preloader">
<img src="../../img/loader.gif" alt="Preloader image">
</div>
<nav class="navbar">
<div class="container">
<div class="row"> <div class="col-md-12">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">
<span>
<img src="../../img/logo-active.png">
</span>
Apache TomEE
</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right main-nav">
<li><a href="../../docs.html">Documentation</a></li>
<li><a href="../../community/index.html">Community</a></li>
<li><a href="../../security/index.html">Security</a></li>
<li><a href="../../download-ng.html">Downloads</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div></div>
</div>
<!-- /.container-fluid -->
</nav>
<div id="main-block" class="container main-block">
<div class="row title">
<div class="col-md-12">
<div class='page-header'>
<h1>null</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h1>Microprofile Fault Tolerance - Retry policy</h1>
<p>This is an example of how to use Microprofile @Retry in TomEE.</p>
<h4>Retry Feature</h4>
<p>Microprofile Fault Tolerance has a feature called Retry that can be used to recover an operation from failure, invoking the same operation again until it reaches its stopping criteria.</p>
<p>The Retry policy allows to configure :</p>
<ul>
<li><strong>maxRetries</strong>: the maximum retries</li>
<li><strong>delay</strong>: delays between each retry</li>
<li><strong>delayUnit</strong>: the delay unit</li>
<li><strong>maxDuration</strong>: maximum duration to perform the retry for.</li>
<li><strong>durationUnit</strong>: duration unit</li>
<li><strong>jitter:</strong> the random vary of retry delays</li>
<li><strong>jitterDelayUnit:</strong> the jitter unit</li>
<li><strong>retryOn:</strong> specify the failures to retry on</li>
<li><strong>abortOn:</strong> specify the failures to abort on</li>
</ul>
<p>To use this feature you can annotate a class and/or a method with the @Retry annotation. Check the <a href="http://download.eclipse.org/microprofile/microprofile-fault-tolerance-1.1/microprofile-fault-tolerance-spec.html">specification</a> for more details.</p>
<h3>Examples</h3>
<h5>Run the application</h5>
<pre><code>mvn clean install tomee:run
</code></pre>
<h5>Example 1</h5>
<p>The method statusOfDay will fail three times, each time, throwing a <code>WeatherGatewayTimeoutException</code> and as the<br/>@Retry annotation is configured to <code>retryOn</code> in case of failure, the FailSafe library will take the <code>maxRetry</code> value and<br/>retry the same operation until it reaches the number maximum of attempts, which is 3 (default value). </p>
<pre><code class="java">@RequestScoped
public class WeatherGateway{
...
@Retry(maxRetry=3, retryOn = WeatherGatewayTimeoutException.class)
public String statusOfDay(){
if(counterStatusOfDay.addAndGet(1) &lt;= DEFAULT_MAX_RETRY){
LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE, DEFAULT_MAX_RETRY, counterStatusOfDay.get()));
throw new WeatherGatewayTimeoutException();
}
return &quot;Today is a sunny day!&quot;;
}
...
}
</code></pre>
<p>Day status call</p>
<pre><code>GET http://localhost:8080/mp-faulttolerance-retry/weather/day/status
</code></pre>
<p>Server log</p>
<pre><code>WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (1) WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (2) WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (3)
</code></pre>
<p>Response</p>
<pre><code>Today is a sunny day!
</code></pre>
<h5>Example 2</h5>
<p>The method weekStatus will fail two times, each time, throwing a <code>WeatherGatewayTimeoutException</code> because <code>retryOn</code> is configured and instead of returning a response to the caller, the logic states that at the third attempt, a <code>WeatherGatewayBusyServiceException</code> will be thrown.<br/> As the <code>@Retry</code> annotation is configured to <code>abortOn</code> in case of <code>WeatherGatewayTimeoutException</code> happens, the remaining attempt won't be<br/> executed and the caller must handle the exception.</p>
<pre><code class="java">@Retry(maxRetries = 3, retryOn = WeatherGatewayTimeoutException.class, abortOn = WeatherGatewayBusyServiceException.class)
public String statusOfWeek(){
if(counterStatusOfWeek.addAndGet(1) &lt;= DEFAULT_MAX_RETRY){
LOGGER.warning(String.format(FORECAST_TIMEOUT_MESSAGE_ATTEMPTS, DEFAULT_MAX_RETRY, counterStatusOfWeek.get()));
throw new WeatherGatewayTimeoutException();
}
LOGGER.log(Level.SEVERE, String.format(FORECAST_BUSY_MESSAGE, counterStatusOfWeek.get()));
throw new WeatherGatewayBusyServiceException();
}
</code></pre>
<p>Week status call</p>
<pre><code>GET http://localhost:8080/mp-faulttolerance-retry/weather/week/status
</code></pre>
<p>Server log</p>
<pre><code>WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (1) WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (2) WARNING - Timeout when accessing AccuWeather Forecast Service. Max of Attempts: (3), Attempts: (3) SEVERE - Error AccuWeather Forecast Service is busy. Number of Attempts: (4)
</code></pre>
<p>Response</p>
<pre><code>WeatherGateway Service is Busy. Retry later
</code></pre>
<h5>Example 3</h5>
<p>The <code>@Retry</code> annotation allows to configure a delay for each new attempt be executed giving a chance to service requested to recover itself and answerer the request properly. For each new retry follow the delay configure, is needed to set <code>jitter</code> to zero (0). Otherwise the delay of each new attempt will be randomized.</p>
<p>Analysing the logged messages, is possible to see that all attempts took the pretty much the same time to execute.</p>
<pre><code class="java ">@Retry(retryOn = WeatherGatewayTimeoutException.class, maxRetries = 5, delay = 500, jitter = 0)
public String statusOfWeekend() {
if (counterStatusOfWeekend.addAndGet(1) &lt;= 5) {
logTimeoutMessage(statusOfWeekendInstant);
statusOfWeekendInstant = Instant.now();
throw new WeatherGatewayTimeoutException();
}
return &quot;The Forecast for the Weekend is Scattered Showers.&quot;;
}
</code></pre>
<p>Weekend status call</p>
<pre><code>GET http://localhost:8080/mp-faulttolerance-retry/weather/weekend/status
</code></pre>
<p>Server log</p>
<pre><code>WARNING - Timeout when accessing AccuWeather Forecast Service. WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (501) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (500) millis
</code></pre>
<h5>Example 4</h5>
<p>Basically with the same behaviour of the <code>Example 3</code>, this example sets the <code>delay</code> and <code>jitter</code> with 500 millis to randomly create a new delay for each new attempt after the first failure. <a href="https://github.com/jhalterman/failsafe/blob/master/src/main/java/net/jodah/failsafe/AbstractExecution.java">AbstractExecution#randomDelay(delay,jitter,random)</a> can give a hit of how the new delay is calculated.</p>
<p>Analysing the logged messages, is possible to see how long each attempt had to wait until its execution.</p>
<pre><code class="java ">@Retry(retryOn = WeatherGatewayTimeoutException.class, delay = 500, jitter = 500)
public String statusOfMonth() {
if (counterStatusOfWeekend.addAndGet(1) &lt;= DEFAULT_MAX_RETRY) {
logTimeoutMessage(statusOfMonthInstant);
statusOfMonthInstant = Instant.now();
throw new WeatherGatewayTimeoutException();
}
return &quot;The Forecast for the Weekend is Scattered Showers.&quot;;
}
</code></pre>
<p>Month status call</p>
<pre><code>GET http://localhost:8080/mp-faulttolerance-retry/weather/month/status
</code></pre>
<p>Server log</p>
<pre><code>WARNING - Timeout when accessing AccuWeather Forecast Service. WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (417) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (90) millis
</code></pre>
<h5>Example 5</h5>
<p>If a condition for an operation be re-executed is not set as in the previous examples using the parameter <code>retryOn</code>, the operation is executed again for <em>any</em> exception that is thrown.</p>
<pre><code class="java ">@Retry(maxDuration = 1000)
public String statusOfYear(){
if (counterStatusOfWeekend.addAndGet(1) &lt;= 5) {
logTimeoutMessage(statusOfYearInstant);
statusOfYearInstant = Instant.now();
throw new RuntimeException();
}
return &quot;WeatherGateway Service Error&quot;;
}
</code></pre>
<p>Year status call</p>
<pre><code>GET http://localhost:8080/mp-faulttolerance-retry/weather/year/statusk
</code></pre>
<p>Server log</p>
<pre><code>WARNING - Timeout when accessing AccuWeather Forecast Service. WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (666) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (266) millis WARNING - Timeout when accessing AccuWeather Forecast Service. Delay before this attempt: (66) millis
</code></pre>
<h5>Run the tests</h5>
<p>You can also try it out using the <a href="src/test/java/org/superbiz/rest/WeatherServiceTest.java">WeatherServiceTest.java</a> available in the project.</p>
<pre><code>mvn clean test
</code></pre>
<pre><code>[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
</code></pre>
</div>
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-sm-6 text-center-mobile">
<h3 class="white">Be simple. Be certified. Be Tomcat.</h3>
<h5 class="light regular light-white">"A good application in a good server"</h5>
<ul class="social-footer">
<li><a href="https://www.facebook.com/ApacheTomEE/"><i class="fa fa-facebook"></i></a></li>
<li><a href="https://twitter.com/apachetomee"><i class="fa fa-twitter"></i></a></li>
<li><a href="https://plus.google.com/communities/105208241852045684449"><i class="fa fa-google-plus"></i></a></li>
</ul>
</div>
<div class="col-sm-6 text-center-mobile">
<div class="row opening-hours">
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../latest/docs/documentation.html" class="white">Documentation</a></h5>
<ul class="list-unstyled">
<li><a href="../../latest/docs/admin/configuration/index.html" class="regular light-white">How to configure</a></li>
<li><a href="../../latest/docs/admin/file-layout.html" class="regular light-white">Dir. Structure</a></li>
<li><a href="../../latest/docs/developer/testing/index.html" class="regular light-white">Testing</a></li>
<li><a href="../../latest/docs/admin/cluster/index.html" class="regular light-white">Clustering</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../latest/examples/" class="white">Examples</a></h5>
<ul class="list-unstyled">
<li><a href="../../latest/examples/simple-cdi-interceptor.html" class="regular light-white">CDI Interceptor</a></li>
<li><a href="../../latest/examples/rest-cdi.html" class="regular light-white">REST with CDI</a></li>
<li><a href="../../latest/examples/ejb-examples.html" class="regular light-white">EJB</a></li>
<li><a href="../../latest/examples/jsf-managedBean-and-ejb.html" class="regular light-white">JSF</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../community/index.html" class="white">Community</a></h5>
<ul class="list-unstyled">
<li><a href="../../community/contributors.html" class="regular light-white">Contributors</a></li>
<li><a href="../../community/social.html" class="regular light-white">Social</a></li>
<li><a href="../../community/sources.html" class="regular light-white">Sources</a></li>
</ul>
</div>
<div class="col-sm-3 text-center-mobile">
<h5><a href="../../security/index.html" class="white">Security</a></h5>
<ul class="list-unstyled">
<li><a href="http://apache.org/security" target="_blank" class="regular light-white">Apache Security</a></li>
<li><a href="http://apache.org/security/projects.html" target="_blank" class="regular light-white">Security Projects</a></li>
<li><a href="http://cve.mitre.org" target="_blank" class="regular light-white">CVE</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="row bottom-footer text-center-mobile">
<div class="col-sm-12 light-white">
<p>Copyright &copy; 1999-2016 The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache TomEE, TomEE, Apache, the Apache feather logo, and the Apache TomEE project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.</p>
</div>
</div>
</div>
</footer>
<!-- Holder for mobile navigation -->
<div class="mobile-nav">
<ul>
<li><a hef="../../latest/docs/admin/index.html">Administrators</a>
<li><a hef="../../latest/docs/developer/index.html">Developers</a>
<li><a hef="../../latest/docs/advanced/index.html">Advanced</a>
<li><a hef="../../community/index.html">Community</a>
</ul>
<a href="#" class="close-link"><i class="arrow_up"></i></a>
</div>
<!-- Scripts -->
<script src="../../js/jquery-1.11.1.min.js"></script>
<script src="../../js/owl.carousel.min.js"></script>
<script src="../../js/bootstrap.min.js"></script>
<script src="../../js/wow.min.js"></script>
<script src="../../js/typewriter.js"></script>
<script src="../../js/jquery.onepagenav.js"></script>
<script src="../../js/tree.jquery.js"></script>
<script src="../../js/highlight.pack.js"></script>
<script src="../../js/main.js"></script>
</body>
</html>