blob: 6ed984f032edddd1153743e0aba05a13fce512bc [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/security.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>@AccessTimeout the Meta-Annotation Way</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p>Any annotation that takes parameters can benefit from meta-annotations. Here we see how <code>@AccessTimeout</code> can be far more understandable and manageable through meta-annotations. We'll use the <a href="../access-timeout/README.html">access-timeout</a> example as our use-case.</p>
<p>The value of the parameters supplied to <code>@AccessTimeout</code> have a dramatic affect on how what that annotation actually does. Moreover, <code>@AccessTimeout</code> has one of those designs where <code>-1</code> and <code>0</code> have signifcantly different meanings. One means "wait forever", the other means "never wait". Only a lucky few can remember which is which on a daily basis. For the rest of us it is a constant source of bugs.</p>
<p>Meta-Annotations to the rescue!</p>
<h1>Creating the Meta-Annotations</h1>
<p>As a matter of best-practices, we will put our meta-annotations in a package called <code>api</code>, for this example that gives us <code>org.superbiz.accesstimeout.api</code>. The package <code>org.superbiz.api</code> would work just as well.</p>
<p>The basic idea is to have a package where "approved' annotations are used and to prohibit usage of the non-meta versions of the annotations. All the real configuration will then be centralized in the <code>api</code> package and changes to timeout values will be localized to that package and automatically be reflected throuhout the application.</p>
<p>An interesting side-effect of this approach is that if the <code>api</code> package where the meta-annotation definitions exist is kept in a separate jar as well, then one can effectively change the configuration of an entire application by simply replacing the <code>api</code> jar.</p>
<h2>@Metatype <small>The "root" Meta-Annotation</small></h2>
<p>As with all meta-annotation usage, you first need to create your own "root" meta-annotation. This is as easy as creating an annotation named <code>Metatype</code> that is annotated with itself and has <code>ElementType.ANNOTATION_TYPE</code> as its target.</p>
<pre><code>package org.superbiz.accesstimeout.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Metatype {
}
</code></pre>
<h2>@AwaitNever</h2>
<p>When the <code>@AccessTimeout</code> annotation has the value of <code>0</code> that has the implication that one should never wait to access the bean. If the bean is busy, the caller will immediately receive an <code>ConcurrentAccessException</code>. This is hard to remember and definitely not self-documenting for those that never knew the details.</p>
<p>To create a meta-annotation version of <code>@AccessTimeout(0)</code> we simply need to think of a good annotation name, create that annotation, and annotate it with both <code>@AccessTimeout</code> and <code>@Metatype</code></p>
<pre><code>package org.superbiz.accesstimeout.api;
import javax.ejb.AccessTimeout;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@AccessTimeout(0)
public @interface AwaitNever {
}
</code></pre>
<h2>@AwaitForever</h2>
<p>Just as <code>0</code> carries the special meaning of "never wait", a value of <code>-1</code> means "wait forever."</p>
<p>As long as we're being picky, which we can be with meta-annotations, Technically "wait forever" is not the best description. The actual methods of the <code>javax.util.concurrent</code> APIs use "await" rather than "wait". One (wait) perphaps implies a command to wait, which this is not, and the other (await) perhaps better implies that waiting is possible but not a certainty. So we will use "await" in our annotation names.</p>
<p>We make our own <code>@AwaitForever</code> and annotate it with <code>@AccessTimeout(0)</code> and <code>@Metatype</code></p>
<pre><code>package org.superbiz.accesstimeout.api;
import javax.ejb.AccessTimeout;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@AccessTimeout(-1)
public @interface AwaitForever {
}
</code></pre>
<h2>@AwaitBriefly</h2>
<p>Non <code>-1</code> and <code>0</code> values to <code>@AccessTimeout</code> actually involve the full breadth of the annotation. Here is where you get to specify the maximum number minutes, seconds, milliseconds, etc. where one might await access to the bean instance.</p>
<pre><code>@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@AccessTimeout(value = 5, unit = TimeUnit.SECONDS)
public @interface AwaitBriefly {
}
</code></pre>
<h1>Configuration vs Operation</h1>
<p>Once you create a few meta-annotations and the fun becomes common-place, questoins start to raise in your mind on how to best get the benefits of meta-annotations.</p>
<p>You have to really start thinking about how you want to approach your usage of meta-annotation and really put your designer hat on. The fundamental question is<br/><strong>configuration vs operation</strong> and the answer is subjective; how much flexibility do you want to design into your applications and where?</p>
<h2>Configuration names <small>describing the configuration</small></h2>
<p>The simplest approach is to name your meta-annotations after the <strong>configuration</strong> they encapsulate. We've been following that format so far with <code>@AwaitNever</code> and <code>@AwaitForever</code> to clearly reflect the contents of each meta-annotation (<code>@AccessTimeout(-1)</code> and <code>@AccessTimeout(0)</code> respectively).</p>
<p>The <strong>cons</strong> of this approach is that should you want to change the configuration of the application by only changing the meta-annotations -- this is one of the potential benefits of meta-annotations. Certainly, the <code>@AwaitNever</code> meta-annotation can have no other value than <code>0</code> if it is to live up to its name.</p>
<h2>Operation names <small>describing the code</small></h2>
<p>The alternate approach is to name your meta-annotations after the <strong>operations</strong> they apply to. In short, to describe the code itself and not the configuration. So, names like<br/><code>@OrderCheckTimeout</code> or <code>@TwitterUpdateTimeout</code>. These names are configuration-change-proof. They would not change if the configuration changes and in fact they can facilitate<br/>finder-grained control over the configuration of an application.</p>
<p>The <strong>cons</strong> are of course it is requires far more deliberation and consideration, not to mention more annotations. Your skills as an architect, designer and ability to think as a administrator will be challenged. You must be good at wearing your dev-opts hat.</p>
<h2>Pragmatism <small>best of both worlds</small></h2>
<p>Fortunately, meta-annotations are recursive. You can do a little of both.</p>
<pre><code>@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@AwaitBriefly
public @interface TwitterUpdateTimeout {
}
</code></pre>
<p>Of course you still need to be very deliberate on how your annotations are used. When using a "configuration" named meta-annotation in code it can help to say to yourself,<br/>"I do not want to reconfigure this later." If that doesn't feel quite right, put the extra effort into creating an operation named annotation and use in that code.</p>
<h1>Applying the Meta-Annotations</h1>
<p>Putting it all together, here's how we might apply our meta-annotations to the <a href="../access-timeout/README.html">access-timeout</a> example.</p>
<h2>Before</h2>
<pre><code>package org.superbiz.accesstimeout;
import javax.ejb.AccessTimeout;
import javax.ejb.Asynchronous;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static javax.ejb.LockType.WRITE;
/**
* @version $Revision$ $Date$
*/
@Singleton
@Lock(WRITE)
public class BusyBee {
@Asynchronous
public Future stayBusy(CountDownLatch ready) {
ready.countDown();
try {
new CountDownLatch(1).await();
} catch (InterruptedException e) {
Thread.interrupted();
}
return null;
}
@AccessTimeout(0)
public void doItNow() {
// do something
}
@AccessTimeout(value = 5, unit = TimeUnit.SECONDS)
public void doItSoon() {
// do something
}
@AccessTimeout(-1)
public void justDoIt() {
// do something
}
}
</code></pre>
<h2>After</h2>
<pre><code>package org.superbiz.accesstimeout;
import org.superbiz.accesstimeout.api.AwaitBriefly;
import org.superbiz.accesstimeout.api.AwaitForever;
import org.superbiz.accesstimeout.api.AwaitNever;
import javax.ejb.Asynchronous;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import static javax.ejb.LockType.WRITE;
/**
* @version $Revision$ $Date$
*/
@Singleton
@Lock(WRITE)
public class BusyBee {
@Asynchronous
public Future stayBusy(CountDownLatch ready) {
ready.countDown();
try {
new CountDownLatch(1).await();
} catch (InterruptedException e) {
Thread.interrupted();
}
return null;
}
@AwaitNever
public void doItNow() {
// do something
}
@AwaitBriefly
public void doItSoon() {
// do something
}
@AwaitForever
public void justDoIt() {
// do something
}
}
</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/" 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>