TOMEE-2301 - Creation on 3 test: normal path, timeout, ended with exception
Signed-off-by: brunobat <[email protected]> rename project Signed-off-by: brunobat <[email protected]> perform first example Signed-off-by: brunobat <[email protected]> Add example with exception handling and refactor Signed-off-by: brunobat <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/d0c72909 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/d0c72909 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/d0c72909 Branch: refs/heads/master Commit: d0c7290916d85ec1e7c85d0647ebb0bb2f7467b8 Parents: b3d8edc Author: brunobat <[email protected]> Authored: Thu Nov 29 12:21:19 2018 +0000 Committer: brunobat <[email protected]> Committed: Wed Dec 5 15:27:04 2018 +0000 ---------------------------------------------------------------------- examples/concurrency-utils/pom.xml | 68 +++++++++++++ .../org/superbiz/executor/ManagedService.java | 89 ++++++++++++++++ .../superbiz/executor/ManagedServiceTest.java | 102 +++++++++++++++++++ examples/executor/pom.xml | 68 ------------- .../org/superbiz/executor/AsyncBookService.java | 77 -------------- .../superbiz/executor/AsyncBookServiceTest.java | 73 ------------- examples/pom.xml | 1 + 7 files changed, 260 insertions(+), 218 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/concurrency-utils/pom.xml ---------------------------------------------------------------------- diff --git a/examples/concurrency-utils/pom.xml b/examples/concurrency-utils/pom.xml new file mode 100644 index 0000000..0e0fba6 --- /dev/null +++ b/examples/concurrency-utils/pom.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>org.superbiz</groupId> + <artifactId>concurrency-utils</artifactId> + <version>8.0.0-SNAPSHOT</version> + <packaging>jar</packaging> + <name>OpenEJB :: Examples :: Concurrency utilities example</name> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <javaee-api.version>8.0</javaee-api.version> + <junit.version>4.12</junit.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>javaee-api</artifactId> + <version>${javaee-api.version}</version> + <scope>provided</scope> + </dependency> + <!--Tests--> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>arquillian-tomee-remote</artifactId> + <version>${pom.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.junit</groupId> + <artifactId>arquillian-junit-container</artifactId> + <version>1.4.0.Final</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jboss.arquillian.container</groupId> + <artifactId>arquillian-container-test-api</artifactId> + <version>1.4.0.Final</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.7.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/concurrency-utils/src/main/java/org/superbiz/executor/ManagedService.java ---------------------------------------------------------------------- diff --git a/examples/concurrency-utils/src/main/java/org/superbiz/executor/ManagedService.java b/examples/concurrency-utils/src/main/java/org/superbiz/executor/ManagedService.java new file mode 100644 index 0000000..89c89fe --- /dev/null +++ b/examples/concurrency-utils/src/main/java/org/superbiz/executor/ManagedService.java @@ -0,0 +1,89 @@ +package org.superbiz.executor; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import javax.annotation.Resource; +import javax.enterprise.concurrent.ManagedExecutorService; +import javax.enterprise.context.RequestScoped; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +import static java.util.Objects.nonNull; + + +@RequestScoped +public class ManagedService { + + @Resource + private ManagedExecutorService executor; + + /** + * Executes an opperation asynchronously, in a different thread provided by the {@link ManagedExecutorService}. + * The computation will carry on after the return of the method. + * + * @param value The demo data. + * @return A {@link CompletableFuture} that will return immediately. + */ + public CompletableFuture<Integer> asyncTask(final int value) { + return CompletableFuture + .supplyAsync(delayedTask(value, 100, null), executor) // Execute asynchronously. + .thenApply(i -> i + 1); // After the return of the task, do something else with the result. + } + + /** + * Executes an opperation asynchronously, in a different thread provided by the {@link ManagedExecutorService}. + * The computation will carry on after the return of the method. + * + * @param value The demo data. + * @return A {@link CompletableFuture} that will return immediately. + */ + public CompletableFuture<Integer> asyncTaskWithException(final int value) { + return CompletableFuture + .supplyAsync(delayedTask(value, 100, "Planned exception"), executor) // Execute asynchronously. + .thenApply(i -> i + 1); // After the return of the task, do something else with the result. + } + + /** + * Method to simulate an asynchronous task. Will add 1 to the value for each invocation. + * + * @param value The demo data. + * @param delayMs How long the task will take to complete. In ms. + * @param errorMessage Message for the exception simulating an execution problem + * @return + */ + private Supplier<Integer> delayedTask(final int value, + final int delayMs, + final String errorMessage) { + return () -> { + if (nonNull(errorMessage)) { + System.out.println("Exception will be thrown"); + throw new RuntimeException(errorMessage); + } + + try { + // simulate long processing task + Thread.sleep(delayMs); + } catch (InterruptedException e) { + throw new RuntimeException("Problem while waiting"); + } + System.out.println("delayedTask complete"); + return value + 1; + }; + } + +} http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/concurrency-utils/src/test/java/org/superbiz/executor/ManagedServiceTest.java ---------------------------------------------------------------------- diff --git a/examples/concurrency-utils/src/test/java/org/superbiz/executor/ManagedServiceTest.java b/examples/concurrency-utils/src/test/java/org/superbiz/executor/ManagedServiceTest.java new file mode 100644 index 0000000..1dd6ff9 --- /dev/null +++ b/examples/concurrency-utils/src/test/java/org/superbiz/executor/ManagedServiceTest.java @@ -0,0 +1,102 @@ +package org.superbiz.executor; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + + +@RunWith(Arquillian.class) +public class ManagedServiceTest { + + @Inject + private ManagedService managedService; + + @Deployment() + public static final WebArchive app() { + return ShrinkWrap.create(WebArchive.class, "example.war") + .addClasses(ManagedService.class) + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + /** + * Happy path. Normal invocation. + */ + @Test + public void managedInvocationTest() { + final CompletableFuture<Integer> future = managedService.asyncTask(1); + System.out.println("You can do something else in the meantime and later get the future value"); + try { + // To prevent hanged tasks, you should obtain the value of a future with a timeout. + assertEquals(3, future.get(200, TimeUnit.MILLISECONDS).intValue()); + } catch (Exception e) { + fail("Unexpected exception" + e); + } + } + + /** + * Request timeout. The result will take at least 100ms and we want it after 10ms. + * + * @throws InterruptedException + * @throws ExecutionException + * @throws TimeoutException + */ + @Test(expected = TimeoutException.class) + public void managedInvocationTestWithTimeout() throws InterruptedException, ExecutionException, TimeoutException { + final CompletableFuture<Integer> future = managedService.asyncTask(1); + future.get(10, TimeUnit.MILLISECONDS); + } + + /** + * The execution ended with an exception. + * Handle the exception apropriately. + * + * @throws InterruptedException + * @throws ExecutionException + * @throws TimeoutException + */ + @Test + public void managedInvocationTestWithException() { + final CompletableFuture<Integer> future = managedService.asyncTaskWithException(1); + + try { + future.get(200, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + // the thrown RuntimeException will be wrapped around an ExecutionException + assertEquals("Planned exception", e.getCause().getMessage()); + } catch (Exception e) { + fail("Unexpected exception" + e); + } + + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/executor/pom.xml ---------------------------------------------------------------------- diff --git a/examples/executor/pom.xml b/examples/executor/pom.xml deleted file mode 100644 index 08a6dd3..0000000 --- a/examples/executor/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <groupId>org.superbiz</groupId> - <artifactId>executor</artifactId> - <version>8.0.0-SNAPSHOT</version> - <packaging>jar</packaging> - <name>OpenEJB :: Examples :: Executor for concurrency utilities</name> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <javaee-api.version>8.0</javaee-api.version> - <junit.version>4.12</junit.version> - </properties> - - <dependencies> - <dependency> - <groupId>org.apache.tomee</groupId> - <artifactId>javaee-api</artifactId> - <version>${javaee-api.version}</version> - <scope>provided</scope> - </dependency> - <!--Tests--> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>${junit.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.tomee</groupId> - <artifactId>arquillian-tomee-remote</artifactId> - <version>${pom.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.jboss.arquillian.junit</groupId> - <artifactId>arquillian-junit-container</artifactId> - <version>1.4.0.Final</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.jboss.arquillian.container</groupId> - <artifactId>arquillian-container-test-api</artifactId> - <version>1.4.0.Final</version> - <scope>test</scope> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.7.1</version> - <configuration> - <source>1.8</source> - <target>1.8</target> - </configuration> - </plugin> - </plugins> - </build> - -</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/executor/src/main/java/org/superbiz/executor/AsyncBookService.java ---------------------------------------------------------------------- diff --git a/examples/executor/src/main/java/org/superbiz/executor/AsyncBookService.java b/examples/executor/src/main/java/org/superbiz/executor/AsyncBookService.java deleted file mode 100644 index 1f17189..0000000 --- a/examples/executor/src/main/java/org/superbiz/executor/AsyncBookService.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.superbiz.executor; - -import javax.annotation.Resource; -import javax.ejb.Asynchronous; -import javax.enterprise.concurrent.ManagedExecutorService; -import javax.enterprise.context.RequestScoped; -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.function.Supplier; - -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@RequestScoped -public class AsyncBookService { - - @Resource - private ManagedExecutorService executor; - - @Asynchronous - public Future<String> serviceA() { - CompletableFuture<String> future = new CompletableFuture<>(); - future.completeExceptionally(new IOException("Simulated error")); - return future; - } - - @Asynchronous - public CompletableFuture<Integer> serviceB() { - return CompletableFuture.supplyAsync(delayedSupplier(1, 100), executor) - .thenApply(i -> i + 1); - } - - @Asynchronous - public CompletableFuture<Integer> serviceB() { - return CompletableFuture.supplyAsync(delayedWithExceptionSupplier(100, new RuntimeException("test")), executor); - } - - private Supplier<Integer> delayedSupplier(final int value, - final int delayMs) { - return () -> { - try { - Thread.sleep(delayMs); - } catch (InterruptedException e) { - throw new RuntimeException("Problem while waiting"); - } - return value; - }; - } - - private CompletableFuture<Integer> delayedWithExceptionSupplier(final int delayMs, - final Throwable t) { - final CompletableFuture<Integer> future = new CompletableFuture<>(); - try { - Thread.sleep(delayMs); - future.completeExceptionally(t); - } catch (InterruptedException e) { - throw new RuntimeException("Problem while waiting"); - } - return future; - } - -} http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/executor/src/test/java/org/superbiz/executor/AsyncBookServiceTest.java ---------------------------------------------------------------------- diff --git a/examples/executor/src/test/java/org/superbiz/executor/AsyncBookServiceTest.java b/examples/executor/src/test/java/org/superbiz/executor/AsyncBookServiceTest.java deleted file mode 100644 index e567da4..0000000 --- a/examples/executor/src/test/java/org/superbiz/executor/AsyncBookServiceTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.superbiz.executor; - -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.EmptyAsset; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.Test; -import org.junit.runner.RunWith; - -import javax.inject.Inject; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@RunWith(Arquillian.class) -public class AsyncBookServiceTest { - - @Inject - private AsyncBookService service; - - @Deployment() - public static final WebArchive app() { - return ShrinkWrap.create(WebArchive.class, "example.war") - .addClasses(AsyncBookService.class) - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); - } - - @Test - public void testServiceA() { - final Future<String> future = service.serviceA(); - try { - future.get(200, TimeUnit.MILLISECONDS); - } catch (InterruptedException | TimeoutException e) { - fail("Unexpected exception" + e); - } catch (ExecutionException ioe) { - assertEquals("Simulated error", ioe.getCause().getMessage()); - } - } - - @Test - public void testServiceB() { - final CompletableFuture<Integer> future = service.serviceB(); - try { - assertEquals(2, future.get(200, TimeUnit.MILLISECONDS).intValue()); - } catch (Exception e) { - fail("Unexpected exception" + e); - } - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tomee/blob/d0c72909/examples/pom.xml ---------------------------------------------------------------------- diff --git a/examples/pom.xml b/examples/pom.xml index 9a19500..2531aa7 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -174,6 +174,7 @@ BROKEN, see TOMEE-2140 <module>mp-metrics-counted</module> <module>mp-metrics-timed</module> <module>websocket-tls-basic-auth</module> + <module>concurrency-utils</module> </modules> <dependencies>
