You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2019/07/10 09:38:16 UTC

[tomee] branch master updated: TOMEE-2560-portuguese async-methods example.

This is an automated email from the ASF dual-hosted git repository.

jlmonteiro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/master by this push:
     new 894c044  TOMEE-2560-portuguese async-methods example.
     new 2baf117  Merge pull request #503 from Daniel-Dos/TOMEE-2560
894c044 is described below

commit 894c044f23d4568167176a5252180917aafa3180
Author: Daniel Dias <da...@gmail.com>
AuthorDate: Sat Jul 6 01:53:59 2019 -0300

    TOMEE-2560-portuguese async-methods example.
---
 examples/async-methods/README_pt.adoc | 213 ++++++++++++++++++++++++++++++++++
 1 file changed, 213 insertions(+)

diff --git a/examples/async-methods/README_pt.adoc b/examples/async-methods/README_pt.adoc
new file mode 100644
index 0000000..81e0ae0
--- /dev/null
+++ b/examples/async-methods/README_pt.adoc
@@ -0,0 +1,213 @@
+:index-group: EJB
+:jbake-type: page
+:jbake-status: status=published
+= Métodos Assíncronos
+
+A anotação @Asynchronous foi introduzida no EJB 3.1 como um  simples meio
+de criar processamento assícrono.
+
+Toda vez que um método anotado com `@Asynchronous` é invocado por qualquer um que
+vai imediatamente retornar independentemente de quanto tempo o método realmente leva.
+ 
+Cada invocação retorna um objeto http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html[Future]
+que essencialmente inicia  _vazio_ e terá mais tarde o seu valor preenchido pelo contêiner quando o método relacionado é chamado concluir. 
+
+Retornar um objeto `Future` não é necessário e os métodos `@ Asynchronous` podem retornar `void`.
+
+== Exemplo
+
+Aqui, no `JobProcessorTest`,
+
+`final Future<String> red = processor.addJob("red");` prossegue para a
+próxima declaração,
+
+`final Future<String> orange = processor.addJob("orange");`
+
+sem aguardar pelo método addJob() para completar. E depois poderíamos
+perguntar pelo resultado usando o método `Future <?>. get ()` como
+
+`assertEquals("blue", blue.get());`
+
+Aguardar que o processamento seja concluído (se ainda não estiver concluído)
+e obter o resultado. Se você não se importar com o resultado, você poderia
+simplesmente ter seu método assíncrono como um método vazio.
+
+Veja a documentação para saber mais: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html[Future]
+
+____
+Uma Future representa o resultado de um cálculo assíncrono. Métodos
+são fornecidos para verificar se o cálculo está completo, para aguardar
+a conclusão, e para recuperar o resultado do cálculo. O resultado
+pode somente ser recuperado usando o método get quando o cálculo estiver
+completado, bloqueando se necessário, até que esteja pronto. O cancelamento é
+realizada pelo método de cancelamento. Método adicionais são fornecidos para
+determinar se a tarefa completou normalmente ou foi cancelada. Uma vez
+o cálculo foi concluído, o cálculo não pode ser cancelado. Se você
+gostaria de usar um Future para causa de cancelabilidade mas não
+fornecer um resultado utilizável, você pode declarar tipos do formulário Future <?> e
+retornar null como resultado da tarefa subjacente.
+____
+
+== O código
+
+....
+@Singleton
+public class JobProcessor {
+@Asynchronous
+@Lock(READ)
+@AccessTimeout(-1)
+public Future<String> addJob(String jobName) {
+
+    // Finja que este trabalho leva um tempo
+    doSomeHeavyLifting();
+
+    // Devolva nosso resultado
+    return new AsyncResult<String>(jobName);
+}
+
+private void doSomeHeavyLifting() {
+    try {
+        Thread.sleep(SECONDS.toMillis(10));
+    } catch (InterruptedException e) {
+        Thread.interrupted();
+        throw new IllegalStateException(e);
+    }
+  }
+}
+....
+
+== Teste
+
+....
+public class JobProcessorTest extends TestCase {
+
+public void test() throws Exception {
+
+    final Context context = EJBContainer.createEJBContainer().getContext();
+
+    final JobProcessor processor = (JobProcessor) context.lookup("java:global/async-methods/JobProcessor");
+
+    final long start = System.nanoTime();
+
+    // Enfileirar um monte de trabalho
+    final Future<String> red = processor.addJob("red");
+    final Future<String> orange = processor.addJob("orange");
+    final Future<String> yellow = processor.addJob("yellow");
+    final Future<String> green = processor.addJob("green");
+    final Future<String> blue = processor.addJob("blue");
+    final Future<String> violet = processor.addJob("violet");
+
+    // Aguarde o resultado - 1 minuto de trabalho
+    assertEquals("blue", blue.get());
+    assertEquals("orange", orange.get());
+    assertEquals("green", green.get());
+    assertEquals("red", red.get());
+    assertEquals("yellow", yellow.get());
+    assertEquals("violet", violet.get());
+
+    // Quanto tempo levou?
+    final long total = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
+
+    // A execução deve ser em torno de 9 a 21 segundos
+    // O tempo de execução depende do número de encadeamentos disponíveis para execução assíncrona.
+    //No melhor dos casos, é 10s mais algum tempo de processamento mínimo. 
+    assertTrue("Expected > 9 but was: " + total, total > 9);
+    assertTrue("Expected < 21 but was: " + total, total < 21);
+
+  }
+}
+....
+
+....
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.async.JobProcessorTest
+INFO - ********************************************************************************
+INFO - OpenEJB http://tomee.apache.org/
+INFO - Startup: Wed Feb 27 12:46:11 BRT 2019
+INFO - Copyright 1999-2018 (C) Apache OpenEJB Project, All Rights Reserved.
+INFO - Version: 8.0.0-SNAPSHOT
+INFO - Build date: 20190227
+INFO - Build time: 04:12
+INFO - ********************************************************************************
+INFO - openejb.home = /home/soro/git/apache/tomee/examples/async-methods
+INFO - openejb.base = /home/soro/git/apache/tomee/examples/async-methods
+INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@22f71333
+INFO - Succeeded in installing singleton service
+INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
+INFO - Cannot find the configuration file [conf/openejb.xml].  Will attempt to create one for the beans deployed.
+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 - Creating TransactionManager(id=Default Transaction Manager)
+INFO - Creating SecurityService(id=Default Security Service)
+INFO - Found EjbModule in classpath: /home/soro/git/apache/tomee/examples/async-methods/target/classes
+INFO - Beginning load: /home/soro/git/apache/tomee/examples/async-methods/target/classes
+INFO - Configuring enterprise application: /home/soro/git/apache/tomee/examples/async-methods
+INFO - Auto-deploying ejb JobProcessor: EjbDeployment(deployment-id=JobProcessor)
+INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
+INFO - Auto-creating a container for bean JobProcessor: Container(type=SINGLETON, id=Default Singleton Container)
+INFO - Creating Container(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.async.JobProcessorTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Creating Container(id=Default Managed Container)
+INFO - Using directory /tmp for stateful session passivation
+INFO - Enterprise application "/home/soro/git/apache/tomee/examples/async-methods" loaded.
+INFO - Assembling app: /home/soro/git/apache/tomee/examples/async-methods
+INFO - Jndi(name="java:global/async-methods/JobProcessor!org.superbiz.async.JobProcessor")
+INFO - Jndi(name="java:global/async-methods/JobProcessor")
+INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@22f71333
+INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found
+INFO - OpenWebBeans Container is starting...
+INFO - Adding OpenWebBeansPlugin : [CdiPlugin]
+INFO - All injection points were validated successfully.
+INFO - OpenWebBeans Container has started, it took 316 ms.
+INFO - Created Ejb(deployment-id=JobProcessor, ejb-name=JobProcessor, container=Default Singleton Container)
+INFO - Started Ejb(deployment-id=JobProcessor, ejb-name=JobProcessor, container=Default Singleton Container)
+INFO - Deployed Application(path=/home/soro/git/apache/tomee/examples/async-methods)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 23.491 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+....
+
+== Como funciona debaixo dos panos
+
+Sob os panos, o que faz esse trabalho é:
+
+* O `JobProcessor` que é o chamador vê que não é realmente uma instância de
+`JobProcessor`. Pelo contrário, é uma subclasse ou proxy que tem todos os métodos sobrescrito. Métodos que devem ser assíncronos são manipulados diferentemente.
+
+* Chamadas para um método assíncrono simplesmente resultam em um `Runnable` sendo
+criado envolve o método e os parâmetros que você deu. Este runnable é
+dado a um
+http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executor.html[Executor]
+que é simplesmente uma fila de trabalho anexada a um conjunto de encadeamentos.
+* Depois de adicionar o trabalho à fila, a versão com proxy do método
+retorna uma implementação de `Future` que está ligada ao` Runnable`
+que agora está esperando na fila.
+* Quando o `Runnable` finalmente executa o método no _real_
+Na instância `JobProcessor`, ele pegará o valor de retorno e o configurará
+o `Future` tornando-o disponível para o chamador.
+
+Importante notar que o objeto `AsyncResult` o` JobProcessor`
+retornado não é o mesmo objeto `Future` que o chamador está segurando.
+
+Seria legal se o `JobProcessor` real pudesse retornar` String` e
+a versão do chamador de `JobProcessor` poderia retornar` Future <String> `,
+mas nós não vimos nenhuma maneira de fazer isso sem adicionar mais complexidade. 
+
+Então o `AsyncResult` é um simples objeto wrapper. O contêiner vai puxar
+o `String` para fora, lançar o ` AsyncResult`, então colocar o `String` em
+_real_ `Future` que o chamador está segurando.
+
+Para obter progresso ao longo do caminho, simplesmente passe um objeto seguro para thread como http://download.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html[AtomicInteger]
+para o método `@ Asynchronous` e ter o código do bean periodicamente atualizado
+com o percentual completo.
+
+== Exemplos relacionados
+
+Para processamento assíncrono complexo, a resposta do JavaEE é
+`@ MessageDrivenBean`. Dê uma olhada no exemplo
+link:../simple-mdb/README.html[simple-mdb]