diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..9c5cdb8f2d
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "testgitrepo"]
+ path = testgitrepo
+ url = /home/prd/Development/projects/idea/tutorials/spring-boot/src/main/resources/testgitrepo/
diff --git a/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch
deleted file mode 100644
index 627021fb96..0000000000
--- a/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/autovalue-tutorial/pom.xml b/autovalue-tutorial/pom.xml
index 37d595dce1..d1f8e825fc 100644
--- a/autovalue-tutorial/pom.xml
+++ b/autovalue-tutorial/pom.xml
@@ -1,36 +1,37 @@
- 4.0.0
- com.baeldung
- autovalue-tutorial
- 1.0
- AutoValue
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.3
-
-
- 7
-
-
-
-
-
-
- com.google.auto.value
- auto-value
- 1.2
-
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ 4.0.0
+ com.baeldung
+ autovalue-tutorial
+ 1.0
+ AutoValue
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+
+ 7
+ false
+
+
+
+
+
+
+ com.google.auto.value
+ auto-value
+ 1.2
+
-
- junit
- junit
- 4.3
- test
-
+
+ junit
+ junit
+ 4.3
+ test
+
-
+
diff --git a/cdi/pom.xml b/cdi/pom.xml
new file mode 100644
index 0000000000..b771857938
--- /dev/null
+++ b/cdi/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ cdi
+ 1.0-SNAPSHOT
+
+
+
+ org.springframework
+ spring-core
+ ${spring.version}
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+
+
+
+ org.aspectj
+ aspectjweaver
+ 1.8.9
+
+
+ org.jboss.weld.se
+ weld-se-core
+ 2.3.5.Final
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+
+
+
+ 4.3.1.RELEASE
+
+
+
\ No newline at end of file
diff --git a/cdi/src/main/java/com/baeldung/interceptor/Audited.java b/cdi/src/main/java/com/baeldung/interceptor/Audited.java
new file mode 100644
index 0000000000..3df4bef95e
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/interceptor/Audited.java
@@ -0,0 +1,14 @@
+package com.baeldung.interceptor;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.interceptor.InterceptorBinding;
+
+@InterceptorBinding
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Audited {
+}
diff --git a/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java b/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java
new file mode 100644
index 0000000000..c62d9a4127
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java
@@ -0,0 +1,20 @@
+package com.baeldung.interceptor;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+@Audited
+@Interceptor
+public class AuditedInterceptor {
+ public static boolean calledBefore = false;
+ public static boolean calledAfter = false;
+
+ @AroundInvoke
+ public Object auditMethod(InvocationContext ctx) throws Exception {
+ calledBefore = true;
+ Object result = ctx.proceed();
+ calledAfter = true;
+ return result;
+ }
+}
diff --git a/cdi/src/main/java/com/baeldung/service/SuperService.java b/cdi/src/main/java/com/baeldung/service/SuperService.java
new file mode 100644
index 0000000000..e15f049342
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/service/SuperService.java
@@ -0,0 +1,10 @@
+package com.baeldung.service;
+
+import com.baeldung.interceptor.Audited;
+
+public class SuperService {
+ @Audited
+ public String deliverService(String uid) {
+ return uid;
+ }
+}
diff --git a/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java b/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java
new file mode 100644
index 0000000000..e48039706d
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java
@@ -0,0 +1,23 @@
+package com.baeldung.spring.aspect;
+
+import java.util.List;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@Aspect
+public class SpringTestAspect {
+ @Autowired
+ private List accumulator;
+
+ @Around("execution(* com.baeldung.spring.service.SpringSuperService.*(..))")
+ public Object auditMethod(ProceedingJoinPoint jp) throws Throwable {
+ String methodName = jp.getSignature().getName();
+ accumulator.add("Call to " + methodName);
+ Object obj = jp.proceed();
+ accumulator.add("Method called successfully: " + methodName);
+ return obj;
+ }
+}
diff --git a/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java b/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java
new file mode 100644
index 0000000000..b30c4a1326
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java
@@ -0,0 +1,30 @@
+package com.baeldung.spring.configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+import com.baeldung.spring.aspect.SpringTestAspect;
+import com.baeldung.spring.service.SpringSuperService;
+
+@Configuration
+@EnableAspectJAutoProxy
+public class AppConfig {
+ @Bean
+ public SpringSuperService springSuperService() {
+ return new SpringSuperService();
+ }
+
+ @Bean
+ public SpringTestAspect springTestAspect() {
+ return new SpringTestAspect();
+ }
+
+ @Bean
+ public List getAccumulator() {
+ return new ArrayList();
+ }
+}
diff --git a/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java b/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java
new file mode 100644
index 0000000000..082eb2e0f8
--- /dev/null
+++ b/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java
@@ -0,0 +1,7 @@
+package com.baeldung.spring.service;
+
+public class SpringSuperService {
+ public String getInfoFromService(String code) {
+ return code;
+ }
+}
diff --git a/cdi/src/main/resources/META-INF/beans.xml b/cdi/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000000..d41b35e7d9
--- /dev/null
+++ b/cdi/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,8 @@
+
+
+ com.baeldung.interceptor.AuditedInterceptor
+
+
\ No newline at end of file
diff --git a/cdi/src/test/java/com/baeldung/test/TestInterceptor.java b/cdi/src/test/java/com/baeldung/test/TestInterceptor.java
new file mode 100644
index 0000000000..3529a796d2
--- /dev/null
+++ b/cdi/src/test/java/com/baeldung/test/TestInterceptor.java
@@ -0,0 +1,38 @@
+package com.baeldung.test;
+
+import org.jboss.weld.environment.se.Weld;
+import org.jboss.weld.environment.se.WeldContainer;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.interceptor.AuditedInterceptor;
+import com.baeldung.service.SuperService;
+
+public class TestInterceptor {
+ Weld weld;
+ WeldContainer container;
+
+ @Before
+ public void init() {
+ weld = new Weld();
+ container = weld.initialize();
+ }
+
+ @After
+ public void shutdown() {
+ weld.shutdown();
+ }
+
+ @Test
+ public void givenTheService_whenMethodAndInterceptorExecuted_thenOK() {
+ SuperService superService = container.select(SuperService.class).get();
+ String code = "123456";
+ superService.deliverService(code);
+
+ Assert.assertTrue(AuditedInterceptor.calledBefore);
+ Assert.assertTrue(AuditedInterceptor.calledAfter);
+ }
+
+}
diff --git a/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java b/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java
new file mode 100644
index 0000000000..1f3a8d83e3
--- /dev/null
+++ b/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java
@@ -0,0 +1,34 @@
+package com.baeldung.test;
+
+import static org.hamcrest.CoreMatchers.is;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.spring.configuration.AppConfig;
+import com.baeldung.spring.service.SpringSuperService;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = { AppConfig.class })
+public class TestSpringInterceptor {
+ @Autowired
+ SpringSuperService springSuperService;
+
+ @Autowired
+ private List accumulator;
+
+ @Test
+ public void givenService_whenServiceAndAspectExecuted_thenOk() {
+ String code = "123456";
+ String result = springSuperService.getInfoFromService(code);
+ Assert.assertThat(accumulator.size(), is(2));
+ Assert.assertThat(accumulator.get(0), is("Call to getInfoFromService"));
+ Assert.assertThat(accumulator.get(1), is("Method called successfully: getInfoFromService"));
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java b/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java
new file mode 100644
index 0000000000..05aa14c5ae
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java
@@ -0,0 +1,22 @@
+package com.baeldung.threadpool;
+
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.RecursiveTask;
+import java.util.stream.Collectors;
+
+public class CountingTask extends RecursiveTask {
+
+ private final TreeNode node;
+
+ public CountingTask(TreeNode node) {
+ this.node = node;
+ }
+
+ @Override
+ protected Integer compute() {
+ return node.value + node.children.stream()
+ .map(childNode -> new CountingTask(childNode).fork())
+ .collect(Collectors.summingInt(ForkJoinTask::join));
+ }
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java b/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java
new file mode 100644
index 0000000000..4775fde930
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java
@@ -0,0 +1,29 @@
+package com.baeldung.threadpool;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.util.concurrent.MoreExecutors;
+
+/**
+ * This class demonstrates the usage of Guava's exiting executor services that keep the VM from hanging.
+ * Without the exiting executor service, the task would hang indefinitely.
+ * This behaviour cannot be demonstrated in JUnit tests, as JUnit kills the VM after the tests.
+ */
+public class ExitingExecutorServiceExample {
+
+ public static void main(String... args) {
+
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
+ ExecutorService executorService = MoreExecutors.getExitingExecutorService(executor, 100, TimeUnit.MILLISECONDS);
+
+ executorService.submit(() -> {
+ while (true) {
+ }
+ });
+
+ }
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java b/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java
new file mode 100644
index 0000000000..9b43152074
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java
@@ -0,0 +1,18 @@
+package com.baeldung.threadpool;
+
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+public class TreeNode {
+
+ int value;
+
+ Set children;
+
+ public TreeNode(int value, TreeNode... children) {
+ this.value = value;
+ this.children = Sets.newHashSet(children);
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/CharToStringTest.java b/core-java-8/src/test/java/com/baeldung/CharToStringTest.java
new file mode 100644
index 0000000000..d91016d104
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/CharToStringTest.java
@@ -0,0 +1,53 @@
+package com.baeldung;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CharToStringTest {
+
+ @Test
+ public void givenChar_whenCallingStringValueOf_shouldConvertToString(){
+ final char givenChar = 'x';
+
+ final String result = String.valueOf(givenChar);
+
+ assertThat(result).isEqualTo("x");
+ }
+
+ @Test
+ public void givenChar_whenCallingToStringOnCharacter_shouldConvertToString(){
+ final char givenChar = 'x';
+
+ final String result = Character.toString(givenChar);
+
+ assertThat(result).isEqualTo("x");
+ }
+
+ @Test
+ public void givenChar_whenCallingCharacterConstructor_shouldConvertToString3(){
+ final char givenChar = 'x';
+
+ final String result = new Character(givenChar).toString();
+
+ assertThat(result).isEqualTo("x");
+ }
+
+ @Test
+ public void givenChar_whenConcatenated_shouldConvertToString4(){
+ final char givenChar = 'x';
+
+ final String result = givenChar + "";
+
+ assertThat(result).isEqualTo("x");
+ }
+
+ @Test
+ public void givenChar_whenFormated_shouldConvertToString5(){
+ final char givenChar = 'x';
+
+ final String result = String.format("%c", givenChar);
+
+ assertThat(result).isEqualTo("x");
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java b/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java
new file mode 100644
index 0000000000..8143da5794
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java
@@ -0,0 +1,17 @@
+package com.baeldung;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+public class RandomListElementTest {
+
+ @Test
+ public void givenList_whenRandomNumberChosen_shouldReturnARandomElement() {
+ List givenList = Arrays.asList(1, 2, 3);
+ Random rand = new Random();
+ givenList.get(rand.nextInt(givenList.size()));
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java b/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java
new file mode 100644
index 0000000000..6c1493d89b
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java
@@ -0,0 +1,62 @@
+package com.baeldung;
+
+import com.google.common.primitives.Ints;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class StringToIntOrIntegerTest {
+
+ @Test
+ public void givenString_whenParsingInt_shouldConvertToInt() {
+ String givenString = "42";
+
+ int result = Integer.parseInt(givenString);
+
+ assertThat(result).isEqualTo(42);
+ }
+
+
+ @Test
+ public void givenString_whenCallingIntegerValueOf_shouldConvertToInt() {
+ String givenString = "42";
+
+ Integer result = Integer.valueOf(givenString);
+
+ assertThat(result).isEqualTo(new Integer(42));
+ }
+
+ @Test
+ public void givenString_whenCallingIntegerConstructor_shouldConvertToInt() {
+ String givenString = "42";
+
+ Integer result = new Integer(givenString);
+
+ assertThat(result).isEqualTo(new Integer(42));
+ }
+
+ @Test
+ public void givenString_whenCallingIntegerDecode_shouldConvertToInt() {
+ String givenString = "42";
+
+ int result = Integer.decode(givenString);
+
+ assertThat(result).isEqualTo(42);
+ }
+
+ @Test
+ public void givenString_whenTryParse_shouldConvertToInt() {
+ String givenString = "42";
+
+ Integer result = Ints.tryParse(givenString);
+
+ assertThat(result).isEqualTo(42);
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenInvalidInput_whenParsingInt_shouldThrow() {
+ String givenString = "nan";
+ Integer.parseInt(givenString);
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java b/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java
new file mode 100644
index 0000000000..5363a73afa
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java
@@ -0,0 +1,209 @@
+package com.baeldung.completablefuture;
+
+import java.util.concurrent.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class CompletableFutureTest {
+
+ @Test
+ public void whenRunningCompletableFutureAsynchronously_thenGetMethodWaitsForResult() throws InterruptedException, ExecutionException {
+
+ Future completableFuture = calculateAsync();
+
+ String result = completableFuture.get();
+ assertEquals("Hello", result);
+
+ }
+
+ public Future calculateAsync() throws InterruptedException {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+
+ Executors.newCachedThreadPool().submit(() -> {
+ Thread.sleep(500);
+ completableFuture.complete("Hello");
+ return null;
+ });
+
+ return completableFuture;
+ }
+
+ @Test
+ public void whenRunningCompletableFutureWithResult_thenGetMethodReturnsImmediately() throws InterruptedException, ExecutionException {
+
+ Future completableFuture = CompletableFuture.completedFuture("Hello");
+
+ String result = completableFuture.get();
+ assertEquals("Hello", result);
+
+ }
+
+
+ public Future calculateAsyncWithCancellation() throws InterruptedException {
+ CompletableFuture completableFuture = new CompletableFuture<>();
+
+ Executors.newCachedThreadPool().submit(() -> {
+ Thread.sleep(500);
+ completableFuture.cancel(false);
+ return null;
+ });
+
+ return completableFuture;
+ }
+
+
+ @Test(expected = CancellationException.class)
+ public void whenCancelingTheFuture_thenThrowsCancellationException() throws ExecutionException, InterruptedException {
+
+ Future future = calculateAsyncWithCancellation();
+ future.get();
+
+ }
+
+ @Test
+ public void whenCreatingCompletableFutureWithSupplyAsync_thenFutureReturnsValue() throws ExecutionException, InterruptedException {
+
+ CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello");
+
+ assertEquals("Hello", future.get());
+
+ }
+
+ @Test
+ public void whenAddingThenAcceptToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
+
+ CompletableFuture future = completableFuture.thenAccept(s -> System.out.println("Computation returned: " + s));
+
+ future.get();
+
+ }
+
+ @Test
+ public void whenAddingThenRunToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
+
+ CompletableFuture future = completableFuture.thenRun(() -> System.out.println("Computation finished."));
+
+ future.get();
+
+ }
+
+ @Test
+ public void whenAddingThenApplyToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
+
+ CompletableFuture future = completableFuture.thenApply(s -> s + " World");
+
+ assertEquals("Hello World", future.get());
+
+ }
+
+ @Test
+ public void whenUsingThenCompose_thenFuturesExecuteSequentially() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
+ .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));
+
+ assertEquals("Hello World", completableFuture.get());
+
+ }
+
+ @Test
+ public void whenUsingThenCombine_thenWaitForExecutionOfBothFutures() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello")
+ .thenCombine(CompletableFuture.supplyAsync(() -> " World"),
+ (s1, s2) -> s1 + s2);
+
+ assertEquals("Hello World", completableFuture.get());
+
+ }
+
+ @Test
+ public void whenUsingThenAcceptBoth_thenWaitForExecutionOfBothFutures() throws ExecutionException, InterruptedException {
+
+ CompletableFuture.supplyAsync(() -> "Hello")
+ .thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"),
+ (s1, s2) -> System.out.println(s1 + s2));
+
+ }
+
+ @Test
+ public void whenFutureCombinedWithAllOfCompletes_thenAllFuturesAreDone() throws ExecutionException, InterruptedException {
+
+ CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello");
+ CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "Beautiful");
+ CompletableFuture future3 = CompletableFuture.supplyAsync(() -> "World");
+
+ CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3);
+
+ // ...
+
+ combinedFuture.get();
+
+ assertTrue(future1.isDone());
+ assertTrue(future2.isDone());
+ assertTrue(future3.isDone());
+
+ String combined = Stream.of(future1, future2, future3)
+ .map(CompletableFuture::join)
+ .collect(Collectors.joining(" "));
+
+ assertEquals("Hello Beautiful World", combined);
+
+ }
+
+ @Test
+ public void whenFutureThrows_thenHandleMethodReceivesException() throws ExecutionException, InterruptedException {
+
+ String name = null;
+
+ // ...
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
+ if (name == null) {
+ throw new RuntimeException("Computation error!");
+ }
+ return "Hello, " + name;
+ }).handle((s, t) -> s != null ? s : "Hello, Stranger!");
+
+ assertEquals("Hello, Stranger!", completableFuture.get());
+
+ }
+
+ @Test(expected = ExecutionException.class)
+ public void whenCompletingFutureExceptionally_thenGetMethodThrows() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = new CompletableFuture<>();
+
+ // ...
+
+ completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
+
+ // ...
+
+ completableFuture.get();
+
+ }
+
+ @Test
+ public void whenAddingThenApplyAsyncToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException {
+
+ CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello");
+
+ CompletableFuture future = completableFuture.thenApplyAsync(s -> s + " World");
+
+ assertEquals("Hello World", future.get());
+
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java b/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java
new file mode 100644
index 0000000000..ce878026d4
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java
@@ -0,0 +1,199 @@
+package com.baeldung.functionalinterface;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.common.util.concurrent.Uninterruptibles;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class FunctionalInterfaceTest {
+
+ @Test
+ public void whenPassingLambdaToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() {
+
+ Map nameMap = new HashMap<>();
+ Integer value = nameMap.computeIfAbsent("John", s -> s.length());
+
+ assertEquals(new Integer(4), nameMap.get("John"));
+ assertEquals(new Integer(4), value);
+
+ }
+
+ @Test
+ public void whenPassingMethodReferenceToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() {
+
+ Map nameMap = new HashMap<>();
+ Integer value = nameMap.computeIfAbsent("John", String::length);
+
+ assertEquals(new Integer(4), nameMap.get("John"));
+ assertEquals(new Integer(4), value);
+
+ }
+
+ public byte[] transformArray(short[] array, ShortToByteFunction function) {
+ byte[] transformedArray = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ transformedArray[i] = function.applyAsByte(array[i]);
+ }
+ return transformedArray;
+ }
+
+ @Test
+ public void whenUsingCustomFunctionalInterfaceForPrimitives_thenCanUseItAsLambda() {
+
+ short[] array = {(short) 1, (short) 2, (short) 3};
+ byte[] transformedArray = transformArray(array, s -> (byte) (s * 2));
+
+ byte[] expectedArray = {(byte) 2, (byte) 4, (byte) 6};
+ assertArrayEquals(expectedArray, transformedArray);
+
+ }
+
+ @Test
+ public void whenUsingBiFunction_thenCanUseItToReplaceMapValues() {
+
+ Map salaries = new HashMap<>();
+ salaries.put("John", 40000);
+ salaries.put("Freddy", 30000);
+ salaries.put("Samuel", 50000);
+
+ salaries.replaceAll((name, oldValue) -> name.equals("Freddy") ? oldValue : oldValue + 10000);
+
+ assertEquals(new Integer(50000), salaries.get("John"));
+ assertEquals(new Integer(30000), salaries.get("Freddy"));
+ assertEquals(new Integer(60000), salaries.get("Samuel"));
+
+ }
+
+
+ @Test
+ public void whenPassingLambdaToThreadConstructor_thenLambdaInferredToRunnable() {
+
+ Thread thread = new Thread(() -> System.out.println("Hello From Another Thread"));
+ thread.start();
+
+ }
+
+ @Test
+ public void whenUsingSupplierToGenerateNumbers_thenCanUseItInStreamGenerate() {
+
+ int[] fibs = {0, 1};
+ Stream fibonacci = Stream.generate(() -> {
+ int result = fibs[1];
+ int fib3 = fibs[0] + fibs[1];
+ fibs[0] = fibs[1];
+ fibs[1] = fib3;
+ return result;
+ });
+
+ List fibonacci5 = fibonacci.limit(5)
+ .collect(Collectors.toList());
+
+ assertEquals(new Integer(1), fibonacci5.get(0));
+ assertEquals(new Integer(1), fibonacci5.get(1));
+ assertEquals(new Integer(2), fibonacci5.get(2));
+ assertEquals(new Integer(3), fibonacci5.get(3));
+ assertEquals(new Integer(5), fibonacci5.get(4));
+
+ }
+
+ @Test
+ public void whenUsingConsumerInForEach_thenConsumerExecutesForEachListElement() {
+
+ List names = Arrays.asList("John", "Freddy", "Samuel");
+ names.forEach(name -> System.out.println("Hello, " + name));
+
+ }
+
+ @Test
+ public void whenUsingBiConsumerInForEach_thenConsumerExecutesForEachMapElement() {
+
+ Map ages = new HashMap<>();
+ ages.put("John", 25);
+ ages.put("Freddy", 24);
+ ages.put("Samuel", 30);
+
+ ages.forEach((name, age) -> System.out.println(name + " is " + age + " years old"));
+
+ }
+
+ @Test
+ public void whenUsingPredicateInFilter_thenListValuesAreFilteredOut() {
+
+ List names = Arrays.asList("Angela", "Aaron", "Bob", "Claire", "David");
+
+ List namesWithA = names.stream()
+ .filter(name -> name.startsWith("A"))
+ .collect(Collectors.toList());
+
+ assertEquals(2, namesWithA.size());
+ assertTrue(namesWithA.contains("Angela"));
+ assertTrue(namesWithA.contains("Aaron"));
+
+ }
+
+ @Test
+ public void whenUsingUnaryOperatorWithReplaceAll_thenAllValuesInTheListAreReplaced() {
+
+ List names = Arrays.asList("bob", "josh", "megan");
+
+ names.replaceAll(String::toUpperCase);
+
+ assertEquals("BOB", names.get(0));
+ assertEquals("JOSH", names.get(1));
+ assertEquals("MEGAN", names.get(2));
+
+ }
+
+ @Test
+ public void whenUsingBinaryOperatorWithStreamReduce_thenResultIsSumOfValues() {
+
+ List values = Arrays.asList(3, 5, 8, 9, 12);
+
+ int sum = values.stream()
+ .reduce(0, (i1, i2) -> i1 + i2);
+
+ assertEquals(37, sum);
+
+ }
+
+ @Test
+ public void whenComposingTwoFunctions_thenFunctionsExecuteSequentially() {
+
+ Function intToString = Object::toString;
+ Function quote = s -> "'" + s + "'";
+
+ Function quoteIntToString = quote.compose(intToString);
+
+ assertEquals("'5'", quoteIntToString.apply(5));
+
+ }
+
+ public double squareLazy(Supplier lazyValue) {
+ return Math.pow(lazyValue.get(), 2);
+ }
+
+ @Test
+ public void whenUsingSupplierToGenerateValue_thenValueIsGeneratedLazily() {
+
+ Supplier lazyValue = () -> {
+ Uninterruptibles.sleepUninterruptibly(1000, TimeUnit.MILLISECONDS);
+ return 9d;
+ };
+
+ double valueSquared = squareLazy(lazyValue);
+
+ assertEquals(81d, valueSquared, 0);
+
+ }
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java b/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java
new file mode 100644
index 0000000000..3231d6244f
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java
@@ -0,0 +1,8 @@
+package com.baeldung.functionalinterface;
+
+@FunctionalInterface
+public interface ShortToByteFunction {
+
+ byte applyAsByte(short s);
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java b/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java
new file mode 100644
index 0000000000..df336f4a93
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java
@@ -0,0 +1,146 @@
+package com.baeldung.threadpool;
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class CoreThreadPoolTest {
+
+ @Test(timeout = 1000)
+ public void whenCallingExecuteWithRunnable_thenRunnableIsExecuted() throws InterruptedException {
+
+ CountDownLatch lock = new CountDownLatch(1);
+
+ Executor executor = Executors.newSingleThreadExecutor();
+ executor.execute(() -> {
+ System.out.println("Hello World");
+ lock.countDown();
+ });
+
+ lock.await(1000, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void whenUsingExecutorServiceAndFuture_thenCanWaitOnFutureResult() throws InterruptedException, ExecutionException {
+
+ ExecutorService executorService = Executors.newFixedThreadPool(10);
+ Future future = executorService.submit(() -> "Hello World");
+ String result = future.get();
+
+ assertEquals("Hello World", result);
+
+ }
+
+ @Test
+ public void whenUsingFixedThreadPool_thenCoreAndMaximumThreadSizeAreTheSame() {
+
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+
+ assertEquals(2, executor.getPoolSize());
+ assertEquals(1, executor.getQueue().size());
+
+ }
+
+ @Test
+ public void whenUsingCachedThreadPool_thenPoolSizeGrowsUnbounded() {
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+ executor.submit(() -> {
+ Thread.sleep(1000);
+ return null;
+ });
+
+ assertEquals(3, executor.getPoolSize());
+ assertEquals(0, executor.getQueue().size());
+
+ }
+
+ @Test(timeout = 1000)
+ public void whenUsingSingleThreadPool_thenTasksExecuteSequentially() throws InterruptedException {
+
+ CountDownLatch lock = new CountDownLatch(2);
+ AtomicInteger counter = new AtomicInteger();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.submit(() -> {
+ counter.set(1);
+ lock.countDown();
+ });
+ executor.submit(() -> {
+ counter.compareAndSet(1, 2);
+ lock.countDown();
+ });
+
+ lock.await(1000, TimeUnit.MILLISECONDS);
+ assertEquals(2, counter.get());
+
+ }
+
+ @Test(timeout = 1000)
+ public void whenSchedulingTask_thenTaskExecutesWithinGivenPeriod() throws InterruptedException {
+
+ CountDownLatch lock = new CountDownLatch(1);
+
+ ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
+ executor.schedule(() -> {
+ System.out.println("Hello World");
+ lock.countDown();
+ }, 500, TimeUnit.MILLISECONDS);
+
+ lock.await(1000, TimeUnit.MILLISECONDS);
+
+ }
+
+ @Test(timeout = 1000)
+ public void whenSchedulingTaskWithFixedPeriod_thenTaskExecutesMultipleTimes() throws InterruptedException {
+
+ CountDownLatch lock = new CountDownLatch(3);
+
+ ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
+ ScheduledFuture> future = executor.scheduleAtFixedRate(() -> {
+ System.out.println("Hello World");
+ lock.countDown();
+ }, 500, 100, TimeUnit.MILLISECONDS);
+
+ lock.await();
+ future.cancel(true);
+
+ }
+
+ @Test
+ public void whenUsingForkJoinPool_thenSumOfTreeElementsIsCalculatedCorrectly() {
+
+ TreeNode tree = new TreeNode(5,
+ new TreeNode(3), new TreeNode(2,
+ new TreeNode(2), new TreeNode(8)));
+
+ ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
+ int sum = forkJoinPool.invoke(new CountingTask(tree));
+
+ assertEquals(20, sum);
+ }
+
+
+}
diff --git a/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java b/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java
new file mode 100644
index 0000000000..92e0f9a8cb
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.threadpool;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class GuavaThreadPoolTest {
+
+ @Test
+ public void whenExecutingTaskWithDirectExecutor_thenTheTaskIsExecutedInTheCurrentThread() {
+
+ Executor executor = MoreExecutors.directExecutor();
+
+ AtomicBoolean executed = new AtomicBoolean();
+
+ executor.execute(() -> {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ executed.set(true);
+ });
+
+ assertTrue(executed.get());
+ }
+
+ @Test
+ public void whenJoiningFuturesWithAllAsList_thenCombinedFutureCompletesAfterAllFuturesComplete() throws ExecutionException, InterruptedException {
+
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
+
+ ListenableFuture future1 = listeningExecutorService.submit(() -> "Hello");
+ ListenableFuture future2 = listeningExecutorService.submit(() -> "World");
+
+ String greeting = Futures.allAsList(future1, future2).get()
+ .stream()
+ .collect(Collectors.joining(" "));
+ assertEquals("Hello World", greeting);
+
+ }
+
+}
diff --git a/spring-security-rest-custom/.gitignore b/core-java-9/.gitignore
similarity index 100%
rename from spring-security-rest-custom/.gitignore
rename to core-java-9/.gitignore
diff --git a/core-java-9/README.md b/core-java-9/README.md
new file mode 100644
index 0000000000..b5d4dbef95
--- /dev/null
+++ b/core-java-9/README.md
@@ -0,0 +1,5 @@
+=========
+
+## Core Java 9 Examples
+
+http://inprogress.baeldung.com/java-9-new-features/
\ No newline at end of file
diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml
new file mode 100644
index 0000000000..b29838d283
--- /dev/null
+++ b/core-java-9/pom.xml
@@ -0,0 +1,102 @@
+
+ 4.0.0
+ com.baeldung
+ core-java9
+ 0.2-SNAPSHOT
+
+ core-java9
+
+
+
+ apache.snapshots
+ http://repository.apache.org/snapshots/
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${org.slf4j.version}
+
+
+
+
+
+ org.hamcrest
+ hamcrest-library
+ ${org.hamcrest.version}
+ test
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+
+
+ core-java-9
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ 1.9
+
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+
+
+
+
+
+
+ 1.7.13
+ 1.0.13
+
+
+
+
+ 3.6-jigsaw-SNAPSHOT
+
+
+ 2.19.1
+
+
+ 1.3
+ 4.12
+ 1.10.19
+
+
+
diff --git a/core-java-9/src/main/java/.gitignore b/core-java-9/src/main/java/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/core-java-9/src/main/java/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java b/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java
new file mode 100644
index 0000000000..fd6a496b18
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java
@@ -0,0 +1,23 @@
+package com.baeldung.java9.language;
+
+public interface PrivateInterface {
+
+ private static String staticPrivate() {
+ return "static private";
+ }
+
+ private String instancePrivate() {
+ return "instance private";
+ }
+
+ public default void check(){
+ String result = staticPrivate();
+ if (!result.equals("static private"))
+ throw new AssertionError("Incorrect result for static private interface method");
+ PrivateInterface pvt = new PrivateInterface() {
+ };
+ result = pvt.instancePrivate();
+ if (!result.equals("instance private"))
+ throw new AssertionError("Incorrect result for instance private interface method");
+ }
+}
diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java b/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java
new file mode 100644
index 0000000000..d6682bd0c8
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java
@@ -0,0 +1,44 @@
+package com.baeldung.java9.process;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.stream.Stream;
+
+
+public class ProcessUtils {
+
+ public static String getClassPath(){
+ String cp = System.getProperty("java.class.path");
+ System.out.println("ClassPath is "+cp);
+ return cp;
+ }
+
+ public static File getJavaCmd() throws IOException{
+ String javaHome = System.getProperty("java.home");
+ File javaCmd;
+ if(System.getProperty("os.name").startsWith("Win")){
+ javaCmd = new File(javaHome, "bin/java.exe");
+ }else{
+ javaCmd = new File(javaHome, "bin/java");
+ }
+ if(javaCmd.canExecute()){
+ return javaCmd;
+ }else{
+ throw new UnsupportedOperationException(javaCmd.getCanonicalPath() + " is not executable");
+ }
+ }
+
+ public static String getMainClass(){
+ return System.getProperty("sun.java.command");
+ }
+
+ public static String getSystemProperties(){
+ StringBuilder sb = new StringBuilder();
+ System.getProperties().forEach((s1, s2) -> sb.append(s1 +" - "+ s2) );
+ return sb.toString();
+ }
+}
diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java
new file mode 100644
index 0000000000..458f746496
--- /dev/null
+++ b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java
@@ -0,0 +1,22 @@
+package com.baeldung.java9.process;
+
+import java.util.Optional;
+
+public class ServiceMain {
+
+ public static void main(String[] args) throws InterruptedException {
+ ProcessHandle thisProcess = ProcessHandle.current();
+ long pid = thisProcess.getPid();
+
+
+ Optional opArgs = Optional.ofNullable(args);
+ String procName = opArgs.map(str -> str.length > 0 ? str[0] : null).orElse(System.getProperty("sun.java.command"));
+
+ for (int i = 0; i < 10000; i++) {
+ System.out.println("Process " + procName + " with ID " + pid + " is running!");
+ Thread.sleep(10000);
+ }
+
+ }
+
+}
diff --git a/core-java-9/src/main/resources/logback.xml b/core-java-9/src/main/resources/logback.xml
new file mode 100644
index 0000000000..eefdc7a337
--- /dev/null
+++ b/core-java-9/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java b/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java
new file mode 100644
index 0000000000..d6c16b91bc
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.java9;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.awt.Image;
+import java.awt.image.BaseMultiResolutionImage;
+import java.awt.image.BufferedImage;
+import java.awt.image.MultiResolutionImage;
+import java.util.List;
+
+import org.junit.Test;
+
+public class MultiResultionImageTest {
+
+
+ @Test
+ public void baseMultiResImageTest() {
+ int baseIndex = 1;
+ int length = 4;
+ BufferedImage[] resolutionVariants = new BufferedImage[length];
+ for (int i = 0; i < length; i++) {
+ resolutionVariants[i] = createImage(i);
+ }
+ MultiResolutionImage bmrImage = new BaseMultiResolutionImage(baseIndex, resolutionVariants);
+ List rvImageList = bmrImage.getResolutionVariants();
+ assertEquals("MultiResoltion Image shoudl contain the same number of resolution variants!", rvImageList.size(), length);
+
+ for (int i = 0; i < length; i++) {
+ int imageSize = getSize(i);
+ Image testRVImage = bmrImage.getResolutionVariant(imageSize, imageSize);
+ assertSame("Images should be the same", testRVImage, resolutionVariants[i]);
+ }
+
+ }
+
+ private static int getSize(int i) {
+ return 8 * (i + 1);
+ }
+
+
+ private static BufferedImage createImage(int i) {
+ return new BufferedImage(getSize(i), getSize(i),
+ BufferedImage.TYPE_INT_RGB);
+ }
+
+}
diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java b/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java
new file mode 100644
index 0000000000..ab28b0a805
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.java9.httpclient;
+
+
+
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimpleHttpRequestsTest {
+
+ private URI httpURI;
+
+ @Before
+ public void init() throws URISyntaxException {
+ httpURI = new URI("http://www.baeldung.com/");
+ }
+
+ @Test
+ public void quickGet() throws IOException, InterruptedException, URISyntaxException {
+ HttpRequest request = HttpRequest.create( httpURI ).GET();
+ HttpResponse response = request.response();
+ int responseStatusCode = response.statusCode();
+ String responseBody = response.body(HttpResponse.asString());
+ assertTrue("Get response status code is bigger then 400", responseStatusCode < 400);
+ }
+
+ @Test
+ public void asynchronousGet() throws URISyntaxException, IOException, InterruptedException, ExecutionException{
+ HttpRequest request = HttpRequest.create(httpURI).GET();
+ long before = System.currentTimeMillis();
+ CompletableFuture futureResponse = request.responseAsync();
+ futureResponse.thenAccept( response -> {
+ String responseBody = response.body(HttpResponse.asString());
+ });
+ HttpResponse resp = futureResponse.get();
+ HttpHeaders hs = resp.headers();
+ assertTrue("There should be more then 1 header.", hs.map().size() >1);
+ }
+
+ @Test
+ public void postMehtod() throws URISyntaxException, IOException, InterruptedException {
+ HttpRequest.Builder requestBuilder = HttpRequest.create(httpURI);
+ requestBuilder.body(HttpRequest.fromString("param1=foo,param2=bar")).followRedirects(HttpClient.Redirect.SECURE);
+ HttpRequest request = requestBuilder.POST();
+ HttpResponse response = request.response();
+ int statusCode = response.statusCode();
+ assertTrue("HTTP return code", statusCode == HTTP_OK);
+ }
+
+ @Test
+ public void configureHttpClient() throws NoSuchAlgorithmException, URISyntaxException, IOException, InterruptedException{
+ CookieManager cManager = new CookieManager();
+ cManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
+
+ SSLParameters sslParam = new SSLParameters (new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, new String[] { "TLSv1.2" });
+
+ HttpClient.Builder hcBuilder = HttpClient.create();
+ hcBuilder.cookieManager(cManager).sslContext(SSLContext.getDefault()).sslParameters(sslParam);
+ HttpClient httpClient = hcBuilder.build();
+ HttpRequest.Builder reqBuilder = httpClient.request(new URI("https://www.facebook.com"));
+
+ HttpRequest request = reqBuilder.followRedirects(HttpClient.Redirect.ALWAYS).GET();
+ HttpResponse response = request.response();
+ int statusCode = response.statusCode();
+ assertTrue("HTTP return code", statusCode == HTTP_OK);
+ }
+
+ SSLParameters getDefaultSSLParameters() throws NoSuchAlgorithmException{
+ SSLParameters sslP1 = SSLContext.getDefault().getSupportedSSLParameters();
+ String [] proto = sslP1.getApplicationProtocols();
+ String [] cifers = sslP1.getCipherSuites();
+ System.out.println(printStringArr(proto));
+ System.out.println(printStringArr(cifers));
+ return sslP1;
+ }
+
+ String printStringArr(String ... args ){
+ if(args == null){
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ for (String s : args){
+ sb.append(s);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ String printHeaders(HttpHeaders h){
+ if(h == null){
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ Map> hMap = h.map();
+ for(String k : hMap.keySet()){
+ sb.append(k).append(":");
+ List l = hMap.get(k);
+ if( l != null ){
+ l.forEach( s -> { sb.append(s).append(","); } );
+ }
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+}
diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java
new file mode 100644
index 0000000000..33da6486f4
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.java9.language;
+
+import org.junit.Test;
+
+public class DiamondTest {
+
+ static class FooClass {
+ FooClass(X x) {
+ }
+
+ FooClass(X x, Z z) {
+ }
+ }
+
+ @Test
+ public void diamondTest() {
+ FooClass fc = new FooClass<>(1) {
+ };
+ FooClass extends Integer> fc0 = new FooClass<>(1) {
+ };
+ FooClass> fc1 = new FooClass<>(1) {
+ };
+ FooClass super Integer> fc2 = new FooClass<>(1) {
+ };
+
+ FooClass fc3 = new FooClass<>(1, "") {
+ };
+ FooClass extends Integer> fc4 = new FooClass<>(1, "") {
+ };
+ FooClass> fc5 = new FooClass<>(1, "") {
+ };
+ FooClass super Integer> fc6 = new FooClass<>(1, "") {
+ };
+
+ }
+}
diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java
new file mode 100644
index 0000000000..29ef3930f8
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.java9.language;
+
+import com.baeldung.java9.language.PrivateInterface;
+import org.junit.Test;
+
+public class PrivateInterfaceTest {
+
+ @Test
+ public void test() {
+ PrivateInterface piClass = new PrivateInterface() {
+ };
+ piClass.check();
+ }
+
+}
diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java
new file mode 100644
index 0000000000..687dfbc390
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.java9.language;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class TryWithResourcesTest {
+
+ static int closeCount = 0;
+
+ static class MyAutoCloseable implements AutoCloseable{
+ final FinalWrapper finalWrapper = new FinalWrapper();
+
+ public void close() {
+ closeCount++;
+ }
+
+ static class FinalWrapper {
+ public final AutoCloseable finalCloseable = new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ closeCount++;
+ }
+ };
+ }
+ }
+
+ @Test
+ public void tryWithResourcesTest() {
+ MyAutoCloseable mac = new MyAutoCloseable();
+
+ try (mac) {
+ assertEquals("Expected and Actual does not match", 0, closeCount);
+ }
+
+ try (mac.finalWrapper.finalCloseable) {
+ assertEquals("Expected and Actual does not match", 1, closeCount);
+ } catch (Exception ex) {
+ }
+
+ try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
+ assertEquals("Expected and Actual does not match", 2, closeCount);
+ } catch (Exception ex) {
+ }
+
+ try ((closeCount > 0 ? mac : new MyAutoCloseable()).finalWrapper.finalCloseable) {
+ assertEquals("Expected and Actual does not match", 3, closeCount);
+ } catch (Exception ex) {
+ }
+
+ try {
+ throw new CloseableException();
+ } catch (CloseableException ex) {
+ try (ex) {
+ assertEquals("Expected and Actual does not match", 4, closeCount);
+ }
+ }
+ assertEquals("Expected and Actual does not match", 5, closeCount);
+ }
+
+
+ static class CloseableException extends Exception implements AutoCloseable {
+ @Override
+ public void close() {
+ closeCount++;
+ }
+ }
+
+}
+
+
diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java
new file mode 100644
index 0000000000..419516cb64
--- /dev/null
+++ b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java
@@ -0,0 +1,112 @@
+package com.baeldung.java9.process;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Stream;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import junit.framework.Assert;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ProcessApi {
+
+
+ @Before
+ public void init() {
+
+ }
+
+ @Test
+ public void processInfoExample()throws NoSuchAlgorithmException{
+ ProcessHandle self = ProcessHandle.current();
+ long PID = self.getPid();
+ ProcessHandle.Info procInfo = self.info();
+ Optional args = procInfo.arguments();
+ Optional cmd = procInfo.commandLine();
+ Optional startTime = procInfo.startInstant();
+ Optional cpuUsage = procInfo.totalCpuDuration();
+
+ waistCPU();
+ System.out.println("Args "+ args);
+ System.out.println("Command " +cmd.orElse("EmptyCmd"));
+ System.out.println("Start time: "+ startTime.get().toString());
+ System.out.println(cpuUsage.get().toMillis());
+
+ Stream allProc = ProcessHandle.current().children();
+ allProc.forEach(p -> {
+ System.out.println("Proc "+ p.getPid());
+ });
+
+ }
+
+ @Test
+ public void createAndDestroyProcess() throws IOException, InterruptedException{
+ int numberOfChildProcesses = 5;
+ for(int i=0; i < numberOfChildProcesses; i++){
+ createNewJVM(ServiceMain.class, i).getPid();
+ }
+
+ Stream childProc = ProcessHandle.current().children();
+ assertEquals( childProc.count(), numberOfChildProcesses);
+
+ childProc = ProcessHandle.current().children();
+ childProc.forEach(processHandle -> {
+ assertTrue("Process "+ processHandle.getPid() +" should be alive!", processHandle.isAlive());
+ CompletableFuture onProcExit = processHandle.onExit();
+ onProcExit.thenAccept(procHandle -> {
+ System.out.println("Process with PID "+ procHandle.getPid() + " has stopped");
+ });
+ });
+
+ Thread.sleep(10000);
+
+ childProc = ProcessHandle.current().children();
+ childProc.forEach(procHandle -> {
+ assertTrue("Could not kill process "+procHandle.getPid(), procHandle.destroy());
+ });
+
+ Thread.sleep(5000);
+
+ childProc = ProcessHandle.current().children();
+ childProc.forEach(procHandle -> {
+ assertFalse("Process "+ procHandle.getPid() +" should not be alive!", procHandle.isAlive());
+ });
+
+ }
+
+ private Process createNewJVM(Class mainClass, int number) throws IOException{
+ ArrayList cmdParams = new ArrayList(5);
+ cmdParams.add(ProcessUtils.getJavaCmd().getAbsolutePath());
+ cmdParams.add("-cp");
+ cmdParams.add(ProcessUtils.getClassPath());
+ cmdParams.add(mainClass.getName());
+ cmdParams.add("Service "+ number);
+ ProcessBuilder myService = new ProcessBuilder(cmdParams);
+ myService.inheritIO();
+ return myService.start();
+ }
+
+ private void waistCPU() throws NoSuchAlgorithmException{
+ ArrayList randArr = new ArrayList(4096);
+ SecureRandom sr = SecureRandom.getInstanceStrong();
+ Duration somecpu = Duration.ofMillis(4200L);
+ Instant end = Instant.now().plus(somecpu);
+ while (Instant.now().isBefore(end)) {
+ //System.out.println(sr.nextInt());
+ randArr.add( sr.nextInt() );
+ }
+ }
+
+}
diff --git a/core-java-9/src/test/resources/.gitignore b/core-java-9/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/core-java-9/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Animal.java b/core-java/src/main/java/com/baeldung/java/reflection/Animal.java
new file mode 100644
index 0000000000..3f36243c29
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Animal.java
@@ -0,0 +1,23 @@
+package com.baeldung.java.reflection;
+
+public abstract class Animal implements Eating {
+
+ public static final String CATEGORY = "domestic";
+
+ private String name;
+
+ public Animal(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ protected abstract String getSound();
+
+}
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Bird.java b/core-java/src/main/java/com/baeldung/java/reflection/Bird.java
new file mode 100644
index 0000000000..bd6f13094c
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Bird.java
@@ -0,0 +1,36 @@
+package com.baeldung.java.reflection;
+
+public class Bird extends Animal {
+ private boolean walks;
+
+ public Bird() {
+ super("bird");
+ }
+
+ public Bird(String name, boolean walks) {
+ super(name);
+ setWalks(walks);
+ }
+
+ public Bird(String name) {
+ super(name);
+ }
+
+ @Override
+ public String eats() {
+ return "grains";
+ }
+
+ @Override
+ protected String getSound() {
+ return "chaps";
+ }
+
+ public boolean walks() {
+ return walks;
+ }
+
+ public void setWalks(boolean walks) {
+ this.walks = walks;
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Eating.java b/core-java/src/main/java/com/baeldung/java/reflection/Eating.java
new file mode 100644
index 0000000000..479425cad4
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Eating.java
@@ -0,0 +1,5 @@
+package com.baeldung.java.reflection;
+
+public interface Eating {
+ String eats();
+}
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Goat.java b/core-java/src/main/java/com/baeldung/java/reflection/Goat.java
new file mode 100644
index 0000000000..503717ae5e
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Goat.java
@@ -0,0 +1,24 @@
+package com.baeldung.java.reflection;
+
+public class Goat extends Animal implements Locomotion {
+
+ public Goat(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getSound() {
+ return "bleat";
+ }
+
+ @Override
+ public String getLocomotion() {
+ return "walks";
+ }
+
+ @Override
+ public String eats() {
+ return "grass";
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java b/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java
new file mode 100644
index 0000000000..047c00cb13
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java
@@ -0,0 +1,5 @@
+package com.baeldung.java.reflection;
+
+public interface Locomotion {
+ String getLocomotion();
+}
diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Person.java b/core-java/src/main/java/com/baeldung/java/reflection/Person.java
new file mode 100644
index 0000000000..f3d7f9f001
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/java/reflection/Person.java
@@ -0,0 +1,6 @@
+package com.baeldung.java.reflection;
+
+public class Person {
+ private String name;
+ private int age;
+}
diff --git a/core-java/src/main/resources/targetFile.tmp b/core-java/src/main/resources/targetFile.tmp
deleted file mode 100644
index 20f137b416..0000000000
--- a/core-java/src/main/resources/targetFile.tmp
+++ /dev/null
@@ -1,2 +0,0 @@
-line 1
-a second line
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java b/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java
new file mode 100644
index 0000000000..a12a2f205f
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java
@@ -0,0 +1,326 @@
+package com.baeldung.java.reflection;
+
+import org.junit.Test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import static org.junit.Assert.*;
+
+public class ReflectionTest {
+
+ @Test
+ public void givenObject_whenGetsFieldNamesAtRuntime_thenCorrect() {
+ Object person = new Person();
+ Field[] fields = person.getClass().getDeclaredFields();
+
+ List actualFieldNames = getFieldNames(fields);
+
+ assertTrue(Arrays.asList("name", "age")
+ .containsAll(actualFieldNames));
+ }
+
+ @Test
+ public void givenObject_whenGetsClassName_thenCorrect() {
+ Object goat = new Goat("goat");
+ Class> clazz = goat.getClass();
+
+ assertEquals("Goat", clazz.getSimpleName());
+ assertEquals("com.baeldung.java.reflection.Goat", clazz.getName());
+ assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName());
+ }
+
+ @Test
+ public void givenClassName_whenCreatesObject_thenCorrect()
+ throws ClassNotFoundException {
+ Class> clazz = Class.forName("com.baeldung.java.reflection.Goat");
+
+ assertEquals("Goat", clazz.getSimpleName());
+ assertEquals("com.baeldung.java.reflection.Goat", clazz.getName());
+ assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName());
+ }
+
+ @Test
+ public void givenClass_whenRecognisesModifiers_thenCorrect()
+ throws ClassNotFoundException {
+ Class> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
+ Class> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
+ int goatMods = goatClass.getModifiers();
+ int animalMods = animalClass.getModifiers();
+
+ assertTrue(Modifier.isPublic(goatMods));
+ assertTrue(Modifier.isAbstract(animalMods));
+ assertTrue(Modifier.isPublic(animalMods));
+ }
+
+ @Test
+ public void givenClass_whenGetsPackageInfo_thenCorrect() {
+ Goat goat = new Goat("goat");
+ Class> goatClass = goat.getClass();
+ Package pkg = goatClass.getPackage();
+
+ assertEquals("com.baeldung.java.reflection", pkg.getName());
+ }
+
+ @Test
+ public void givenClass_whenGetsSuperClass_thenCorrect() {
+ Goat goat = new Goat("goat");
+ String str = "any string";
+
+ Class> goatClass = goat.getClass();
+ Class> goatSuperClass = goatClass.getSuperclass();
+
+ assertEquals("Animal", goatSuperClass.getSimpleName());
+ assertEquals("Object", str.getClass().getSuperclass().getSimpleName());
+
+ }
+
+ @Test
+ public void givenClass_whenGetsImplementedInterfaces_thenCorrect()
+ throws ClassNotFoundException {
+ Class> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
+ Class> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
+ Class>[] goatInterfaces = goatClass.getInterfaces();
+ Class>[] animalInterfaces = animalClass.getInterfaces();
+
+ assertEquals(1, goatInterfaces.length);
+ assertEquals(1, animalInterfaces.length);
+ assertEquals("Locomotion", goatInterfaces[0].getSimpleName());
+ assertEquals("Eating", animalInterfaces[0].getSimpleName());
+ }
+
+ @Test
+ public void givenClass_whenGetsConstructor_thenCorrect()
+ throws ClassNotFoundException {
+ Class> goatClass = Class.forName("com.baeldung.java.reflection.Goat");
+ Constructor>[] constructors = goatClass.getConstructors();
+
+ assertEquals(1, constructors.length);
+ assertEquals("com.baeldung.java.reflection.Goat", constructors[0].getName());
+ }
+
+ @Test
+ public void givenClass_whenGetsFields_thenCorrect()
+ throws ClassNotFoundException {
+ Class> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
+ Field[] fields = animalClass.getDeclaredFields();
+
+ List actualFields = getFieldNames(fields);
+
+ assertEquals(2, actualFields.size());
+ assertTrue(actualFields.containsAll(Arrays.asList("name", "CATEGORY")));
+ }
+
+ @Test
+ public void givenClass_whenGetsMethods_thenCorrect()
+ throws ClassNotFoundException {
+ Class> animalClass = Class.forName("com.baeldung.java.reflection.Animal");
+ Method[] methods = animalClass.getDeclaredMethods();
+ List actualMethods = getMethodNames(methods);
+
+ assertEquals(4, actualMethods.size());
+ assertTrue(actualMethods.containsAll(Arrays.asList("getName",
+ "setName", "getSound")));
+ }
+
+ @Test
+ public void givenClass_whenGetsAllConstructors_thenCorrect()
+ throws ClassNotFoundException {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Constructor>[] constructors = birdClass.getConstructors();
+
+ assertEquals(3, constructors.length);
+ }
+
+ @Test
+ public void givenClass_whenGetsEachConstructorByParamTypes_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Constructor> cons1 = birdClass.getConstructor();
+ Constructor> cons2 = birdClass.getConstructor(String.class);
+ Constructor> cons3 = birdClass.getConstructor(String.class,
+ boolean.class);
+ }
+
+ @Test
+ public void givenClass_whenInstantiatesObjectsAtRuntime_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+
+ Constructor> cons1 = birdClass.getConstructor();
+ Constructor> cons2 = birdClass.getConstructor(String.class);
+ Constructor> cons3 = birdClass.getConstructor(String.class,
+ boolean.class);
+
+ Bird bird1 = (Bird) cons1.newInstance();
+ Bird bird2 = (Bird) cons2.newInstance("Weaver bird");
+ Bird bird3 = (Bird) cons3.newInstance("dove", true);
+
+ assertEquals("bird", bird1.getName());
+ assertEquals("Weaver bird", bird2.getName());
+ assertEquals("dove", bird3.getName());
+ assertFalse(bird1.walks());
+ assertTrue(bird3.walks());
+ }
+
+ @Test
+ public void givenClass_whenGetsPublicFields_thenCorrect()
+ throws ClassNotFoundException {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Field[] fields = birdClass.getFields();
+ assertEquals(1, fields.length);
+ assertEquals("CATEGORY", fields[0].getName());
+
+ }
+
+ @Test
+ public void givenClass_whenGetsPublicFieldByName_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Field field = birdClass.getField("CATEGORY");
+ assertEquals("CATEGORY", field.getName());
+
+ }
+
+ @Test
+ public void givenClass_whenGetsDeclaredFields_thenCorrect()
+ throws ClassNotFoundException {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Field[] fields = birdClass.getDeclaredFields();
+ assertEquals(1, fields.length);
+ assertEquals("walks", fields[0].getName());
+ }
+
+ @Test
+ public void givenClass_whenGetsFieldsByName_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Field field = birdClass.getDeclaredField("walks");
+ assertEquals("walks", field.getName());
+
+ }
+
+ @Test
+ public void givenClassField_whenGetsType_thenCorrect()
+ throws Exception {
+ Field field = Class.forName("com.baeldung.java.reflection.Bird")
+ .getDeclaredField("walks");
+ Class> fieldClass = field.getType();
+ assertEquals("boolean", fieldClass.getSimpleName());
+ }
+
+ @Test
+ public void givenClassField_whenSetsAndGetsValue_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Bird bird = (Bird) birdClass.newInstance();
+ Field field = birdClass.getDeclaredField("walks");
+ field.setAccessible(true);
+
+ assertFalse(field.getBoolean(bird));
+ assertFalse(bird.walks());
+
+ field.set(bird, true);
+
+ assertTrue(field.getBoolean(bird));
+ assertTrue(bird.walks());
+
+ }
+
+ @Test
+ public void givenClassField_whenGetsAndSetsWithNull_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Field field = birdClass.getField("CATEGORY");
+ field.setAccessible(true);
+
+ assertEquals("domestic", field.get(null));
+ }
+
+ @Test
+ public void givenClass_whenGetsAllPublicMethods_thenCorrect()
+ throws ClassNotFoundException {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Method[] methods = birdClass.getMethods();
+ List methodNames = getMethodNames(methods);
+
+ assertTrue(methodNames.containsAll(Arrays
+ .asList("equals", "notifyAll", "hashCode",
+ "walks", "eats", "toString")));
+
+ }
+
+ @Test
+ public void givenClass_whenGetsOnlyDeclaredMethods_thenCorrect()
+ throws ClassNotFoundException {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ List actualMethodNames = getMethodNames(birdClass.getDeclaredMethods());
+
+ List expectedMethodNames = Arrays.asList("setWalks", "walks", "getSound", "eats");
+
+ assertEquals(expectedMethodNames.size(), actualMethodNames.size());
+ assertTrue(expectedMethodNames.containsAll(actualMethodNames));
+ assertTrue(actualMethodNames.containsAll(expectedMethodNames));
+
+ }
+
+ @Test
+ public void givenMethodName_whenGetsMethod_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Method walksMethod = birdClass.getDeclaredMethod("walks");
+ Method setWalksMethod = birdClass.getDeclaredMethod("setWalks",
+ boolean.class);
+
+ assertFalse(walksMethod.isAccessible());
+ assertFalse(setWalksMethod.isAccessible());
+
+ walksMethod.setAccessible(true);
+ setWalksMethod.setAccessible(true);
+
+ assertTrue(walksMethod.isAccessible());
+ assertTrue(setWalksMethod.isAccessible());
+
+ }
+
+ @Test
+ public void givenMethod_whenInvokes_thenCorrect()
+ throws Exception {
+ Class> birdClass = Class.forName("com.baeldung.java.reflection.Bird");
+ Bird bird = (Bird) birdClass.newInstance();
+ Method setWalksMethod = birdClass.getDeclaredMethod("setWalks",
+ boolean.class);
+ Method walksMethod = birdClass.getDeclaredMethod("walks");
+ boolean walks = (boolean) walksMethod.invoke(bird);
+
+ assertFalse(walks);
+ assertFalse(bird.walks());
+
+ setWalksMethod.invoke(bird, true);
+ boolean walks2 = (boolean) walksMethod.invoke(bird);
+
+ assertTrue(walks2);
+ assertTrue(bird.walks());
+
+ }
+
+ private static List getFieldNames(Field[] fields) {
+ List fieldNames = new ArrayList<>();
+ for (Field field : fields)
+ fieldNames.add(field.getName());
+ return fieldNames;
+
+ }
+
+ private static List getMethodNames(Method[] methods) {
+ List methodNames = new ArrayList<>();
+ for (Method method : methods)
+ methodNames.add(method.getName());
+ return methodNames;
+ }
+
+}
diff --git a/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java b/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java
new file mode 100644
index 0000000000..ad1f2dc70c
--- /dev/null
+++ b/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java
@@ -0,0 +1,44 @@
+package org.baeldung.java.arrays;
+
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ArraysJoinAndSplitJUnitTest {
+
+ private final String[] sauces = {"Marinara", "Olive Oil"};
+ private final String[] cheeses = {"Mozzarella", "Feta", "Parmesan"};
+ private final String[] vegetables = {"Olives", "Spinach", "Green Peppers"};
+
+ private final String[] customers = {"Jay", "Harry", "Ronnie", "Gary", "Ross"};
+
+ @Test
+ public void givenThreeStringArrays_whenJoiningIntoOneStringArray_shouldSucceed() {
+ String[] toppings = new String[sauces.length + cheeses.length + vegetables.length];
+
+ System.arraycopy(sauces, 0, toppings, 0, sauces.length);
+ int AddedSoFar = sauces.length;
+
+ System.arraycopy(cheeses, 0, toppings, AddedSoFar, cheeses.length);
+ AddedSoFar += cheeses.length;
+
+ System.arraycopy(vegetables, 0, toppings, AddedSoFar, vegetables.length);
+
+ Assert.assertArrayEquals(toppings,
+ new String[]{"Marinara", "Olive Oil", "Mozzarella", "Feta",
+ "Parmesan", "Olives", "Spinach", "Green Peppers"});
+ }
+
+
+ @Test
+ public void givenOneStringArray_whenSplittingInHalfTwoStringArrays_shouldSucceed() {
+ int ordersHalved = (customers.length / 2) + (customers.length % 2);
+
+ String[] driverOne = Arrays.copyOf(customers, ordersHalved);
+ String[] driverTwo = Arrays.copyOfRange(customers, ordersHalved, customers.length);
+
+ Assert.assertArrayEquals(driverOne, new String[]{"Jay", "Harry", "Ronnie"});
+ Assert.assertArrayEquals(driverTwo, new String[]{"Gary", "Ross"});
+ }
+}
diff --git a/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java
new file mode 100644
index 0000000000..9cafa179ab
--- /dev/null
+++ b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java
@@ -0,0 +1,146 @@
+package org.baeldung.java.collections;
+
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.*;
+import java.util.stream.*;
+
+import static java.util.stream.Collectors.*;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.*;
+
+public class ArrayListTest {
+
+ private List stringsToSearch;
+
+ @Before
+ public void setUp() {
+ List xs = LongStream.range(0, 16)
+ .boxed()
+ .map(Long::toHexString)
+ .collect(toCollection(ArrayList::new));
+ stringsToSearch = new ArrayList<>(xs);
+ stringsToSearch.addAll(xs);
+ }
+
+ @Test
+ public void givenNewArrayList_whenCheckCapacity_thenDefaultValue() {
+ List xs = new ArrayList<>();
+ assertTrue(xs.isEmpty());
+ }
+
+ @Test
+ public void givenCollection_whenProvideItToArrayListCtor_thenArrayListIsPopulatedWithItsElements() {
+ Collection numbers =
+ IntStream.range(0, 10).boxed().collect(toSet());
+
+ List xs = new ArrayList<>(numbers);
+ assertEquals(10, xs.size());
+ assertTrue(numbers.containsAll(xs));
+ }
+
+ @Test
+ public void givenElement_whenAddToArrayList_thenIsAdded() {
+ List xs = new ArrayList<>();
+
+ xs.add(1L);
+ xs.add(2L);
+ xs.add(1, 3L);
+
+ assertThat(Arrays.asList(1L, 3L, 2L), equalTo(xs));
+ }
+
+ @Test
+ public void givenCollection_whenAddToArrayList_thenIsAdded() {
+ List xs = new ArrayList<>(Arrays.asList(1L, 2L, 3L));
+ LongStream.range(4, 10).boxed()
+ .collect(collectingAndThen(toCollection(ArrayList::new), ys -> xs.addAll(0, ys)));
+
+ assertThat(Arrays.asList(4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L), equalTo(xs));
+ }
+
+ @Test
+ public void givenExistingElement_whenCallIndexOf_thenReturnCorrectIndex() {
+ assertEquals(10, stringsToSearch.indexOf("a"));
+ assertEquals(26, stringsToSearch.lastIndexOf("a"));
+ }
+
+ @Test
+ public void givenCondition_whenIterateArrayList_thenFindAllElementsSatisfyingCondition() {
+ Iterator it = stringsToSearch.iterator();
+ Set matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));
+
+ List result = new ArrayList<>();
+ while (it.hasNext()) {
+ String s = it.next();
+ if (matchingStrings.contains(s)) {
+ result.add(s);
+ }
+ }
+
+ assertEquals(6, result.size());
+ }
+
+ @Test
+ public void givenPredicate_whenIterateArrayList_thenFindAllElementsSatisfyingPredicate() {
+ Set matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));
+
+ List result = stringsToSearch
+ .stream()
+ .filter(matchingStrings::contains)
+ .collect(toCollection(ArrayList::new));
+
+ assertEquals(6, result.size());
+ }
+
+ @Test
+ public void givenSortedArray_whenUseBinarySearch_thenFindElement() {
+ List copy = new ArrayList<>(stringsToSearch);
+ Collections.sort(copy);
+ int index = Collections.binarySearch(copy, "f");
+ assertThat(index, not(equalTo(-1)));
+ }
+
+ @Test
+ public void givenIndex_whenRemove_thenCorrectElementRemoved() {
+ List xs = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new));
+ Collections.reverse(xs);
+
+ xs.remove(0);
+ assertThat(xs.get(0), equalTo(8));
+
+ xs.remove(Integer.valueOf(0));
+ assertFalse(xs.contains(0));
+ }
+
+ @Test
+ public void givenListIterator_whenReverseTraversal_thenRetrieveElementsInOppositeOrder() {
+ List xs = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new));
+ ListIterator it = xs.listIterator(xs.size());
+ List result = new ArrayList<>(xs.size());
+ while (it.hasPrevious()) {
+ result.add(it.previous());
+ }
+
+ Collections.reverse(xs);
+ assertThat(result, equalTo(xs));
+ }
+
+ @Test
+ public void givenCondition_whenIterateArrayList_thenRemoveAllElementsSatisfyingCondition() {
+ Set matchingStrings
+ = Sets.newHashSet("a", "b", "c", "d", "e", "f");
+
+ Iterator it = stringsToSearch.iterator();
+ while (it.hasNext()) {
+ if (matchingStrings.contains(it.next())) {
+ it.remove();
+ }
+ }
+
+ assertEquals(20, stringsToSearch.size());
+ }
+}
diff --git a/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java b/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java
new file mode 100644
index 0000000000..c288cf499d
--- /dev/null
+++ b/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java
@@ -0,0 +1,62 @@
+package org.baeldung.java.collections;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CollectionsJoinAndSplitJUnitTest {
+
+ private ArrayList sauces = new ArrayList<>();
+ private ArrayList cheeses = new ArrayList<>();
+ private ArrayList vegetables = new ArrayList<>();
+
+ private ArrayList> ingredients = new ArrayList<>();
+
+ @Before
+ public void init() {
+ sauces.add("Olive Oil");
+ sauces.add("Marinara");
+
+ cheeses.add("Mozzarella");
+ cheeses.add("Feta");
+ cheeses.add("Parmesan");
+
+ vegetables.add("Olives");
+ vegetables.add("Spinach");
+ vegetables.add("Green Peppers");
+
+ ingredients.add(sauces);
+ ingredients.add(cheeses);
+ ingredients.add(vegetables);
+ }
+
+ @Test
+ public void givenThreeArrayLists_whenJoiningIntoOneArrayList_shouldSucceed() {
+ ArrayList> toppings = new ArrayList<>();
+
+ toppings.add(sauces);
+ toppings.add(cheeses);
+ toppings.add(vegetables);
+
+ Assert.assertTrue(toppings.size() == 3);
+ Assert.assertTrue(toppings.contains(sauces));
+ Assert.assertTrue(toppings.contains(cheeses));
+ Assert.assertTrue(toppings.contains(vegetables));
+ }
+
+ @Test
+ public void givenOneArrayList_whenSplittingIntoTwoArrayLists_shouldSucceed() {
+
+ ArrayList> removedToppings = new ArrayList<>();
+ removedToppings.add(ingredients.remove(ingredients.indexOf(vegetables)));
+
+ Assert.assertTrue(removedToppings.contains(vegetables));
+ Assert.assertTrue(removedToppings.size() == 1);
+ Assert.assertTrue(ingredients.size() == 2);
+ Assert.assertTrue(ingredients.contains(sauces));
+ Assert.assertTrue(ingredients.contains(cheeses));
+ }
+}
diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java
index 55a0904499..1a6ac5f8ce 100644
--- a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java
+++ b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java
@@ -19,6 +19,7 @@ import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardCopyOption;
import java.util.Scanner;
import org.apache.commons.io.FileUtils;
@@ -191,6 +192,16 @@ public class JavaInputStreamToXUnitTest {
IOUtils.closeQuietly(outStream);
}
+ @Test
+ public final void givenUsingPlainJava8_whenConvertingAnInProgressInputStreamToAFile_thenCorrect() throws IOException {
+ final InputStream initialStream = new FileInputStream(new File("src/main/resources/sample.txt"));
+ final File targetFile = new File("src/main/resources/targetFile.tmp");
+
+ java.nio.file.Files.copy(initialStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ IOUtils.closeQuietly(initialStream);
+ }
+
@Test
public final void givenUsingGuava_whenConvertingAnInputStreamToAFile_thenCorrect() throws IOException {
final InputStream initialStream = new FileInputStream(new File("src/main/resources/sample.txt"));
diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java
index 7a4c7366eb..3c574f1e5c 100644
--- a/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java
+++ b/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java
@@ -1,5 +1,8 @@
package org.baeldung.java.io;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
@@ -187,10 +190,24 @@ public class JavaReaderToXUnitTest {
targetStream.close();
}
+ @Test
+ public void givenUsingCommonsIO_whenConvertingReaderIntoInputStream_thenCorrect() throws IOException {
+ String initialString = "With Commons IO";
+ final Reader initialReader = new StringReader(initialString);
+
+ final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader));
+
+ final String finalString = IOUtils.toString(targetStream);
+ assertThat(finalString, equalTo(initialString));
+
+ initialReader.close();
+ targetStream.close();
+ }
+
// tests - Reader to InputStream with encoding
@Test
- public void givenUsingPlainJava_whenConvertingReaderIntoInputStreamWithCharset_thenCorrect() throws IOException {
+ public void givenUsingPlainJava_whenConvertingReaderIntoInputStreamWithCharset() throws IOException {
final Reader initialReader = new StringReader("With Java");
final char[] charBuffer = new char[8 * 1024];
@@ -225,4 +242,17 @@ public class JavaReaderToXUnitTest {
targetStream.close();
}
+ @Test
+ public void givenUsingCommonsIO_whenConvertingReaderIntoInputStreamWithEncoding_thenCorrect() throws IOException {
+ String initialString = "With Commons IO";
+ final Reader initialReader = new StringReader(initialString);
+ final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader), Charsets.UTF_8);
+
+ String finalString = IOUtils.toString(targetStream, Charsets.UTF_8);
+ assertThat(finalString, equalTo(initialString));
+
+ initialReader.close();
+ targetStream.close();
+ }
+
}
diff --git a/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java b/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java
new file mode 100644
index 0000000000..2c330c513d
--- /dev/null
+++ b/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java
@@ -0,0 +1,66 @@
+package org.baeldung.java.shell;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.*;
+import java.util.concurrent.Executors;
+import java.util.function.Consumer;
+
+public class JavaProcessUnitTest {
+ private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows");
+
+ private static class StreamGobbler implements Runnable {
+ private InputStream inputStream;
+ private Consumer consumer;
+
+ public StreamGobbler(InputStream inputStream, Consumer consumer) {
+ this.inputStream = inputStream;
+ this.consumer = consumer;
+ }
+
+ @Override
+ public void run() {
+ new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
+ }
+ }
+
+ private Consumer consumer = new Consumer() {
+ @Override
+ public void accept(String s) {
+ Assert.assertNotNull(s);
+ }
+ };
+
+ private String homeDirectory = System.getProperty("user.home");
+
+ @Test
+ public void givenProcess_whenCreatingViaRuntime_shouldSucceed() throws Exception {
+ Process process;
+ if (IS_WINDOWS) {
+ process = Runtime.getRuntime().exec(String.format("cmd.exe /c dir %s", homeDirectory));
+ } else {
+ process = Runtime.getRuntime().exec(String.format("sh -c ls %s", homeDirectory));
+ }
+ StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
+ Executors.newSingleThreadExecutor().submit(streamGobbler);
+ int exitCode = process.waitFor();
+ Assert.assertEquals(0, exitCode);
+ }
+
+ @Test
+ public void givenProcess_whenCreatingViaProcessBuilder_shouldSucceed() throws Exception {
+ ProcessBuilder builder = new ProcessBuilder();
+ if (IS_WINDOWS) {
+ builder.command("cmd.exe", "/c", "dir");
+ } else {
+ builder.command("sh", "-c", "ls");
+ }
+ builder.directory(new File(homeDirectory));
+ Process process = builder.start();
+ StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
+ Executors.newSingleThreadExecutor().submit(streamGobbler);
+ int exitCode = process.waitFor();
+ Assert.assertEquals(0, exitCode);
+ }
+}
diff --git a/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.jar b/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..5fd4d5023f
Binary files /dev/null and b/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.properties b/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..eb91947648
--- /dev/null
+++ b/couchbase-sdk-async/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
\ No newline at end of file
diff --git a/couchbase-sdk-async/.springBeans b/couchbase-sdk-async/.springBeans
new file mode 100644
index 0000000000..ff32b84d3b
--- /dev/null
+++ b/couchbase-sdk-async/.springBeans
@@ -0,0 +1,15 @@
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/couchbase-sdk-async/mvnw b/couchbase-sdk-async/mvnw
new file mode 100755
index 0000000000..a1ba1bf554
--- /dev/null
+++ b/couchbase-sdk-async/mvnw
@@ -0,0 +1,233 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ #
+ # Look for the Apple JDKs first to preserve the existing behaviour, and then look
+ # for the new JDKs provided by Oracle.
+ #
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
+ #
+ # Oracle JDKs
+ #
+ export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
+ fi
+
+ if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
+ #
+ # Apple JDKs
+ #
+ export JAVA_HOME=`/usr/libexec/java_home`
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ local basedir=$(pwd)
+ local wdir=$(pwd)
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ wdir=$(cd "$wdir/.."; pwd)
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} "$@"
diff --git a/couchbase-sdk-async/mvnw.cmd b/couchbase-sdk-async/mvnw.cmd
new file mode 100644
index 0000000000..2b934e89dd
--- /dev/null
+++ b/couchbase-sdk-async/mvnw.cmd
@@ -0,0 +1,145 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+set MAVEN_CMD_LINE_ARGS=%*
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
\ No newline at end of file
diff --git a/couchbase-sdk-async/pom.xml b/couchbase-sdk-async/pom.xml
new file mode 100644
index 0000000000..9062ef8e15
--- /dev/null
+++ b/couchbase-sdk-async/pom.xml
@@ -0,0 +1,102 @@
+
+
+ 4.0.0
+ com.baeldung
+ couchbase-sdk-async
+ 0.1-SNAPSHOT
+ jar
+ couchbase-sdk-async
+ Couchbase SDK Asynchronous Operations
+
+
+
+
+ com.couchbase.client
+ java-client
+ ${couchbase.client.version}
+
+
+
+
+ org.springframework
+ spring-context
+ ${spring-framework.version}
+
+
+ org.springframework
+ spring-context-support
+ ${spring-framework.version}
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${org.slf4j.version}
+ compile
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+ org.slf4j
+ jcl-over-slf4j
+ ${org.slf4j.version}
+
+
+ org.slf4j
+ log4j-over-slf4j
+ ${org.slf4j.version}
+
+
+
+
+ org.springframework
+ spring-test
+ ${spring-framework.version}
+ test
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+ test
+
+
+
+
+
+
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.7
+
+
+
+
+
+
+ 1.7
+ UTF-8
+ 2.2.6
+ 4.2.4.RELEASE
+ 1.1.3
+ 1.7.12
+ 4.11
+ 3.4
+
+
+
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/Person.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/Person.java
new file mode 100644
index 0000000000..bf248c3999
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/Person.java
@@ -0,0 +1,89 @@
+package com.baeldung.couchbase.person;
+
+import com.baeldung.couchbase.service.CouchbaseEntity;
+
+public class Person implements CouchbaseEntity {
+
+ private String id;
+ private String type;
+ private String name;
+ private String homeTown;
+
+ Person() {}
+
+ public Person(Builder b) {
+ this.id = b.id;
+ this.type = b.type;
+ this.name = b.name;
+ this.homeTown = b.homeTown;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getHomeTown() {
+ return homeTown;
+ }
+
+ public void setHomeTown(String homeTown) {
+ this.homeTown = homeTown;
+ }
+
+ public static class Builder {
+ private String id;
+ private String type;
+ private String name;
+ private String homeTown;
+
+ public static Builder newInstance() {
+ return new Builder();
+ }
+
+ public Person build() {
+ return new Person(this);
+ }
+
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public Builder type(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public Builder homeTown(String homeTown) {
+ this.homeTown = homeTown;
+ return this;
+ }
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonCrudService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonCrudService.java
new file mode 100644
index 0000000000..d5302bd6db
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonCrudService.java
@@ -0,0 +1,26 @@
+package com.baeldung.couchbase.person;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.couchbase.service.AbstractCrudService;
+import com.baeldung.couchbase.service.BucketService;
+
+@Service
+public class PersonCrudService extends AbstractCrudService {
+
+ @Autowired
+ public PersonCrudService(
+ @Qualifier("TutorialBucketService") BucketService bucketService,
+ PersonDocumentConverter converter) {
+ super(bucketService, converter);
+ }
+
+ @PostConstruct
+ private void init() {
+ loadBucket();
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonDocumentConverter.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonDocumentConverter.java
new file mode 100644
index 0000000000..cfb20a2bfb
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/PersonDocumentConverter.java
@@ -0,0 +1,31 @@
+package com.baeldung.couchbase.person;
+
+import org.springframework.stereotype.Service;
+
+import com.baeldung.couchbase.service.JsonDocumentConverter;
+import com.couchbase.client.java.document.JsonDocument;
+import com.couchbase.client.java.document.json.JsonObject;
+
+@Service
+public class PersonDocumentConverter implements JsonDocumentConverter {
+
+ @Override
+ public JsonDocument toDocument(Person p) {
+ JsonObject content = JsonObject.empty()
+ .put("type", "Person")
+ .put("name", p.getName())
+ .put("homeTown", p.getHomeTown());
+ return JsonDocument.create(p.getId(), content);
+ }
+
+ @Override
+ public Person fromDocument(JsonDocument doc) {
+ JsonObject content = doc.content();
+ Person p = new Person();
+ p.setId(doc.id());
+ p.setType("Person");
+ p.setName(content.getString("name"));
+ p.setHomeTown(content.getString("homeTown"));
+ return p;
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/RegistrationService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/RegistrationService.java
new file mode 100644
index 0000000000..53af1c4041
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/person/RegistrationService.java
@@ -0,0 +1,29 @@
+package com.baeldung.couchbase.person;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.couchbase.client.core.CouchbaseException;
+
+@Service
+public class RegistrationService {
+
+ @Autowired
+ private PersonCrudService crud;
+
+ public void registerNewPerson(String name, String homeTown) {
+ Person person = new Person();
+ person.setName(name);
+ person.setHomeTown(homeTown);
+ crud.create(person);
+ }
+
+ public Person findRegistrant(String id) {
+ try{
+ return crud.read(id);
+ }
+ catch(CouchbaseException e) {
+ return crud.readFromReplica(id);
+ }
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractBucketService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractBucketService.java
new file mode 100644
index 0000000000..08acf5deed
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractBucketService.java
@@ -0,0 +1,27 @@
+package com.baeldung.couchbase.service;
+
+import com.couchbase.client.java.Bucket;
+
+public abstract class AbstractBucketService implements BucketService {
+
+ private ClusterService clusterService;
+
+ private Bucket bucket;
+
+ protected void openBucket() {
+ bucket = clusterService.openBucket(getBucketName(), getBucketPassword());
+ }
+
+ protected abstract String getBucketName();
+
+ protected abstract String getBucketPassword();
+
+ public AbstractBucketService(ClusterService clusterService) {
+ this.clusterService = clusterService;
+ }
+
+ @Override
+ public Bucket getBucket() {
+ return bucket;
+ }
+ }
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractCrudService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractCrudService.java
new file mode 100644
index 0000000000..ce95074015
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/AbstractCrudService.java
@@ -0,0 +1,174 @@
+package com.baeldung.couchbase.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.couchbase.client.core.BackpressureException;
+import com.couchbase.client.core.time.Delay;
+import com.couchbase.client.java.AsyncBucket;
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.ReplicaMode;
+import com.couchbase.client.java.document.JsonDocument;
+import com.couchbase.client.java.util.retry.RetryBuilder;
+
+import rx.Observable;
+import rx.functions.Action1;
+import rx.functions.Func1;
+
+public abstract class AbstractCrudService implements CrudService {
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractCrudService.class);
+
+ private BucketService bucketService;
+ private Bucket bucket;
+ private JsonDocumentConverter converter;
+
+ public AbstractCrudService(BucketService bucketService, JsonDocumentConverter converter) {
+ this.bucketService = bucketService;
+ this.converter = converter;
+ }
+
+ protected void loadBucket() {
+ bucket = bucketService.getBucket();
+ }
+
+ @Override
+ public void create(T t) {
+ if(t.getId() == null) {
+ t.setId(UUID.randomUUID().toString());
+ }
+ JsonDocument doc = converter.toDocument(t);
+ bucket.insert(doc);
+ }
+
+ @Override
+ public T read(String id) {
+ JsonDocument doc = bucket.get(id);
+ return (doc == null ? null : converter.fromDocument(doc));
+ }
+
+ @Override
+ public T readFromReplica(String id) {
+ List docs = bucket.getFromReplica(id, ReplicaMode.FIRST);
+ return (docs.isEmpty() ? null : converter.fromDocument(docs.get(0)));
+ }
+
+ @Override
+ public void update(T t) {
+ JsonDocument doc = converter.toDocument(t);
+ bucket.upsert(doc);
+ }
+
+ @Override
+ public void delete(String id) {
+ bucket.remove(id);
+ }
+
+ @Override
+ public List readBulk(Iterable ids) {
+ final AsyncBucket asyncBucket = bucket.async();
+ Observable asyncOperation = Observable
+ .from(ids)
+ .flatMap(new Func1>() {
+ public Observable call(String key) {
+ return asyncBucket.get(key);
+ }
+ });
+
+ final List items = new ArrayList();
+ try {
+ asyncOperation.toBlocking()
+ .forEach(new Action1() {
+ public void call(JsonDocument doc) {
+ T item = converter.fromDocument(doc);
+ items.add(item);
+ }
+ });
+ } catch (Exception e) {
+ logger.error("Error during bulk get", e);
+ }
+
+ return items;
+ }
+
+ @Override
+ public void createBulk(Iterable items) {
+ final AsyncBucket asyncBucket = bucket.async();
+ Observable
+ .from(items)
+ .flatMap(new Func1>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Observable call(final T t) {
+ if(t.getId() == null) {
+ t.setId(UUID.randomUUID().toString());
+ }
+ JsonDocument doc = converter.toDocument(t);
+ return asyncBucket.insert(doc)
+ .retryWhen(RetryBuilder
+ .anyOf(BackpressureException.class)
+ .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100))
+ .max(10)
+ .build());
+ }
+ })
+ .last()
+ .toBlocking()
+ .single();
+ }
+
+ @Override
+ public void updateBulk(Iterable items) {
+ final AsyncBucket asyncBucket = bucket.async();
+ Observable
+ .from(items)
+ .flatMap(new Func1>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Observable call(final T t) {
+ JsonDocument doc = converter.toDocument(t);
+ return asyncBucket.upsert(doc)
+ .retryWhen(RetryBuilder
+ .anyOf(BackpressureException.class)
+ .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100))
+ .max(10)
+ .build());
+ }
+ })
+ .last()
+ .toBlocking()
+ .single();
+ }
+
+ @Override
+ public void deleteBulk(Iterable ids) {
+ final AsyncBucket asyncBucket = bucket.async();
+ Observable
+ .from(ids)
+ .flatMap(new Func1>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public Observable call(String key) {
+ return asyncBucket.remove(key)
+ .retryWhen(RetryBuilder
+ .anyOf(BackpressureException.class)
+ .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100))
+ .max(10)
+ .build());
+ }
+ })
+ .last()
+ .toBlocking()
+ .single();
+ }
+
+ @Override
+ public boolean exists(String id) {
+ return bucket.exists(id);
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/BucketService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/BucketService.java
new file mode 100644
index 0000000000..df9156d87d
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/BucketService.java
@@ -0,0 +1,8 @@
+package com.baeldung.couchbase.service;
+
+import com.couchbase.client.java.Bucket;
+
+public interface BucketService {
+
+ Bucket getBucket();
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterService.java
new file mode 100644
index 0000000000..437ec00ff4
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterService.java
@@ -0,0 +1,8 @@
+package com.baeldung.couchbase.service;
+
+import com.couchbase.client.java.Bucket;
+
+public interface ClusterService {
+
+ Bucket openBucket(String name, String password);
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterServiceImpl.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterServiceImpl.java
new file mode 100644
index 0000000000..c8ff56269d
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/ClusterServiceImpl.java
@@ -0,0 +1,36 @@
+package com.baeldung.couchbase.service;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.stereotype.Service;
+
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.Cluster;
+import com.couchbase.client.java.CouchbaseCluster;
+import com.couchbase.client.java.env.CouchbaseEnvironment;
+import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
+
+@Service
+public class ClusterServiceImpl implements ClusterService {
+
+ private Cluster cluster;
+ private Map buckets = new ConcurrentHashMap<>();
+
+ @PostConstruct
+ private void init() {
+ CouchbaseEnvironment env = DefaultCouchbaseEnvironment.create();
+ cluster = CouchbaseCluster.create(env, "localhost");
+ }
+
+ @Override
+ synchronized public Bucket openBucket(String name, String password) {
+ if(!buckets.containsKey(name)) {
+ Bucket bucket = cluster.openBucket(name, password);
+ buckets.put(name, bucket);
+ }
+ return buckets.get(name);
+ }
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CouchbaseEntity.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CouchbaseEntity.java
new file mode 100644
index 0000000000..4d2500197b
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CouchbaseEntity.java
@@ -0,0 +1,9 @@
+package com.baeldung.couchbase.service;
+
+public interface CouchbaseEntity {
+
+ String getId();
+
+ void setId(String id);
+
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CrudService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CrudService.java
new file mode 100644
index 0000000000..e0f0831abb
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/CrudService.java
@@ -0,0 +1,26 @@
+package com.baeldung.couchbase.service;
+
+import java.util.List;
+
+public interface CrudService {
+
+ void create(T t);
+
+ T read(String id);
+
+ T readFromReplica(String id);
+
+ void update(T t);
+
+ void delete(String id);
+
+ List readBulk(Iterable ids);
+
+ void createBulk(Iterable items);
+
+ void updateBulk(Iterable items);
+
+ void deleteBulk(Iterable ids);
+
+ boolean exists(String id);
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/JsonDocumentConverter.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/JsonDocumentConverter.java
new file mode 100644
index 0000000000..87331d2a17
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/JsonDocumentConverter.java
@@ -0,0 +1,10 @@
+package com.baeldung.couchbase.service;
+
+import com.couchbase.client.java.document.JsonDocument;
+
+public interface JsonDocumentConverter {
+
+ JsonDocument toDocument(T t);
+
+ T fromDocument(JsonDocument doc);
+}
diff --git a/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/TutorialBucketService.java b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/TutorialBucketService.java
new file mode 100644
index 0000000000..2e40321272
--- /dev/null
+++ b/couchbase-sdk-async/src/main/java/com/baeldung/couchbase/service/TutorialBucketService.java
@@ -0,0 +1,32 @@
+package com.baeldung.couchbase.service;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+@Qualifier("TutorialBucketService")
+public class TutorialBucketService extends AbstractBucketService {
+
+ @PostConstruct
+ void init() {
+ openBucket();
+ }
+
+ @Autowired
+ public TutorialBucketService(ClusterService clusterService) {
+ super(clusterService);
+ }
+
+ @Override
+ protected String getBucketName() {
+ return "baeldung-tutorial";
+ }
+
+ @Override
+ protected String getBucketPassword() {
+ return "";
+ }
+}
diff --git a/couchbase-sdk-async/src/main/resources/application.properties b/couchbase-sdk-async/src/main/resources/application.properties
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/couchbase-sdk-async/src/main/resources/logback.xml b/couchbase-sdk-async/src/main/resources/logback.xml
new file mode 100644
index 0000000000..efcc6fb4c7
--- /dev/null
+++ b/couchbase-sdk-async/src/main/resources/logback.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTest.java b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTest.java
new file mode 100644
index 0000000000..d1cc807f7a
--- /dev/null
+++ b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTest.java
@@ -0,0 +1,13 @@
+package com.baeldung.couchbase;
+
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { IntegrationTestConfig.class })
+@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class })
+public abstract class IntegrationTest {
+}
diff --git a/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTestConfig.java b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTestConfig.java
new file mode 100644
index 0000000000..d593aac52d
--- /dev/null
+++ b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/IntegrationTestConfig.java
@@ -0,0 +1,9 @@
+package com.baeldung.couchbase;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages={"com.baeldung.couchbase"})
+public class IntegrationTestConfig {
+}
diff --git a/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/person/PersonCrudServiceTest.java b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/person/PersonCrudServiceTest.java
new file mode 100644
index 0000000000..3da282492c
--- /dev/null
+++ b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/person/PersonCrudServiceTest.java
@@ -0,0 +1,220 @@
+package com.baeldung.couchbase.person;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import com.baeldung.couchbase.IntegrationTest;
+import com.baeldung.couchbase.service.BucketService;
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.document.JsonDocument;
+
+public class PersonCrudServiceTest extends IntegrationTest {
+
+ @Autowired
+ private PersonCrudService personService;
+
+ @Autowired
+ @Qualifier("TutorialBucketService")
+ private BucketService bucketService;
+
+ @Autowired
+ private PersonDocumentConverter converter;
+
+ private Bucket bucket;
+
+ @PostConstruct
+ private void init() {
+ bucket = bucketService.getBucket();
+ }
+
+ @Test
+ public final void givenRandomPerson_whenCreate_thenPersonPersisted() {
+ //create person
+ Person person = randomPerson();
+ personService.create(person);
+
+ //check results
+ assertNotNull(person.getId());
+ assertNotNull(bucket.get(person.getId()));
+
+ //cleanup
+ bucket.remove(person.getId());
+ }
+
+ @Test
+ public final void givenId_whenRead_thenReturnsPerson() {
+ //create and insert person document
+ String id = insertRandomPersonDocument().id();
+
+ //read person and check results
+ assertNotNull(personService.read(id));
+
+ //cleanup
+ bucket.remove(id);
+ }
+
+ @Test
+ public final void givenNewHometown_whenUpdate_thenNewHometownPersisted() {
+ //create and insert person document
+ JsonDocument doc = insertRandomPersonDocument();
+
+ //update person
+ Person expected = converter.fromDocument(doc);
+ String updatedHomeTown = RandomStringUtils.randomAlphabetic(12);
+ expected.setHomeTown(updatedHomeTown);
+ personService.update(expected);
+
+ //check results
+ JsonDocument actual = bucket.get(expected.getId());
+ assertNotNull(actual);
+ assertNotNull(actual.content());
+ assertEquals(expected.getHomeTown(), actual.content().getString("homeTown"));
+
+ //cleanup
+ bucket.remove(expected.getId());
+ }
+
+ @Test
+ public final void givenRandomPerson_whenDelete_thenPersonNotInBucket() {
+ //create and insert person document
+ String id = insertRandomPersonDocument().id();
+
+ //delete person and check results
+ personService.delete(id);
+ assertNull(bucket.get(id));
+ }
+
+ @Test
+ public final void givenIds_whenReadBulk_thenReturnsOnlyPersonsWithMatchingIds() {
+ List ids = new ArrayList<>();
+
+ //add some person documents
+ for(int i=0; i<5; i++) {
+ ids.add(insertRandomPersonDocument().id());
+ }
+
+ //perform bulk read
+ List persons = personService.readBulk(ids);
+
+ //check results
+ for(Person person : persons) {
+ assertTrue(ids.contains(person.getId()));
+ }
+
+ //cleanup
+ for(String id : ids) {
+ bucket.remove(id);
+ }
+ }
+
+ @Test
+ public final void givenPersons_whenInsertBulk_thenPersonsAreInserted() {
+
+ //create some persons
+ List persons = new ArrayList<>();
+ for(int i=0; i<5; i++) {
+ persons.add(randomPerson());
+ }
+
+ //perform bulk insert
+ personService.createBulk(persons);
+
+ //check results
+ for(Person person : persons) {
+ assertNotNull(bucket.get(person.getId()));
+ }
+
+ //cleanup
+ for(Person person : persons) {
+ bucket.remove(person.getId());
+ }
+ }
+
+ @Test
+ public final void givenPersons_whenUpdateBulk_thenPersonsAreUpdated() {
+
+ List ids = new ArrayList<>();
+
+ //add some person documents
+ for(int i=0; i<5; i++) {
+ ids.add(insertRandomPersonDocument().id());
+ }
+
+ //load persons from Couchbase
+ List persons = new ArrayList<>();
+ for(String id : ids) {
+ persons.add(converter.fromDocument(bucket.get(id)));
+ }
+
+ //modify persons
+ for(Person person : persons) {
+ person.setHomeTown(RandomStringUtils.randomAlphabetic(10));
+ }
+
+ //perform bulk update
+ personService.updateBulk(persons);
+
+ //check results
+ for(Person person : persons) {
+ JsonDocument doc = bucket.get(person.getId());
+ assertEquals(person.getName(), doc.content().getString("name"));
+ assertEquals(person.getHomeTown(), doc.content().getString("homeTown"));
+ }
+
+ //cleanup
+ for(String id : ids) {
+ bucket.remove(id);
+ }
+ }
+
+ @Test
+ public void givenIds_whenDeleteBulk_thenPersonsAreDeleted() {
+
+ List ids = new ArrayList<>();
+
+ //add some person documents
+ for(int i=0; i<5; i++) {
+ ids.add(insertRandomPersonDocument().id());
+ }
+
+ //perform bulk delete
+ personService.deleteBulk(ids);
+
+ //check results
+ for(String id : ids) {
+ assertNull(bucket.get(id));
+ }
+
+ }
+
+ private JsonDocument insertRandomPersonDocument() {
+ Person expected = randomPersonWithId();
+ JsonDocument doc = converter.toDocument(expected);
+ return bucket.insert(doc);
+ }
+
+ private Person randomPerson() {
+ return Person.Builder.newInstance()
+ .name(RandomStringUtils.randomAlphabetic(10))
+ .homeTown(RandomStringUtils.randomAlphabetic(10))
+ .build();
+ }
+
+ private Person randomPersonWithId() {
+ return Person.Builder.newInstance()
+ .id(UUID.randomUUID().toString())
+ .name(RandomStringUtils.randomAlphabetic(10))
+ .homeTown(RandomStringUtils.randomAlphabetic(10))
+ .build();
+ }
+}
diff --git a/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/service/ClusterServiceTest.java b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/service/ClusterServiceTest.java
new file mode 100644
index 0000000000..7795f41c93
--- /dev/null
+++ b/couchbase-sdk-async/src/test/java/com/baeldung/couchbase/service/ClusterServiceTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.couchbase.service;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+import com.baeldung.couchbase.IntegrationTest;
+import com.baeldung.couchbase.IntegrationTestConfig;
+import com.couchbase.client.java.Bucket;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { IntegrationTestConfig.class })
+@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class })
+public class ClusterServiceTest extends IntegrationTest {
+
+ @Autowired
+ private ClusterService couchbaseService;
+
+ private Bucket defaultBucket;
+
+ @Test
+ public void whenOpenBucket_thenBucketIsNotNull() throws Exception {
+ defaultBucket = couchbaseService.openBucket("default", "");
+ assertNotNull(defaultBucket);
+ assertFalse(defaultBucket.isClosed());
+ defaultBucket.close();
+ }
+}
diff --git a/deltaspike/.gitignore b/deltaspike/.gitignore
new file mode 100644
index 0000000000..aa121e866e
--- /dev/null
+++ b/deltaspike/.gitignore
@@ -0,0 +1,3 @@
+/.idea
+baeldung-jee7-seed.iml
+/target
diff --git a/deltaspike/pom.xml b/deltaspike/pom.xml
new file mode 100644
index 0000000000..22cf8f935c
--- /dev/null
+++ b/deltaspike/pom.xml
@@ -0,0 +1,301 @@
+
+
+ 4.0.0
+ com.baeldung
+ deltaspike
+ 1.0
+ war
+ deltaspike
+ A starter Java EE 7 webapp which uses DeltaSpike
+
+ http://wildfly.org
+
+
+ Apache License, Version 2.0
+ repo
+ http://www.apache.org/licenses/LICENSE-2.0.html
+
+
+
+
+
+
+ UTF-8
+
+
+ 1.0.2.Final
+
+
+ 8.2.1.Final
+
+
+ 3.1
+ 2.16
+ 2.5
+
+
+ 1.7
+ 1.7
+
+
+
+
+
+
+
+ org.wildfly.bom
+ jboss-javaee-7.0-with-tools
+ ${version.jboss.bom}
+ pom
+ import
+
+
+ org.wildfly.bom
+ jboss-javaee-7.0-with-hibernate
+ ${version.jboss.bom}
+ pom
+ import
+
+
+
+
+
+
+
+
+
+
+ javax.enterprise
+ cdi-api
+ provided
+
+
+
+
+ org.jboss.spec.javax.annotation
+ jboss-annotations-api_1.2_spec
+ provided
+
+
+
+
+ org.jboss.resteasy
+ jaxrs-api
+ provided
+
+
+
+
+ org.hibernate.javax.persistence
+ hibernate-jpa-2.1-api
+ provided
+
+
+
+
+ org.jboss.spec.javax.ejb
+ jboss-ejb-api_3.2_spec
+ provided
+
+
+
+
+
+
+ org.hibernate
+ hibernate-validator
+ provided
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+
+
+ org.jboss.spec.javax.faces
+ jboss-jsf-api_2.2_spec
+ provided
+
+
+
+
+
+
+ org.hibernate
+ hibernate-jpamodelgen
+ provided
+
+
+
+
+ org.hibernate
+ hibernate-validator-annotation-processor
+ provided
+
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+ org.jboss.arquillian.junit
+ arquillian-junit-container
+ test
+
+
+
+ org.jboss.arquillian.protocol
+ arquillian-protocol-servlet
+ test
+
+
+
+ org.jboss.shrinkwrap.resolver
+ shrinkwrap-resolver-impl-maven
+ test
+
+
+
+ org.apache.deltaspike.modules
+ deltaspike-data-module-api
+ 1.7.1
+ compile
+
+
+
+ org.apache.deltaspike.modules
+ deltaspike-data-module-impl
+ 1.7.1
+ runtime
+
+
+
+
+ com.mysema.querydsl
+ querydsl-apt
+ 3.7.4
+ provided
+
+
+
+ com.mysema.querydsl
+ querydsl-jpa
+ 3.7.4
+
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.6.1
+
+
+
+
+
+ ${project.artifactId}
+
+
+ maven-war-plugin
+ ${version.war.plugin}
+
+
+ false
+
+
+
+ com.mysema.maven
+ apt-maven-plugin
+ 1.0.9
+
+
+
+ process
+
+
+ target/generated-sources/java
+ com.mysema.query.apt.jpa.JPAAnnotationProcessor
+
+
+
+
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+ ${version.wildfly.maven.plugin}
+
+
+
+
+
+
+
+
+ default
+
+ true
+
+
+
+
+ maven-surefire-plugin
+ ${version.surefire.plugin}
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+ arq-wildfly-managed
+
+
+ org.wildfly
+ wildfly-arquillian-container-managed
+ test
+
+
+
+
+
diff --git a/deltaspike/src/main/java/baeldung/controller/MemberController.java b/deltaspike/src/main/java/baeldung/controller/MemberController.java
new file mode 100644
index 0000000000..7a9e9800f4
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/controller/MemberController.java
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.controller;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.inject.Model;
+import javax.enterprise.inject.Produces;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import baeldung.model.Member;
+import baeldung.service.MemberRegistration;
+
+// The @Model stereotype is a convenience mechanism to make this a request-scoped bean that has an
+// EL name
+// Read more about the @Model stereotype in this FAQ:
+// http://www.cdi-spec.org/faq/#accordion6
+@Model
+public class MemberController {
+
+ @Inject
+ private FacesContext facesContext;
+
+ @Inject
+ private MemberRegistration memberRegistration;
+
+ @Produces
+ @Named
+ private Member newMember;
+
+ @PostConstruct
+ public void initNewMember() {
+ newMember = new Member();
+ }
+
+ public void register() throws Exception {
+ try {
+ memberRegistration.register(newMember);
+ FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Registered!", "Registration successful");
+ facesContext.addMessage(null, m);
+ initNewMember();
+ } catch (Exception e) {
+ String errorMessage = getRootErrorMessage(e);
+ FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Registration unsuccessful");
+ facesContext.addMessage(null, m);
+ }
+ }
+
+ private String getRootErrorMessage(Exception e) {
+ // Default to general error message that registration failed.
+ String errorMessage = "Registration failed. See server log for more information";
+ if (e == null) {
+ // This shouldn't happen, but return the default messages
+ return errorMessage;
+ }
+
+ // Start with the exception and recurse to find the root cause
+ Throwable t = e;
+ while (t != null) {
+ // Get the message from the Throwable class instance
+ errorMessage = t.getLocalizedMessage();
+ t = t.getCause();
+ }
+ // This is the root cause message
+ return errorMessage;
+ }
+
+}
diff --git a/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java b/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java
new file mode 100644
index 0000000000..9189dbba74
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java
@@ -0,0 +1,29 @@
+package baeldung.data;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.Disposes;
+import javax.enterprise.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnit;
+
+@ApplicationScoped
+public class EntityManagerProducer {
+ @PersistenceUnit(unitName = "primary")
+ private EntityManagerFactory entityManagerFactory;
+
+ @Produces
+ @Default
+ @RequestScoped
+ public EntityManager create() {
+ return this.entityManagerFactory.createEntityManager();
+ }
+
+ public void dispose(@Disposes @Default EntityManager entityManager) {
+ if (entityManager.isOpen()) {
+ entityManager.close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/deltaspike/src/main/java/baeldung/data/MemberListProducer.java b/deltaspike/src/main/java/baeldung/data/MemberListProducer.java
new file mode 100644
index 0000000000..c1f5fda31d
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/MemberListProducer.java
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.data;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.event.Reception;
+import javax.enterprise.inject.Produces;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.List;
+
+import baeldung.model.Member;
+
+@RequestScoped
+public class MemberListProducer {
+
+ @Inject
+ private MemberRepository memberRepository;
+
+ private List members;
+
+ // @Named provides access the return value via the EL variable name "members" in the UI (e.g.
+ // Facelets or JSP view)
+ @Produces
+ @Named
+ public List getMembers() {
+ return members;
+ }
+
+ public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final Member member) {
+ retrieveAllMembersOrderedByName();
+ }
+
+ @PostConstruct
+ public void retrieveAllMembersOrderedByName() {
+ members = memberRepository.findAllOrderedByNameWithQueryDSL();
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/data/MemberRepository.java b/deltaspike/src/main/java/baeldung/data/MemberRepository.java
new file mode 100644
index 0000000000..56a4a4e634
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/MemberRepository.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.data;
+
+import baeldung.model.Member;
+import baeldung.model.QMember;
+import org.apache.deltaspike.data.api.*;
+
+import java.util.List;
+
+@Repository
+@EntityManagerConfig(entityManagerResolver = SecondaryEntityManagerResolver.class)
+public abstract class MemberRepository extends AbstractEntityRepository implements QueryDslSupport {
+
+ public abstract Member findById(Long id);
+
+ public abstract Member findByEmail(String email);
+
+ @Query("from Member m order by m.name")
+ public abstract List findAllOrderedByName();
+
+ public List findAllOrderedByNameWithQueryDSL() {
+ final QMember member = QMember.member;
+ return jpaQuery()
+ .from(member)
+ .orderBy(member.email.asc())
+ .list(member);
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java b/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java
new file mode 100644
index 0000000000..8cb00958ab
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java
@@ -0,0 +1,18 @@
+package baeldung.data;
+
+import com.mysema.query.jpa.impl.JPAQuery;
+import org.apache.deltaspike.data.spi.DelegateQueryHandler;
+import org.apache.deltaspike.data.spi.QueryInvocationContext;
+
+import javax.inject.Inject;
+
+public class QueryDslRepositoryExtension implements QueryDslSupport, DelegateQueryHandler {
+
+ @Inject
+ private QueryInvocationContext context;
+
+ @Override
+ public JPAQuery jpaQuery() {
+ return new JPAQuery(context.getEntityManager());
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java b/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java
new file mode 100644
index 0000000000..72c33cf1b6
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java
@@ -0,0 +1,7 @@
+package baeldung.data;
+
+import com.mysema.query.jpa.impl.JPAQuery;
+
+public interface QueryDslSupport {
+ JPAQuery jpaQuery();
+}
diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java
new file mode 100644
index 0000000000..41d30d9018
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java
@@ -0,0 +1,30 @@
+package baeldung.data;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.Disposes;
+import javax.enterprise.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnit;
+
+@ApplicationScoped
+public class SecondaryEntityManagerProducer {
+ @PersistenceUnit(unitName = "secondary")
+ private EntityManagerFactory entityManagerFactory;
+
+ @Produces
+ @Default
+ @RequestScoped
+ @SecondaryPersistenceUnit
+ public EntityManager create() {
+ return this.entityManagerFactory.createEntityManager();
+ }
+
+ public void dispose(@Disposes @Default EntityManager entityManager) {
+ if (entityManager.isOpen()) {
+ entityManager.close();
+ }
+ }
+}
\ No newline at end of file
diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java
new file mode 100644
index 0000000000..7faaa1ac49
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java
@@ -0,0 +1,18 @@
+package baeldung.data;
+
+import org.apache.deltaspike.data.api.EntityManagerResolver;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+public class SecondaryEntityManagerResolver implements EntityManagerResolver {
+
+ @Inject
+ @SecondaryPersistenceUnit
+ private EntityManager entityManager;
+
+ @Override
+ public EntityManager resolveEntityManager() {
+ return entityManager;
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java b/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java
new file mode 100644
index 0000000000..e60d0aff05
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java
@@ -0,0 +1,12 @@
+package baeldung.data;
+
+import javax.inject.Qualifier;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface SecondaryPersistenceUnit {
+}
diff --git a/deltaspike/src/main/java/baeldung/model/Member.java b/deltaspike/src/main/java/baeldung/model/Member.java
new file mode 100644
index 0000000000..e178dcf63a
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/model/Member.java
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import javax.validation.constraints.Digits;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotEmpty;
+
+@SuppressWarnings("serial")
+@Entity
+@XmlRootElement
+@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))
+public class Member implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ @NotNull
+ @Size(min = 1, max = 25)
+ @Pattern(regexp = "[^0-9]*", message = "Must not contain numbers")
+ private String name;
+
+ @NotNull
+ @NotEmpty
+ @Email
+ private String email;
+
+ @NotNull
+ @Size(min = 10, max = 12)
+ @Digits(fraction = 0, integer = 12)
+ @Column(name = "phone_number")
+ private String phoneNumber;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+
+ public void setPhoneNumber(String phoneNumber) {
+ this.phoneNumber = phoneNumber;
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java b/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java
new file mode 100644
index 0000000000..9357ae0ea6
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.rest;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * A class extending {@link Application} and annotated with @ApplicationPath is the Java EE 7 "no XML" approach to activating
+ * JAX-RS.
+ *
+ *
+ * Resources are served relative to the servlet path specified in the {@link ApplicationPath} annotation.
+ *
+ */
+@ApplicationPath("/rest")
+public class JaxRsActivator extends Application {
+ /* class body intentionally left blank */
+}
diff --git a/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java b/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java
new file mode 100644
index 0000000000..5a09e45591
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java
@@ -0,0 +1,185 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.rest;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.persistence.NoResultException;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import baeldung.data.MemberRepository;
+import baeldung.model.Member;
+import baeldung.service.MemberRegistration;
+
+/**
+ * JAX-RS Example
+ *
+ * This class produces a RESTful service to read/write the contents of the members table.
+ */
+@Path("/members")
+@RequestScoped
+public class MemberResourceRESTService {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private Validator validator;
+
+ @Inject
+ private MemberRepository repository;
+
+ @Inject
+ MemberRegistration registration;
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public List listAllMembers() {
+ return repository.findAllOrderedByName();
+ }
+
+ @GET
+ @Path("/{id:[0-9][0-9]*}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Member lookupMemberById(@PathParam("id") long id) {
+ Member member = repository.findById(id);
+ if (member == null) {
+ throw new WebApplicationException(Response.Status.NOT_FOUND);
+ }
+ return member;
+ }
+
+ /**
+ * Creates a new member from the values provided. Performs validation, and will return a JAX-RS response with either 200 ok,
+ * or with a map of fields, and related errors.
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createMember(Member member) {
+
+ Response.ResponseBuilder builder = null;
+
+ try {
+ // Validates member using bean validation
+ validateMember(member);
+
+ registration.register(member);
+
+ // Create an "ok" response
+ builder = Response.ok();
+ } catch (ConstraintViolationException ce) {
+ // Handle bean validation issues
+ builder = createViolationResponse(ce.getConstraintViolations());
+ } catch (ValidationException e) {
+ // Handle the unique constrain violation
+ Map responseObj = new HashMap<>();
+ responseObj.put("email", "Email taken");
+ builder = Response.status(Response.Status.CONFLICT).entity(responseObj);
+ } catch (Exception e) {
+ // Handle generic exceptions
+ Map responseObj = new HashMap<>();
+ responseObj.put("error", e.getMessage());
+ builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);
+ }
+
+ return builder.build();
+ }
+
+ /**
+ *
+ * Validates the given Member variable and throws validation exceptions based on the type of error. If the error is standard
+ * bean validation errors then it will throw a ConstraintValidationException with the set of the constraints violated.
+ *
+ *
+ * If the error is caused because an existing member with the same email is registered it throws a regular validation
+ * exception so that it can be interpreted separately.
+ *
+ *
+ * @param member Member to be validated
+ * @throws ConstraintViolationException If Bean Validation errors exist
+ * @throws ValidationException If member with the same email already exists
+ */
+ private void validateMember(Member member) throws ConstraintViolationException, ValidationException {
+ // Create a bean validator and check for issues.
+ Set> violations = validator.validate(member);
+
+ if (!violations.isEmpty()) {
+ throw new ConstraintViolationException(new HashSet>(violations));
+ }
+
+ // Check the uniqueness of the email address
+ if (emailAlreadyExists(member.getEmail())) {
+ throw new ValidationException("Unique Email Violation");
+ }
+ }
+
+ /**
+ * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and their message. This can then be used
+ * by clients to show violations.
+ *
+ * @param violations A set of violations that needs to be reported
+ * @return JAX-RS response containing all violations
+ */
+ private Response.ResponseBuilder createViolationResponse(Set> violations) {
+ log.fine("Validation completed. violations found: " + violations.size());
+
+ Map responseObj = new HashMap<>();
+
+ for (ConstraintViolation> violation : violations) {
+ responseObj.put(violation.getPropertyPath().toString(), violation.getMessage());
+ }
+
+ return Response.status(Response.Status.BAD_REQUEST).entity(responseObj);
+ }
+
+ /**
+ * Checks if a member with the same email address is already registered. This is the only way to easily capture the
+ * "@UniqueConstraint(columnNames = "email")" constraint from the Member class.
+ *
+ * @param email The email to check
+ * @return True if the email already exists, and false otherwise
+ */
+ public boolean emailAlreadyExists(String email) {
+ Member member = null;
+ try {
+ member = repository.findByEmail(email);
+ } catch (NoResultException e) {
+ // ignore
+ }
+ return member != null;
+ }
+}
diff --git a/deltaspike/src/main/java/baeldung/service/MemberRegistration.java b/deltaspike/src/main/java/baeldung/service/MemberRegistration.java
new file mode 100644
index 0000000000..ec65471622
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/service/MemberRegistration.java
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.service;
+
+import baeldung.data.MemberRepository;
+import baeldung.data.SecondaryPersistenceUnit;
+import baeldung.model.Member;
+import baeldung.model.QMember;
+
+import javax.ejb.Stateless;
+import javax.enterprise.event.Event;
+import javax.enterprise.inject.Default;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+@Stateless
+public class MemberRegistration {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private MemberRepository repository;
+
+ @Inject
+ private Event memberEventSrc;
+
+ @Inject
+ private Validator validator;
+
+ private void validateMember(Member member) throws ConstraintViolationException, ValidationException {
+ // Create a bean validator and check for issues.
+ Set> violations = validator.validate(member);
+
+ if (!violations.isEmpty()) {
+ throw new ConstraintViolationException(new HashSet>(violations));
+ }
+
+ // Check the uniqueness of the email address
+ if (emailAlreadyExists(member.getEmail())) {
+ throw new ValidationException("Unique Email Violation");
+ }
+ }
+
+
+ public void register(Member member) throws Exception {
+ log.info("Registering " + member.getName());
+ validateMember(member);
+ repository.save(member);
+ memberEventSrc.fire(member);
+ }
+
+ public boolean emailAlreadyExists(String email) {
+ Member member = null;
+ try {
+ member = repository.findByEmail(email);
+ } catch (NoResultException e) {
+ // ignore
+ }
+ return member != null;
+ }
+
+}
diff --git a/deltaspike/src/main/java/baeldung/util/Resources.java b/deltaspike/src/main/java/baeldung/util/Resources.java
new file mode 100644
index 0000000000..2cc1f235d7
--- /dev/null
+++ b/deltaspike/src/main/java/baeldung/util/Resources.java
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 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.
+ */
+package baeldung.util;
+
+import java.util.logging.Logger;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.faces.context.FacesContext;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+/**
+ * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans
+ *
+ *
+ * Example injection on a managed bean field:
+ *
+ *
+ *
+ * @Inject
+ * private EntityManager em;
+ *
+ */
+public class Resources {
+
+ @Produces
+ public Logger produceLog(InjectionPoint injectionPoint) {
+ return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
+ }
+
+ @Produces
+ @RequestScoped
+ public FacesContext produceFacesContext() {
+ return FacesContext.getCurrentInstance();
+ }
+
+}
diff --git a/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties b/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties
new file mode 100644
index 0000000000..a861ad729a
--- /dev/null
+++ b/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties
@@ -0,0 +1 @@
+globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
diff --git a/deltaspike/src/main/resources/META-INF/persistence.xml b/deltaspike/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..b68c2c1bb1
--- /dev/null
+++ b/deltaspike/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,21 @@
+
+
+
+ java:jboss/datasources/baeldung-jee7-seedDS
+
+
+
+
+
+
+ java:jboss/datasources/baeldung-jee7-seed-secondaryDS
+
+
+
+
+
+
diff --git a/deltaspike/src/main/resources/import.sql b/deltaspike/src/main/resources/import.sql
new file mode 100644
index 0000000000..154f4e9923
--- /dev/null
+++ b/deltaspike/src/main/resources/import.sql
@@ -0,0 +1,19 @@
+--
+-- JBoss, Home of Professional Open Source
+-- Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
+-- contributors by the @authors tag. See the copyright.txt in the
+-- distribution for a full listing of individual contributors.
+--
+-- Licensed 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
+-- http://www.apache.org/licenses/LICENSE-2.0
+-- 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.
+--
+
+-- You can use this file to load seed data into the database using SQL statements
+insert into Member (id, name, email, phone_number) values (0, 'John Smith', 'john.smith@mailinator.com', '2125551212')
diff --git a/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml
new file mode 100644
index 0000000000..1a8e350667
--- /dev/null
+++ b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ jdbc:h2:mem:baeldung-jee7-seed;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1
+ h2
+
+ sa
+ sa
+
+
+
+
diff --git a/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml
new file mode 100644
index 0000000000..c4c9afb2e0
--- /dev/null
+++ b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+ jdbc:h2:mem:baeldung-jee7-seed;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1
+ h2
+
+ sa
+ sa
+
+
+
+
diff --git a/deltaspike/src/main/webapp/WEB-INF/beans.xml b/deltaspike/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000000..0090177eb7
--- /dev/null
+++ b/deltaspike/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/deltaspike/src/main/webapp/WEB-INF/faces-config.xml b/deltaspike/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000000..26cf98b669
--- /dev/null
+++ b/deltaspike/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml b/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml
new file mode 100644
index 0000000000..2f001f8626
--- /dev/null
+++ b/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml
@@ -0,0 +1,55 @@
+
+
+
+
+ baeldung-jee7-seed
+
+
+
+
+