blob: cef6dde973d35ce8bfc83d16504b8842c34d261c [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>Anotação @AccessTimeout</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Antes de darmos uma olhada no <code>@AccessTimeout</code>, pode ajudar entender quando uma chamada precisa "esperar".</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_esperando">Esperando&#8230;&#8203;</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_stateful_bean">Stateful Bean</h3>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Por padrão, é permitido que clientes façam chamadas concorrentes para um stateful session object e o container é requerido para serializar cada requisição concorrente. O container nunca permite acesso multi-thread a instancia de um componente stateful. Por essa razão, métodos de leitura/escrita bloqueiam metadados assim como componentes que gerenciam a própria concorrência (bean-managed concurrency) não são aplicáveis a um stateful session bean e não devem ser usados.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Isso significa que quando um método <code>foo()</code> de uma instancia stateful esta sendo executado e uma chega uma segunda requisição para esse ou outro método, o container EJB serializa a segunda requisição. Isso não permite com que o método seja executado concorrentemente mas espere ate o primeiro método ser processado.</p>
</div>
<div class="paragraph">
<p>O cliente também tem de esperar quando o bean <code>@Stateful</code> esta em uma transação e o cliente o invocar de fora dessa transação.</p>
</div>
</div>
<div class="sect2">
<h3 id="_stateless_bean">Stateless Bean</h3>
<div class="paragraph">
<p>Se existir 20 instancias de um bean no pool e todas elas estiverem ocupadas, quando uma nova requisição chegar, o processo <strong>tem de esperar</strong> ate algum bean estar disponível no pool. (Nota: a semântica de pool, se houver, não é coberta pela especificação. O server vendor pode ou não envolver uma condição de espera)</p>
</div>
</div>
<div class="sect2">
<h3 id="_singleton_bean">Singleton Bean</h3>
<div class="paragraph">
<p>O container força um acesso single-thread por padrão para um componente singleton. Isso é parecido com o que a anotação <code>@Lock(WRITE)</code> faz. Quando um método anotado com <code>@Lock(WRITE)</code> é executado, todos os outros métodos <code>@Lock(WRITE)</code> e <code>@Lock(READ)</code> que são chamados tem de esperar até que ele termine sua execução.</p>
</div>
</div>
<div class="sect2">
<h3 id="_resumindo">Resumindo</h3>
<div class="ulist">
<ul>
<li>
<p><code>@Singleton</code> - Um método <code>@Lock(WRITE)</code> esta sendo invocado e o gerenciamento de concorrência pelo container esta sendo usado. Todos os métodos sao <code>@Lock(WRITE)</code> por padrão.</p>
</li>
<li>
<p><code>@Stateful</code> - Qualquer método de uma instancia pode estar sendo utilizado e uma segunda chamada pode acontecer. Ou o bean <code>@Stateful</code> esta em uma transação e o cliente o chama de fora dessa transação.</p>
</li>
<li>
<p><code>@Stateless</code> - Sem instancias disponíveis no pool. Como observado, a semântica de pool (se houver) não é coberta pela especificação. Caso exista uma semântica no server vendor que envolva uma condição de espera, a anotação <code>@AccessTimeout</code> deveria ser aplicada.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="__code_accesstimeout_code"><code>@AccessTimeout</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>A anotação <code>@AccessTimeout</code> é simplesmente uma conveniência em torno da tupla <code>long</code> e <code>TimeUnit</code> comumente usadas na <code>java.util.concurrent</code> API.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">import java.util.concurrent.TimeUnit;
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface AccessTimeout {
long value();
TimeUnit unit() default TimeUnit.MILLISECONDS;
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_uso">Uso</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Um método ou uma classe pode ser anotada com <code>@AccessTimeout</code> para especificar o temo máximo que uma chamada deve esperar para acessar o bean quando acontecer uma condição de espera.</p>
</div>
<div class="paragraph">
<p>A semântica para o <code>value</code> é a seguinte:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>value</code> &gt; 0 indica um tempo de espera que é especificado pelo elemento <code>unit</code>.</p>
</li>
<li>
<p><code>value</code> de 0 significa que acesso concorrente não é permitido.</p>
</li>
<li>
<p><code>value</code> de -1 indica que a chamada do cliente vai ficar bloqueada por tempo indeterminado ate que possa proceder.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Simples!</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Quando acontecer um timeout, qual exceção o cliente recebe?
Citando a especificação: "if a client-invoked business method is in progress on an instance when another client-invoked call, from the same or different client, arrives at the same instance of a stateful session bean, if the second client is a client of the bean&#8217;s business interface or no-interface view, the concurrent invocation must result in the second client receiving a javax.ejb.ConcurrentAccessException[15]. If the EJB 2.1 client view is used, the container must throw a java.rmi.RemoteException if the second client is a remote client, or a javax.ejb.EJBException if the second client is a local client"
Ou seja pode receber <code>javax.ejb.ConcurrentAccessException</code>. Ou no caso de EJB 2.1 estar sendo utilizado pode receber <code>java.rmi.RemoteException</code> se for um cliente externo ou <code>javax.ejb.EJBException</code> se for local.
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="_sem_padrão">Sem padrão</h3>
<div class="paragraph">
<p>Note que o atributo <code>value</code> não tem um valor padrão. Isso foi intencional, tendo a intenção de informar que se o <code>@AccessTimeout</code> não for explicitamente usado, o comportamento sera o do server vendor.</p>
</div>
<div class="paragraph">
<p>Alguns servidores vão esperar por um tempo pre determinado e lançar a exceção <code>javax.ejb.ConcurrentAccessException</code>, outros podem lançar de imediato.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exemplo">Exemplo</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Aqui nos temos um simples <code>@Singleton</code> bean que possui tres métodos síncronos e um método anotado com <code>@Asynchronous</code>. O componente esta anotado com <code>@Lock(WRITE)</code> então apenas uma thread pode acessar o <code>@Singleton</code> por vez. Este é o comportamento padrão de um componente <code>@Singleton</code>, então usar a anotação <code>@Lock(WRITE)</code> não é necessário mas é importante para deixar claro que o componente tem um comportamento single-thread.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">@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() {
// faz alguma coisa
}
@AccessTimeout(value = 5, unit = TimeUnit.SECONDS)
public void doItSoon() {
// faz alguma coisa
}
@AccessTimeout(-1)
public void justDoIt() {
// faz alguma coisa
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>O método <code>@Asynchronous</code> não tem uma relação direta com o <code>@AccessTimeout</code>, mas serve como uma forma simple de travar ("lockar") o bean para realizarmos o teste. Ele nos permite testar o comportamento concorrente do componente.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class BusyBeeTest extends TestCase {
public void test() throws Exception {
final Context context = EJBContainer.createEJBContainer().getContext();
final CountDownLatch ready = new CountDownLatch(1);
final BusyBee busyBee = (BusyBee) context.lookup("java:global/access-timeout/BusyBee");
// Esse método assíncrono nunca termina.
busyBee.stayBusy(ready);
// Você ainda esta trabalhando abelhinha?
ready.await();
// Beleza, a abelha esta ocupada.
{ // Timeout imediato
final long start = System.nanoTime();
try {
busyBee.doItNow();
fail("A abelha continua ocupada");
} catch (Exception e) {
// A abelha continua muito ocupada como esperado.
}
assertEquals(0, seconds(start));
}
{ // Timeout em 5 segundos
final long start = System.nanoTime();
try {
busyBee.doItSoon();
fail("A abelha deve estar ocupada");
} catch (Exception e) {
// A abelha continua ocupada como esperado.
}
assertEquals(5, seconds(start));
}
// Esse método vai te fazer esperar para sempre, apenas teste se estiver com bastante tempo :D
// busyBee.justDoIt();
}
private long seconds(long start) {
return TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
}
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_executando">Executando</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">mvn clean test</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="_saida">Saida</h3>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.superbiz.accesstimeout.BusyBeeTest
Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06
http://tomee.apache.org/
INFO - openejb.home = /Users/dblevins/examples/access-timeout
INFO - openejb.base = /Users/dblevins/examples/access-timeout
INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Found EjbModule in classpath: /Users/dblevins/examples/access-timeout/target/classes
INFO - Beginning load: /Users/dblevins/examples/access-timeout/target/classes
INFO - Configuring enterprise application: /Users/dblevins/examples/access-timeout
INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
INFO - Auto-creating a container for bean BusyBee: Container(type=SINGLETON, id=Default Singleton Container)
INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
INFO - Auto-creating a container for bean org.superbiz.accesstimeout.BusyBeeTest: Container(type=MANAGED, id=Default Managed Container)
INFO - Enterprise application "/Users/dblevins/examples/access-timeout" loaded.
INFO - Assembling app: /Users/dblevins/examples/access-timeout
INFO - Jndi(name="java:global/access-timeout/BusyBee!org.superbiz.accesstimeout.BusyBee")
INFO - Jndi(name="java:global/access-timeout/BusyBee")
INFO - Jndi(name="java:global/EjbModule748454644/org.superbiz.accesstimeout.BusyBeeTest!org.superbiz.accesstimeout.BusyBeeTest")
INFO - Jndi(name="java:global/EjbModule748454644/org.superbiz.accesstimeout.BusyBeeTest")
INFO - Created Ejb(deployment-id=org.superbiz.accesstimeout.BusyBeeTest, ejb-name=org.superbiz.accesstimeout.BusyBeeTest, container=Default Managed Container)
INFO - Created Ejb(deployment-id=BusyBee, ejb-name=BusyBee, container=Default Singleton Container)
INFO - Started Ejb(deployment-id=org.superbiz.accesstimeout.BusyBeeTest, ejb-name=org.superbiz.accesstimeout.BusyBeeTest, container=Default Managed Container)
INFO - Started Ejb(deployment-id=BusyBee, ejb-name=BusyBee, container=Default Singleton Container)
INFO - Deployed Application(path=/Users/dblevins/examples/access-timeout)
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.071 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0</code></pre>
</div>
</div>
</div>
</div>
</div>
</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>