diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000..df7825df61
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/EmailSenderService.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/EmailSenderService.java
new file mode 100644
index 0000000000..a7f9d95045
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/EmailSenderService.java
@@ -0,0 +1,10 @@
+package com.ossez.anonymousclass;
+
+public class EmailSenderService implements SenderService {
+
+ @Override
+ public String callSender(Sender sender) {
+ return sender.send("Email Notification");
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/Sender.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/Sender.java
new file mode 100644
index 0000000000..9b280e0f15
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/Sender.java
@@ -0,0 +1,7 @@
+package com.ossez.anonymousclass;
+
+public interface Sender {
+
+ String send(final String message);
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SenderService.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SenderService.java
new file mode 100644
index 0000000000..da30102bd6
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SenderService.java
@@ -0,0 +1,7 @@
+package com.ossez.anonymousclass;
+
+public interface SenderService {
+
+ String callSender(Sender sender);
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SmsSenderService.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SmsSenderService.java
new file mode 100644
index 0000000000..ab44b28df5
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/anonymousclass/SmsSenderService.java
@@ -0,0 +1,10 @@
+package com.ossez.anonymousclass;
+
+public class SmsSenderService implements SenderService {
+
+ @Override
+ public String callSender(Sender sender) {
+ return sender.send("SMS Notification");
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/java8/lambda/serialization/SerializableLambdaExpression.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/java8/lambda/serialization/SerializableLambdaExpression.java
new file mode 100644
index 0000000000..0122ac40b4
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/java8/lambda/serialization/SerializableLambdaExpression.java
@@ -0,0 +1,10 @@
+package com.ossez.java8.lambda.serialization;
+
+import java.io.Serializable;
+
+public class SerializableLambdaExpression {
+ public static Object getLambdaExpressionObject() {
+ Runnable r = (Runnable & Serializable) () -> System.out.println("please serialize this message");
+ return r;
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/data/User.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/data/User.java
new file mode 100644
index 0000000000..393fbee6ae
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/data/User.java
@@ -0,0 +1,59 @@
+package com.ossez.suppliercallable.data;
+
+import java.time.LocalDate;
+
+public class User {
+
+ private String name;
+ private String surname;
+ private LocalDate birthDate;
+ private Integer age;
+ private Boolean canDriveACar = false;
+
+ public User(String name, String surname, LocalDate birthDate) {
+ this.name = name;
+ this.surname = surname;
+ this.birthDate = birthDate;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+
+ public LocalDate getBirthDate() {
+ return birthDate;
+ }
+
+ public void setBirthDate(LocalDate birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public Boolean getCanDriveACar() {
+ return canDriveACar;
+ }
+
+ public void setCanDriveACar(Boolean canDriveACar) {
+ this.canDriveACar = canDriveACar;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/Service.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/Service.java
new file mode 100644
index 0000000000..0a8353efad
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/Service.java
@@ -0,0 +1,8 @@
+package com.ossez.suppliercallable.service;
+
+import com.ossez.suppliercallable.data.User;
+
+public interface Service {
+
+ User execute(User user);
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/AgeCalculatorCallable.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/AgeCalculatorCallable.java
new file mode 100644
index 0000000000..0fc3e4b35c
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/AgeCalculatorCallable.java
@@ -0,0 +1,20 @@
+package com.ossez.suppliercallable.service.callable;
+
+import java.time.LocalDate;
+import java.time.Period;
+import java.util.concurrent.Callable;
+
+public class AgeCalculatorCallable implements Callable {
+
+ private final LocalDate birthDate;
+
+ @Override
+ public Integer call() throws Exception {
+ return Period.between(birthDate, LocalDate.now())
+ .getYears();
+ }
+
+ public AgeCalculatorCallable(LocalDate birthDate) {
+ this.birthDate = birthDate;
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CallableServiceImpl.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CallableServiceImpl.java
new file mode 100644
index 0000000000..36633c893d
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CallableServiceImpl.java
@@ -0,0 +1,31 @@
+package com.ossez.suppliercallable.service.callable;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import com.ossez.suppliercallable.data.User;
+import com.ossez.suppliercallable.service.Service;
+
+public class CallableServiceImpl implements Service {
+
+ @Override
+ public User execute(User user) {
+ ExecutorService executorService = Executors.newCachedThreadPool();
+
+ try {
+ Future ageFuture = executorService.submit(new AgeCalculatorCallable(user.getBirthDate()));
+ Integer age = ageFuture.get();
+ Future canDriveACarFuture = executorService.submit(new CarDriverValidatorCallable(age));
+ Boolean canDriveACar = canDriveACarFuture.get();
+ user.setAge(age);
+ user.setCanDriveACar(canDriveACar);
+ } catch (ExecutionException | InterruptedException e) {
+ throw new RuntimeException(e.getCause());
+ }
+
+ return user;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CarDriverValidatorCallable.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CarDriverValidatorCallable.java
new file mode 100644
index 0000000000..813ac9c86a
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/callable/CarDriverValidatorCallable.java
@@ -0,0 +1,17 @@
+package com.ossez.suppliercallable.service.callable;
+
+import java.util.concurrent.Callable;
+
+public class CarDriverValidatorCallable implements Callable {
+
+ private final Integer age;
+
+ @Override
+ public Boolean call() throws Exception {
+ return age > 18;
+ }
+
+ public CarDriverValidatorCallable(Integer age) {
+ this.age = age;
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/supplier/SupplierServiceImpl.java b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/supplier/SupplierServiceImpl.java
new file mode 100644
index 0000000000..5e5ea3a82d
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/ossez/suppliercallable/service/supplier/SupplierServiceImpl.java
@@ -0,0 +1,26 @@
+package com.ossez.suppliercallable.service.supplier;
+
+import java.time.LocalDate;
+import java.time.Period;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.ossez.suppliercallable.data.User;
+import com.ossez.suppliercallable.service.Service;
+
+public class SupplierServiceImpl implements Service {
+ @Override
+ public User execute(User user) {
+ ExecutorService executorService = Executors.newCachedThreadPool();
+ CompletableFuture ageFut = CompletableFuture.supplyAsync(() -> Period.between(user.getBirthDate(), LocalDate.now())
+ .getYears(), executorService)
+ .exceptionally((throwable -> null));
+ CompletableFuture canDriveACarFut = ageFut.thenComposeAsync(age -> CompletableFuture.supplyAsync(() -> age > 18, executorService))
+ .exceptionally((ex) -> false);
+ user.setAge(ageFut.join());
+ user.setCanDriveACar(canDriveACarFut.join());
+ return user;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/ossez/anonymousclass/AnonymousClassToLambdaIntegrationTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/anonymousclass/AnonymousClassToLambdaIntegrationTest.java
new file mode 100644
index 0000000000..2579b4ba86
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/anonymousclass/AnonymousClassToLambdaIntegrationTest.java
@@ -0,0 +1,38 @@
+package com.ossez.anonymousclass;
+
+import static org.junit.Assert.assertEquals;
+
+import com.ossez.anonymousclass.EmailSenderService;
+import com.ossez.anonymousclass.Sender;
+import com.ossez.anonymousclass.SenderService;
+import com.ossez.anonymousclass.SmsSenderService;
+import org.junit.Test;
+
+public class AnonymousClassToLambdaIntegrationTest {
+
+ @Test
+ public void whenPassingAnonymousClass_thenSuccess() {
+ final SenderService emailSenderService = new EmailSenderService();
+
+ final String emailNotif = emailSenderService.callSender(new Sender() {
+ @Override
+ public String send(String message) {
+ return message;
+ }
+ });
+
+ assertEquals(emailNotif, "Email Notification");
+ }
+
+ @Test
+ public void whenPassingLambdaExpression_thenSuccess() {
+ final SenderService smsSenderService = new SmsSenderService();
+
+ final String smsNotif = smsSenderService.callSender((String message) -> {
+ return message;
+ });
+
+ assertEquals(smsNotif, "SMS Notification");
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/ossez/java8/lambda/serialization/LambdaSerializationUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/java8/lambda/serialization/LambdaSerializationUnitTest.java
new file mode 100644
index 0000000000..faf7cf3bf3
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/java8/lambda/serialization/LambdaSerializationUnitTest.java
@@ -0,0 +1,79 @@
+package com.ossez.java8.lambda.serialization;
+
+import com.ossez.java8.lambda.serialization.NotSerializableLambdaExpression;
+import com.ossez.java8.lambda.serialization.SerializableLambdaExpression;
+import org.junit.Test;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import static org.junit.Assert.assertTrue;
+
+public class LambdaSerializationUnitTest {
+ @Test(expected = NotSerializableException.class)
+ public void givenRunnable_whenNoCapturing_thenSerializationFailed() throws IOException, ClassNotFoundException {
+ Object obj = NotSerializableLambdaExpression.getLambdaExpressionObject();
+ writeAndReadObject(obj, Runnable.class);
+ }
+
+ @Test
+ public void givenIntersectionType_whenNoCapturing_thenSerializationSuccess() throws IOException, ClassNotFoundException {
+ Object obj = SerializableLambdaExpression.getLambdaExpressionObject();
+ writeAndReadObject(obj, Runnable.class);
+ }
+
+ @Test
+ public void givenSerializableRunnable_whenNoCapturing_thenSerializationSuccess() throws IOException, ClassNotFoundException {
+ SerializableRunnable obj = () -> System.out.println("please serialize this message");
+ writeAndReadObject(obj, SerializableRunnable.class);
+ }
+
+ @Test
+ public void givenSerializableFunction_whenNoCapturing_thenSerializationSuccess() throws IOException, ClassNotFoundException {
+ SerializableFunction obj = message -> String.format("Hello %s", message);
+ writeAndReadObject(obj, SerializableFunction.class);
+ }
+
+ @Test
+ public void givenSerializableConsumer_whenNoCapturing_thenSerializationSuccess() throws IOException, ClassNotFoundException {
+ SerializableConsumer obj = message -> System.out.println(message);
+ writeAndReadObject(obj, SerializableConsumer.class);
+ }
+
+ @Test(expected = NotSerializableException.class)
+ public void givenSerializableConsumer_whenCapturingNotSerializable_thenSerializationFailed() throws IOException, ClassNotFoundException {
+ SerializableConsumer obj = System.out::println;
+ writeAndReadObject(obj, SerializableConsumer.class);
+ }
+
+ private void writeAndReadObject(Object obj, Class clazz) throws IOException, ClassNotFoundException {
+ File file = Files.createTempFile("lambda", "ser").toFile();
+ try (
+ FileOutputStream fos = new FileOutputStream(file);
+ ObjectOutputStream oos = new ObjectOutputStream(fos)
+ ) {
+ oos.writeObject(obj);
+ }
+
+ try (
+ FileInputStream fis = new FileInputStream(file);
+ ObjectInputStream ois = new ObjectInputStream(fis)
+ ) {
+ Object newObj = ois.readObject();
+ boolean isInstance = clazz.isInstance(newObj);
+
+ assertTrue(isInstance);
+ }
+ }
+
+ interface SerializableRunnable extends Runnable, Serializable {
+ }
+
+ interface SerializableFunction extends Function, Serializable {
+ }
+
+ interface SerializableConsumer extends Consumer, Serializable {
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/ossez/suppliercallable/CallableSupplierUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/suppliercallable/CallableSupplierUnitTest.java
new file mode 100644
index 0000000000..08134b5781
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/ossez/suppliercallable/CallableSupplierUnitTest.java
@@ -0,0 +1,64 @@
+package com.ossez.suppliercallable;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.time.LocalDate;
+import java.time.Month;
+import org.junit.jupiter.api.Test;
+import com.ossez.suppliercallable.data.User;
+import com.ossez.suppliercallable.service.Service;
+import com.ossez.suppliercallable.service.callable.CallableServiceImpl;
+import com.ossez.suppliercallable.service.supplier.SupplierServiceImpl;
+
+public class CallableSupplierUnitTest {
+
+ @Test
+ void givenCallableService_whenUserIsAnAdult_thenCanDriveACar() {
+ User user = new User("Test", "Test", LocalDate.of(2000, Month.JANUARY, 19));
+ Service service = new CallableServiceImpl();
+ service.execute(user);
+ assertEquals(true, user.getCanDriveACar());
+ }
+
+ @Test
+ void givenCallableService_whenUserIsNotAnAdult_thenCannotDriveACar() {
+ User user = new User("Test", "Test", LocalDate.of(2010, Month.JANUARY, 19));
+ Service service = new CallableServiceImpl();
+ service.execute(user);
+ assertEquals(false, user.getCanDriveACar());
+ }
+
+ @Test
+ void givenCallableService_whenBirthDateIsNull_thenShouldThrowAnException() {
+ User user = new User("Test", "Test", null);
+ Service service = new CallableServiceImpl();
+ assertThrows(RuntimeException.class, () -> service.execute(user));
+ }
+
+ @Test
+ void givenSupplierService_whenUserIsAnAdult_thenCanDriveACar() {
+ User user = new User("Test", "Test", LocalDate.of(2000, Month.JANUARY, 19));
+ Service service = new SupplierServiceImpl();
+ service.execute(user);
+ assertEquals(true, user.getCanDriveACar());
+ }
+
+ @Test
+ void givenSupplierService_whenUserIsNotAnAdult_thenCannotDriveACar() {
+ User user = new User("Test", "Test", LocalDate.of(2010, Month.JANUARY, 19));
+ Service service = new SupplierServiceImpl();
+ service.execute(user);
+ assertEquals(false, user.getCanDriveACar());
+ }
+
+ @Test
+ void givenSupplierService_whenBirthDateIsNull_thenCannotDriveACarAndAgeIsNull() {
+ User user = new User("Test", "Test", null);
+ Service service = new SupplierServiceImpl();
+ service.execute(user);
+ assertEquals(false, user.getCanDriveACar());
+ assertNull(user.getBirthDate());
+ }
+
+}